From 806c1851be9f36d47cb77f409d55ece6a5f6a65f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 23 Jan 2015 16:09:45 -0800 Subject: [PATCH 01/20] add save/restore of gravity --- examples/controllers/hydra/hydraGrab.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/controllers/hydra/hydraGrab.js b/examples/controllers/hydra/hydraGrab.js index 4d0b873fd2..7b65db94a3 100644 --- a/examples/controllers/hydra/hydraGrab.js +++ b/examples/controllers/hydra/hydraGrab.js @@ -74,6 +74,7 @@ function controller(wichSide) { this.positionAtGrab; this.rotationAtGrab; + this.gravityAtGrab; this.modelPositionAtGrab; this.rotationAtGrab; this.jointsIntersectingFromStart = []; @@ -125,6 +126,7 @@ function controller(wichSide) { this.entityID = entityID; this.modelURL = properties.modelURL; + this.oldModelPosition = properties.position; this.oldModelRotation = properties.rotation; this.oldModelHalfDiagonal = Vec3.length(properties.dimensions) / 2.0; @@ -133,6 +135,10 @@ function controller(wichSide) { this.rotationAtGrab = this.rotation; this.modelPositionAtGrab = properties.position; this.rotationAtGrab = properties.rotation; + this.gravityAtGrab = properties.gravity; + + Entities.editEntity(entityID, { gravity: { x: 0, y: 0, z: 0 }, velocity: { x: 0, y: 0, z: 0 } }); + this.jointsIntersectingFromStart = []; for (var i = 0; i < jointList.length; i++) { var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); @@ -145,6 +151,9 @@ function controller(wichSide) { this.release = function () { if (this.grabbing) { + + Entities.editEntity(entityID, { gravity: this.gravityAtGrab }); + jointList = MyAvatar.getJointNames(); var closestJointIndex = -1; From 901044fc537a0dfe7bfdc1c4cb8175d9f238aede Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sun, 25 Jan 2015 21:40:16 -0800 Subject: [PATCH 02/20] First version, popcorn machine --- examples/controllers/hydra/gun.js | 4 +- examples/controllers/hydra/hydraGrab.js | 8 +- examples/controllers/hydra/paddleBall.js | 20 ++- examples/popcorn.js | 182 +++++++++++++++++++++++ 4 files changed, 201 insertions(+), 13 deletions(-) create mode 100644 examples/popcorn.js diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index 0c0740e12b..549be9bccb 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -304,10 +304,12 @@ function makePlatform(gravity, scale, size) { } function entityCollisionWithEntity(entity1, entity2, collision) { - + cTime = new Date().getTime(); + //print("Collision at " + cTime); if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) && ((entity2.id == bulletID.id) || (entity2.id == targetID.id))) { score++; + print("Hit Target!"); if (showScore) { Overlays.editOverlay(text, { text: "Score: " + score } ); } diff --git a/examples/controllers/hydra/hydraGrab.js b/examples/controllers/hydra/hydraGrab.js index 8450b15758..ff51583599 100644 --- a/examples/controllers/hydra/hydraGrab.js +++ b/examples/controllers/hydra/hydraGrab.js @@ -14,7 +14,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/entityPropertyDialogBox.js"); +Script.include("../../libraries/entityPropertyDialogBox.js"); var entityPropertyDialogBox = EntityPropertyDialogBox; var LASER_WIDTH = 4; @@ -23,8 +23,8 @@ var LASER_LENGTH_FACTOR = 500; var MIN_ANGULAR_SIZE = 2; var MAX_ANGULAR_SIZE = 45; -var allowLargeModels = false; -var allowSmallModels = false; +var allowLargeModels = true; +var allowSmallModels = true; var wantEntityGlow = false; var LEFT = 0; @@ -152,7 +152,7 @@ function controller(wichSide) { this.release = function () { if (this.grabbing) { - Entities.editEntity(entityID, { gravity: this.gravityAtGrab }); + Entities.editEntity(this.entityID, { gravity: this.gravityAtGrab }); jointList = MyAvatar.getJointNames(); diff --git a/examples/controllers/hydra/paddleBall.js b/examples/controllers/hydra/paddleBall.js index 85b025e4cd..a6b0a52c5f 100644 --- a/examples/controllers/hydra/paddleBall.js +++ b/examples/controllers/hydra/paddleBall.js @@ -16,12 +16,14 @@ var PADDLE_THICKNESS = 0.06; var PADDLE_COLOR = { red: 184, green: 134, blue: 11 }; var BALL_COLOR = { red: 255, green: 0, blue: 0 }; var LINE_COLOR = { red: 255, green: 255, blue: 0 }; -var PADDLE_OFFSET = { x: 0.05, y: 0.0, z: 0.0 }; +var PADDLE_BOX_OFFSET = { x: 0.05, y: 0.0, z: 0.0 }; +var HOLD_POSITION_OFFSET = { x: -0.2, y: 0.0, z: -0.25 }; +var PADDLE_ORIENTATION = Quat.fromPitchYawRollDegrees(0,0,0); var GRAVITY = 0.0; var SPRING_FORCE = 15.0; var lastSoundTime = 0; var gameOn = false; -var leftHanded = false; +var leftHanded = true; var controllerID; if (leftHanded) { @@ -73,7 +75,7 @@ function createEntities() { modelURL = "http://public.highfidelity.io/models/attachments/pong_paddle.fbx"; paddleModel = Entities.addEntity( { type: "Model", - position: Vec3.sum(Controller.getSpatialControlPosition(controllerID), PADDLE_OFFSET), + position: Vec3.sum(Controller.getSpatialControlPosition(controllerID), PADDLE_BOX_OFFSET), dimensions: { x: PADDLE_SIZE * 1.5, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 1.25 }, color: PADDLE_COLOR, gravity: { x: 0, y: 0, z: 0 }, @@ -120,18 +122,20 @@ function update(deltaTime) { if (!ball.isKnownID) { ball = Entities.identifyEntity(ball); } else { + var paddleWorldOrientation = Quat.multiply(Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)), PADDLE_ORIENTATION); + var holdPosition = Vec3.sum(palmPosition, Vec3.multiplyQbyV(paddleWorldOrientation, HOLD_POSITION_OFFSET)); var props = Entities.getEntityProperties(ball); - var spring = Vec3.subtract(palmPosition, props.position); - var paddleWorldOrientation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)); + var spring = Vec3.subtract(holdPosition, props.position); var springLength = Vec3.length(spring); + spring = Vec3.normalize(spring); var ballVelocity = Vec3.sum(props.velocity, Vec3.multiply(springLength * SPRING_FORCE * deltaTime, spring)); Entities.editEntity(ball, { velocity: ballVelocity }); - Overlays.editOverlay(line, { start: props.position, end: palmPosition }); - Entities.editEntity(paddle, { position: palmPosition, + Overlays.editOverlay(line, { start: props.position, end: holdPosition }); + Entities.editEntity(paddle, { position: holdPosition, velocity: Controller.getSpatialControlVelocity(controllerID), rotation: paddleWorldOrientation }); - Entities.editEntity(paddleModel, { position: Vec3.sum(palmPosition, Vec3.multiplyQbyV(paddleWorldOrientation, PADDLE_OFFSET)), + Entities.editEntity(paddleModel, { position: Vec3.sum(holdPosition, Vec3.multiplyQbyV(paddleWorldOrientation, PADDLE_BOX_OFFSET)), velocity: Controller.getSpatialControlVelocity(controllerID), rotation: paddleWorldOrientation }); } diff --git a/examples/popcorn.js b/examples/popcorn.js new file mode 100644 index 0000000000..567953ac60 --- /dev/null +++ b/examples/popcorn.js @@ -0,0 +1,182 @@ +// +// popcorn.js +// examples +// +// Created by Philip Rosedale on January 25, 2014 +// Copyright 2015 High Fidelity, Inc. +// +// Creates a bunch of physical balls trapped in a box with a rotating wall in the middle that smacks them around, +// and a periodic 'pop' force that shoots them into the air. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var BALL_SIZE = 0.07; +var WALL_THICKNESS = 0.10; +var SCALE = 1.0; + +var GRAVITY = -1.0; +var LIFETIME = 600; +var DAMPING = 0.50; + +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(SCALE * 3.0, Quat.getFront(Camera.getOrientation()))); + +var floor = Entities.addEntity( + { type: "Box", + position: Vec3.subtract(center, { x: 0, y: SCALE / 2.0, z: 0 }), + dimensions: { x: SCALE, y: WALL_THICKNESS, z: SCALE }, + color: { red: 0, green: 255, blue: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + lifetime: LIFETIME }); + +var ceiling = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: 0, y: SCALE / 2.0, z: 0 }), + dimensions: { x: SCALE, y: WALL_THICKNESS, z: SCALE }, + color: { red: 128, green: 128, blue: 128 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var wall1 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: SCALE / 2.0, y: 0, z: 0 }), + dimensions: { x: WALL_THICKNESS, y: SCALE, z: SCALE }, + color: { red: 0, green: 255, blue: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: false, + lifetime: LIFETIME }); + +var wall2 = Entities.addEntity( + { type: "Box", + position: Vec3.subtract(center, { x: SCALE / 2.0, y: 0, z: 0 }), + dimensions: { x: WALL_THICKNESS, y: SCALE, z: SCALE }, + color: { red: 0, green: 255, blue: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: false, + lifetime: LIFETIME }); + +var wall3 = Entities.addEntity( + { type: "Box", + position: Vec3.subtract(center, { x: 0, y: 0, z: SCALE / 2.0 }), + dimensions: { x: SCALE, y: SCALE, z: WALL_THICKNESS }, + color: { red: 0, green: 255, blue: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: false, + lifetime: LIFETIME }); + +var wall4 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: 0, y: 0, z: SCALE / 2.0 }), + dimensions: { x: SCALE, y: SCALE, z: WALL_THICKNESS }, + color: { red: 0, green: 255, blue: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: false, + lifetime: LIFETIME }); + +var corner1 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: -SCALE / 2.0, y: 0, z: SCALE / 2.0 }), + dimensions: { x: WALL_THICKNESS, y: SCALE, z: WALL_THICKNESS }, + color: { red: 128, green: 128, blue: 128 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var corner2 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: -SCALE / 2.0, y: 0, z: -SCALE / 2.0 }), + dimensions: { x: WALL_THICKNESS, y: SCALE, z: WALL_THICKNESS }, + color: { red: 128, green: 128, blue: 128 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var corner3 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: SCALE / 2.0, y: 0, z: SCALE / 2.0 }), + dimensions: { x: WALL_THICKNESS, y: SCALE, z: WALL_THICKNESS }, + color: { red: 128, green: 128, blue: 128 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var corner4 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: SCALE / 2.0, y: 0, z: -SCALE / 2.0 }), + dimensions: { x: WALL_THICKNESS, y: SCALE, z: WALL_THICKNESS }, + color: { red: 128, green: 128, blue: 128 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var spinner = Entities.addEntity( + { type: "Box", + position: center, + dimensions: { x: SCALE / 1.5, y: SCALE / 3.0, z: SCALE / 8.0 }, + color: { red: 255, green: 0, blue: 0 }, + angularVelocity: { x: 0, y: 360, z: 0 }, + angularDamping: 0.0, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var NUM_BALLS = 70; + +balls = []; + +for (var i = 0; i < NUM_BALLS; i++) { + balls.push(Entities.addEntity( + { type: "Sphere", + position: { x: center.x + (Math.random() - 0.5) * (SCALE - BALL_SIZE - WALL_THICKNESS), + y: center.y + (Math.random() - 0.5) * (SCALE - BALL_SIZE - WALL_THICKNESS) , + z: center.z + (Math.random() - 0.5) * (SCALE - BALL_SIZE - WALL_THICKNESS) }, + dimensions: { x: BALL_SIZE, y: BALL_SIZE, z: BALL_SIZE }, + color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 }, + gravity: { x: 0, y: GRAVITY, z: 0 }, + ignoreCollisions: false, + damping: DAMPING, + lifetime: LIFETIME, + collisionsWillMove: true })); +} + +var VEL_MAG = 2.0; +var CHANCE_OF_POP = 0.007; // 0.01; +function update(deltaTime) { + for (var i = 0; i < NUM_BALLS; i++) { + if (Math.random() < CHANCE_OF_POP) { + Entities.editEntity(balls[i], { velocity: { x: (Math.random() - 0.5) * VEL_MAG, y: Math.random() * VEL_MAG, z: (Math.random() - 0.5) * VEL_MAG }}); + } + } + +} + + +function scriptEnding() { + Entities.deleteEntity(wall1); + Entities.deleteEntity(wall2); + Entities.deleteEntity(wall3); + Entities.deleteEntity(wall4); + Entities.deleteEntity(corner1); + Entities.deleteEntity(corner2); + Entities.deleteEntity(corner3); + Entities.deleteEntity(corner4); + Entities.deleteEntity(floor); + Entities.deleteEntity(ceiling); + Entities.deleteEntity(spinner); + + for (var i = 0; i < NUM_BALLS; i++) { + Entities.deleteEntity(balls[i]); + } +} + +Script.scriptEnding.connect(scriptEnding); +Script.update.connect(update); \ No newline at end of file From 67632fa589399da975762d83a0dd72abe5f9ff6c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sun, 25 Jan 2015 21:51:12 -0800 Subject: [PATCH 03/20] remove debug --- examples/controllers/hydra/gun.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index 549be9bccb..bd6cf6f9f1 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -304,8 +304,6 @@ function makePlatform(gravity, scale, size) { } function entityCollisionWithEntity(entity1, entity2, collision) { - cTime = new Date().getTime(); - //print("Collision at " + cTime); if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) && ((entity2.id == bulletID.id) || (entity2.id == targetID.id))) { score++; From 09527cc2648fd074eded39814359c18227a1ca49 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sun, 25 Jan 2015 21:52:08 -0800 Subject: [PATCH 04/20] hit target --- examples/controllers/hydra/gun.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index bd6cf6f9f1..b8fc15d75f 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -307,7 +307,6 @@ function entityCollisionWithEntity(entity1, entity2, collision) { if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) && ((entity2.id == bulletID.id) || (entity2.id == targetID.id))) { score++; - print("Hit Target!"); if (showScore) { Overlays.editOverlay(text, { text: "Score: " + score } ); } From bfdbe2e675b92a2fcc4341b5098889612e2a2254 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 26 Jan 2015 16:25:07 -0800 Subject: [PATCH 05/20] Detach both guns on shutdown --- examples/controllers/hydra/gun.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index b8fc15d75f..b5d015637c 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -500,6 +500,7 @@ function scriptEnding() { Overlays.deleteOverlay(pointer[1]); Overlays.deleteOverlay(text); MyAvatar.detachOne(gunModel); + MyAvatar.detachOne(gunModel); clearPose(); } From a1babe3a333eed514a1d620e1d2c3fc5a0060c73 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 26 Jan 2015 17:20:31 -0800 Subject: [PATCH 06/20] Put paddle exactly in hand, add animation of fingers gripping paddle --- examples/controllers/hydra/paddleBall.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/examples/controllers/hydra/paddleBall.js b/examples/controllers/hydra/paddleBall.js index a6b0a52c5f..8c9af68498 100644 --- a/examples/controllers/hydra/paddleBall.js +++ b/examples/controllers/hydra/paddleBall.js @@ -10,6 +10,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + +hitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-ballhitsandcatches/billiards/collision1.wav"); +var rightHandAnimation = HIFI_PUBLIC_BUCKET + "animations/RightHandAnimPhilip.fbx"; +var leftHandAnimation = HIFI_PUBLIC_BUCKET + "animations/LeftHandAnimPhilip.fbx"; + var BALL_SIZE = 0.08; var PADDLE_SIZE = 0.20; var PADDLE_THICKNESS = 0.06; @@ -17,7 +23,8 @@ var PADDLE_COLOR = { red: 184, green: 134, blue: 11 }; var BALL_COLOR = { red: 255, green: 0, blue: 0 }; var LINE_COLOR = { red: 255, green: 255, blue: 0 }; var PADDLE_BOX_OFFSET = { x: 0.05, y: 0.0, z: 0.0 }; -var HOLD_POSITION_OFFSET = { x: -0.2, y: 0.0, z: -0.25 }; + +var HOLD_POSITION_OFFSET = { x: -0.15, y: 0.05, z: -0.05 }; var PADDLE_ORIENTATION = Quat.fromPitchYawRollDegrees(0,0,0); var GRAVITY = 0.0; var SPRING_FORCE = 15.0; @@ -33,8 +40,7 @@ if (leftHanded) { } -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -hitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-ballhitsandcatches/billiards/collision1.wav"); + var screenSize = Controller.getViewportDimensions(); var offButton = Overlays.addOverlay("image", { @@ -92,6 +98,9 @@ function createEntities() { alpha: 1, visible: true, lineWidth: 2 }); + + MyAvatar.stopAnimation(leftHanded ? leftHandAnimation: rightHandAnimation); + MyAvatar.startAnimation(leftHanded ? leftHandAnimation: rightHandAnimation, 15.0, 1.0, false, true, 0.0, 6); } function deleteEntities() { @@ -99,6 +108,7 @@ function deleteEntities() { Entities.deleteEntity(paddle); Entities.deleteEntity(paddleModel); Overlays.deleteOverlay(line); + MyAvatar.stopAnimation(leftHanded ? leftHandAnimation: rightHandAnimation); } function update(deltaTime) { @@ -123,7 +133,9 @@ function update(deltaTime) { ball = Entities.identifyEntity(ball); } else { var paddleWorldOrientation = Quat.multiply(Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)), PADDLE_ORIENTATION); - var holdPosition = Vec3.sum(palmPosition, Vec3.multiplyQbyV(paddleWorldOrientation, HOLD_POSITION_OFFSET)); + var holdPosition = Vec3.sum(leftHanded ? MyAvatar.getLeftPalmPosition() : MyAvatar.getRightPalmPosition(), + Vec3.multiplyQbyV(paddleWorldOrientation, HOLD_POSITION_OFFSET)); + var props = Entities.getEntityProperties(ball); var spring = Vec3.subtract(holdPosition, props.position); var springLength = Vec3.length(spring); @@ -168,6 +180,7 @@ function scriptEnding() { deleteEntities(); } Overlays.deleteOverlay(offButton); + MyAvatar.stopAnimation(leftHanded ? leftHandAnimation: rightHandAnimation); } Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); From e0c9af853c6e132979df2c0c7c931aab94d009f6 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 26 Jan 2015 20:19:46 -0800 Subject: [PATCH 07/20] remove 'STICKS' mode, add drop line to better tell what something you are holding is above --- examples/controllers/hydra/hydraGrab.js | 173 +++++++++--------------- 1 file changed, 67 insertions(+), 106 deletions(-) diff --git a/examples/controllers/hydra/hydraGrab.js b/examples/controllers/hydra/hydraGrab.js index 2ebe4eb9b6..9f250f9208 100644 --- a/examples/controllers/hydra/hydraGrab.js +++ b/examples/controllers/hydra/hydraGrab.js @@ -28,13 +28,12 @@ var RIGHT = 1; var jointList = MyAvatar.getJointNames(); -var STICKS = 0; -var MAPPED = 1; -var mode = STICKS; +var LASER_WIDTH = 3; +var LASER_COLOR = { red: 50, green: 150, blue: 200 }; +var DROP_COLOR = { red: 200, green: 200, blue: 200 }; +var DROP_WIDTH = 4; +var DROP_DISTANCE = 5.0; -var LASER_WIDTH = 4; -var LASER_COLOR = [{ red: 200, green: 150, blue: 50 }, // STICKS - { red: 50, green: 150, blue: 200 }]; // MAPPED var LASER_LENGTH_FACTOR = 500; var lastAccurateIntersection = null; @@ -115,13 +114,21 @@ function controller(wichSide) { this.laser = Overlays.addOverlay("line3d", { start: { x: 0, y: 0, z: 0 }, end: { x: 0, y: 0, z: 0 }, - color: LASER_COLOR[mode], + color: LASER_COLOR, alpha: 1, visible: false, lineWidth: LASER_WIDTH, anchor: "MyAvatar" }); + this.dropLine = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: DROP_COLOR, + alpha: 1, + visible: false, + lineWidth: DROP_WIDTH }); + this.guideScale = 0.02; this.ball = Overlays.addOverlay("sphere", { position: { x: 0, y: 0, z: 0 }, @@ -180,6 +187,7 @@ function controller(wichSide) { } } this.showLaser(false); + Overlays.editOverlay(this.dropLine, { visible: true }); } this.release = function () { @@ -225,6 +233,8 @@ function controller(wichSide) { Entities.deleteEntity(this.entityID); } } + + Overlays.editOverlay(this.dropLine, { visible: false }); } this.grabbing = false; @@ -297,7 +307,6 @@ function controller(wichSide) { end: endPosition }); - Overlays.editOverlay(this.ball, { position: endPosition }); @@ -309,7 +318,7 @@ function controller(wichSide) { start: Vec3.sum(endPosition, Vec3.multiply(this.up, 2 * this.guideScale)), end: Vec3.sum(endPosition, Vec3.multiply(this.up, -2 * this.guideScale)) }); - this.showLaser(!this.grabbing || mode == STICKS); + this.showLaser(!this.grabbing); if (this.glowedIntersectingModel.isKnownID) { Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.0 }); @@ -352,49 +361,33 @@ function controller(wichSide) { } var newPosition; var newRotation; + + var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); + var d = Vec3.dot(forward, MyAvatar.position); - switch (mode) { - case STICKS: - newPosition = Vec3.sum(this.palmPosition, - Vec3.multiply(this.front, this.x)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.up, this.y)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.right, this.z)); + var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; + var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; + var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.oldRotation)); - newRotation = Quat.multiply(newRotation, - this.oldModelRotation); - break; - case MAPPED: - var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); - var d = Vec3.dot(forward, MyAvatar.position); - - var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; - var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; - var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); - - if (factor2 < 0) { - factor2 = 0; - } - if (factor1 <= 0) { - factor1 = 1; - factor2 = 1; - } - - newPosition = Vec3.sum(this.modelPositionAtGrab, - Vec3.multiply(vector, - factor2 / factor1)); - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.rotationAtGrab)); - newRotation = Quat.multiply(newRotation, newRotation); - newRotation = Quat.multiply(newRotation, - this.modelRotationAtGrab); - break; + if (factor2 < 0) { + factor2 = 0; } + if (factor1 <= 0) { + factor1 = 1; + factor2 = 1; + } + + newPosition = Vec3.sum(this.modelPositionAtGrab, + Vec3.multiply(vector, + factor2 / factor1)); + + newRotation = Quat.multiply(this.rotation, + Quat.inverse(this.rotationAtGrab)); + newRotation = Quat.multiply(newRotation, newRotation); + newRotation = Quat.multiply(newRotation, + this.modelRotationAtGrab); + + Entities.editEntity(this.entityID, { position: newPosition, rotation: newRotation @@ -402,6 +395,8 @@ function controller(wichSide) { this.oldModelRotation = newRotation; this.oldModelPosition = newPosition; + Overlays.editOverlay(this.dropLine, { start: newPosition, end: Vec3.sum(newPosition, { x: 0, y: -DROP_DISTANCE, z: 0 }) }); + var indicesToRemove = []; for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) { var distance = Vec3.distance(MyAvatar.getJointPosition(this.jointsIntersectingFromStart[i]), this.oldModelPosition); @@ -437,15 +432,6 @@ function controller(wichSide) { this.triggerValue = Controller.getTriggerValue(this.trigger); var bumperValue = Controller.isButtonPressed(this.bumper); - if (bumperValue && !this.bumperValue) { - if (mode === STICKS) { - mode = MAPPED; - } else if (mode === MAPPED) { - mode = STICKS; - } - Overlays.editOverlay(leftController.laser, { color: LASER_COLOR[mode] }); - Overlays.editOverlay(rightController.laser, { color: LASER_COLOR[mode] }); - } this.bumperValue = bumperValue; @@ -563,55 +549,31 @@ function moveEntities() { var rotation = leftController.oldModelRotation; var ratio = 1; + var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition)); + var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition)); - switch (mode) { - case STICKS: - var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x)); - var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x)); - - var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5); - var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint)); - - - var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x)); - var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x)); - - var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5); - var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint)); - - - ratio = length / oldLength; - newPosition = Vec3.sum(middle, - Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio)); - break; - case MAPPED: - var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition)); - var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition)); - - var cos_theta = Vec3.dot(u, v); - if (cos_theta > 1) { - cos_theta = 1; - } - var angle = Math.acos(cos_theta) / Math.PI * 180; - if (angle < 0.1) { - return; - - } - var w = Vec3.normalize(Vec3.cross(u, v)); - - rotation = Quat.multiply(Quat.angleAxis(angle, w), leftController.oldModelRotation); - - - leftController.positionAtGrab = leftController.palmPosition; - leftController.rotationAtGrab = leftController.rotation; - leftController.modelPositionAtGrab = leftController.oldModelPosition; - leftController.modelRotationAtGrab = rotation; - rightController.positionAtGrab = rightController.palmPosition; - rightController.rotationAtGrab = rightController.rotation; - rightController.modelPositionAtGrab = rightController.oldModelPosition; - rightController.modelRotationAtGrab = rotation; - break; + var cos_theta = Vec3.dot(u, v); + if (cos_theta > 1) { + cos_theta = 1; } + var angle = Math.acos(cos_theta) / Math.PI * 180; + if (angle < 0.1) { + return; + } + var w = Vec3.normalize(Vec3.cross(u, v)); + + rotation = Quat.multiply(Quat.angleAxis(angle, w), leftController.oldModelRotation); + + + leftController.positionAtGrab = leftController.palmPosition; + leftController.rotationAtGrab = leftController.rotation; + leftController.modelPositionAtGrab = leftController.oldModelPosition; + leftController.modelRotationAtGrab = rotation; + rightController.positionAtGrab = rightController.palmPosition; + rightController.rotationAtGrab = rightController.rotation; + rightController.modelPositionAtGrab = rightController.oldModelPosition; + rightController.modelRotationAtGrab = rotation; + Entities.editEntity(leftController.entityID, { position: newPosition, rotation: rotation, @@ -621,7 +583,6 @@ function moveEntities() { y: leftController.oldModelHalfDiagonal * ratio, z: leftController.oldModelHalfDiagonal * ratio } - }); leftController.oldModelPosition = newPosition; leftController.oldModelRotation = rotation; From 005cd2ba53a70c639b73f8299e72d9c2871d3420 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 26 Jan 2015 20:44:47 -0800 Subject: [PATCH 08/20] Add block building toolset, first version --- examples/blocks.js | 114 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 examples/blocks.js diff --git a/examples/blocks.js b/examples/blocks.js new file mode 100644 index 0000000000..69d4dbc4d4 --- /dev/null +++ b/examples/blocks.js @@ -0,0 +1,114 @@ +// +// Blocks.js +// +// Created by Philip Rosedale on January 26, 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Create a bunch of building blocks and drop them onto a playing surface in front of you. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +var FLOOR_SIZE = 5.0; +var FLOOR_THICKNESS = 0.10; +var EDGE_THICKESS = 0.25; +var SCALE = 0.25; + +var GRAVITY = -1.0; +var LIFETIME = 6000; +var DAMPING = 0.50; + +var blockTypes = []; +blockTypes.push({ x: 1, y: 1, z: 1, red: 255, green: 0, blue: 0 }); +blockTypes.push({ x: 1, y: 1, z: 2, red: 0, green: 255, blue: 0 }); +blockTypes.push({ x: 1, y: 2, z: 5, red: 0, green: 0, blue: 255 }); +blockTypes.push({ x: 1, y: 2, z: 2, red: 255, green: 255, blue: 0 }); + + +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(FLOOR_SIZE * 2.0, Quat.getFront(Camera.getOrientation()))); + +var floor = Entities.addEntity( + { type: "Box", + position: Vec3.subtract(center, { x: 0, y: SCALE / 2.0, z: 0 }), + dimensions: { x: FLOOR_SIZE, y: FLOOR_THICKNESS, z: FLOOR_SIZE }, + color: { red: 128, green: 128, blue: 128 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + locked: true, + lifetime: LIFETIME }); + +var edge1 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), + dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, + color: { red: 128, green: 128, blue: 128 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var edge2 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: -FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), + dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, + color: { red: 128, green: 128, blue: 128 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var edge3 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: -FLOOR_SIZE / 2.0 }), + dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, + color: { red: 128, green: 128, blue: 128 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var edge4 = Entities.addEntity( + { type: "Box", + position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: FLOOR_SIZE / 2.0 }), + dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, + color: { red: 128, green: 128, blue: 128 }, + gravity: { x: 0, y: 0, z: 0 }, + ignoreCollisions: false, + visible: true, + lifetime: LIFETIME }); + +var NUM_BLOCKS = 20; +var DROP_HEIGHT = FLOOR_SIZE / 3; + +blocks = []; + +for (var i = 0; i < NUM_BLOCKS; i++) { + var which = Math.floor(Math.random() * blockTypes.length); + var type = blockTypes[which]; + blocks.push(Entities.addEntity( + { type: "Box", + position: { x: center.x + (Math.random() - 0.5) * (FLOOR_SIZE * 0.75), + y: center.y + DROP_HEIGHT, + z: center.z + (Math.random() - 0.5) * (FLOOR_SIZE * 0.75) }, + dimensions: { x: type.x * SCALE, y: type.y * SCALE, z: type.z * SCALE }, + color: { red: type.red, green: type.green, blue: type.blue }, + gravity: { x: 0, y: GRAVITY, z: 0 }, + ignoreCollisions: false, + damping: DAMPING, + lifetime: LIFETIME, + collisionsWillMove: true })); +} + +function scriptEnding() { + Entities.deleteEntity(edge1); + Entities.deleteEntity(edge2); + Entities.deleteEntity(edge3); + Entities.deleteEntity(edge4); + Entities.deleteEntity(floor); + + for (var i = 0; i < NUM_BLOCKS; i++) { + Entities.deleteEntity(blocks[i]); + } +} + +Script.scriptEnding.connect(scriptEnding); \ No newline at end of file From 8b5a45188695f19755d7ceb6ab81175b420aeaf6 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 26 Jan 2015 21:09:21 -0800 Subject: [PATCH 09/20] Grab now correctly adds linear velocity so that you can grab and throw things --- examples/controllers/hydra/hydraGrab.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/controllers/hydra/hydraGrab.js b/examples/controllers/hydra/hydraGrab.js index 9f250f9208..5ba8613ad9 100644 --- a/examples/controllers/hydra/hydraGrab.js +++ b/examples/controllers/hydra/hydraGrab.js @@ -36,6 +36,8 @@ var DROP_DISTANCE = 5.0; var LASER_LENGTH_FACTOR = 500; +var velocity = { x: 0, y: 0, z: 0 }; + var lastAccurateIntersection = null; var accurateIntersections = 0; var totalIntersections = 0; @@ -350,7 +352,7 @@ function controller(wichSide) { Overlays.editOverlay(this.leftRight, { visible: show }); Overlays.editOverlay(this.topDown, { visible: show }); } - this.moveEntity = function () { + this.moveEntity = function (deltaTime) { if (this.grabbing) { if (!this.entityID.isKnownID) { print("Unknown grabbed ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); @@ -386,11 +388,13 @@ function controller(wichSide) { newRotation = Quat.multiply(newRotation, newRotation); newRotation = Quat.multiply(newRotation, this.modelRotationAtGrab); - + velocity = Vec3.multiply(1.0 / deltaTime, Vec3.subtract(newPosition, this.oldModelPosition)); + Entities.editEntity(this.entityID, { position: newPosition, - rotation: newRotation + rotation: newRotation, + velocity: velocity }); this.oldModelRotation = newRotation; this.oldModelPosition = newPosition; @@ -543,7 +547,7 @@ function controller(wichSide) { var leftController = new controller(LEFT); var rightController = new controller(RIGHT); -function moveEntities() { +function moveEntities(deltaTime) { if (leftController.grabbing && rightController.grabbing && rightController.entityID.id == leftController.entityID.id) { var newPosition = leftController.oldModelPosition; var rotation = leftController.oldModelRotation; @@ -593,8 +597,8 @@ function moveEntities() { rightController.oldModelHalfDiagonal *= ratio; return; } - leftController.moveEntity(); - rightController.moveEntity(); + leftController.moveEntity(deltaTime); + rightController.moveEntity(deltaTime); } var hydraConnected = false; @@ -612,7 +616,7 @@ function checkController(deltaTime) { leftController.update(); rightController.update(); - moveEntities(); + moveEntities(deltaTime); } else { if (hydraConnected) { hydraConnected = false; From e8f4783beadc8f158dad398e819d6cc1b392e259 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 26 Jan 2015 22:06:59 -0800 Subject: [PATCH 10/20] border, new size for blocks, smoother hydra grab action --- examples/blocks.js | 14 +++++++++----- examples/controllers/hydra/hydraGrab.js | 23 +++++++---------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/examples/blocks.js b/examples/blocks.js index 69d4dbc4d4..30c2126096 100644 --- a/examples/blocks.js +++ b/examples/blocks.js @@ -9,11 +9,14 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var FLOOR_SIZE = 5.0; +var FLOOR_SIZE = 7.5; var FLOOR_THICKNESS = 0.10; var EDGE_THICKESS = 0.25; var SCALE = 0.25; +var NUM_BLOCKS = 25; +var DROP_HEIGHT = SCALE * 8.0; + var GRAVITY = -1.0; var LIFETIME = 6000; var DAMPING = 0.50; @@ -23,7 +26,7 @@ blockTypes.push({ x: 1, y: 1, z: 1, red: 255, green: 0, blue: 0 }); blockTypes.push({ x: 1, y: 1, z: 2, red: 0, green: 255, blue: 0 }); blockTypes.push({ x: 1, y: 2, z: 5, red: 0, green: 0, blue: 255 }); blockTypes.push({ x: 1, y: 2, z: 2, red: 255, green: 255, blue: 0 }); - +blockTypes.push({ x: 1, y: 1, z: 5, red: 0, green: 255, blue: 255 }); var center = Vec3.sum(MyAvatar.position, Vec3.multiply(FLOOR_SIZE * 2.0, Quat.getFront(Camera.getOrientation()))); @@ -45,6 +48,7 @@ var edge1 = Entities.addEntity( gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, + locked: true, lifetime: LIFETIME }); var edge2 = Entities.addEntity( @@ -55,6 +59,7 @@ var edge2 = Entities.addEntity( gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, + locked: true, lifetime: LIFETIME }); var edge3 = Entities.addEntity( @@ -65,6 +70,7 @@ var edge3 = Entities.addEntity( gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, + locked: true, lifetime: LIFETIME }); var edge4 = Entities.addEntity( @@ -75,11 +81,9 @@ var edge4 = Entities.addEntity( gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, + locked: true, lifetime: LIFETIME }); -var NUM_BLOCKS = 20; -var DROP_HEIGHT = FLOOR_SIZE / 3; - blocks = []; for (var i = 0; i < NUM_BLOCKS; i++) { diff --git a/examples/controllers/hydra/hydraGrab.js b/examples/controllers/hydra/hydraGrab.js index 5ba8613ad9..dc8cd14eaa 100644 --- a/examples/controllers/hydra/hydraGrab.js +++ b/examples/controllers/hydra/hydraGrab.js @@ -363,25 +363,16 @@ function controller(wichSide) { } var newPosition; var newRotation; - - var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); - var d = Vec3.dot(forward, MyAvatar.position); - var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; - var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; - var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); - - if (factor2 < 0) { - factor2 = 0; - } - if (factor1 <= 0) { - factor1 = 1; - factor2 = 1; + var CONSTANT_SCALING_FACTOR = 5.0; + var MINIMUM_SCALING_DISTANCE = 2.0; + var distanceToModel = Vec3.length(Vec3.subtract(this.oldModelPosition, this.palmPosition)); + if (distanceToModel < MINIMUM_SCALING_DISTANCE) { + distanceToModel = MINIMUM_SCALING_DISTANCE; } - newPosition = Vec3.sum(this.modelPositionAtGrab, - Vec3.multiply(vector, - factor2 / factor1)); + var deltaPalm = Vec3.multiply(distanceToModel * CONSTANT_SCALING_FACTOR, Vec3.subtract(this.palmPosition, this.oldPalmPosition)); + newPosition = Vec3.sum(this.oldModelPosition, deltaPalm); newRotation = Quat.multiply(this.rotation, Quat.inverse(this.rotationAtGrab)); From 117e6abb46e979c14aa41a42b3d600e53ef71e86 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 28 Jan 2015 09:34:15 -0800 Subject: [PATCH 11/20] remove debug and PR fixes --- examples/billiards.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/billiards.js b/examples/billiards.js index 3e2be52d0f..fbd41e8939 100644 --- a/examples/billiards.js +++ b/examples/billiards.js @@ -139,8 +139,6 @@ function makeBalls(pos) { } ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE; } - print(balls.length + " Object balls made."); - print(isObjectBall(balls[1].id)); // Cue Ball cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z }; @@ -160,8 +158,9 @@ function makeBalls(pos) { function isObjectBall(id) { for (var i; i < balls.length; i++) { - if (balls[i].id == id) + if (balls[i].id == id) { return true; + } } return false; } @@ -243,6 +242,7 @@ function update(deltaTime) { function entityCollisionWithEntity(entity1, entity2, collision) { /* + NOT WORKING YET if ((entity1.id == cueBall.id) || (entity2.id == cueBall.id)) { print("Cue ball collision!"); //audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); From a85c6aa956e0ce7030103a246214fee68e2430a4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 28 Jan 2015 09:49:45 -0800 Subject: [PATCH 12/20] fix tabs? --- examples/controllers/hydra/paddleBall.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/controllers/hydra/paddleBall.js b/examples/controllers/hydra/paddleBall.js index 8c9af68498..d6c39131c8 100644 --- a/examples/controllers/hydra/paddleBall.js +++ b/examples/controllers/hydra/paddleBall.js @@ -39,9 +39,6 @@ if (leftHanded) { controllerID = 3; } - - - var screenSize = Controller.getViewportDimensions(); var offButton = Overlays.addOverlay("image", { x: screenSize.x - 48, @@ -98,8 +95,8 @@ function createEntities() { alpha: 1, visible: true, lineWidth: 2 }); - - MyAvatar.stopAnimation(leftHanded ? leftHandAnimation: rightHandAnimation); + + MyAvatar.stopAnimation(leftHanded ? leftHandAnimation: rightHandAnimation); MyAvatar.startAnimation(leftHanded ? leftHandAnimation: rightHandAnimation, 15.0, 1.0, false, true, 0.0, 6); } From e1ca6d5048c786bed4b462a9a476187ab9f7b3d9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 Jan 2015 12:16:28 -0800 Subject: [PATCH 13/20] Disable editentities auto-off when moving avatar --- examples/editEntities.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index e2c7a6d435..10cc7df894 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -820,9 +820,8 @@ function handeMenuEvent(menuItem) { Menu.menuItemEvent.connect(handeMenuEvent); Controller.keyPressEvent.connect(function(event) { - if (event.text == 'w' || event.text == 'a' || event.text == 's' || event.text == 'd' - || event.text == 'UP' || event.text == 'DOWN' || event.text == 'LEFT' || event.text == 'RIGHT') { - toolBar.setActive(false); + if (isActive) { + cameraManager.keyPressEvent(event); } }); From 5633be0e92d8020e0ca56e64d7785747698773c4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 Jan 2015 12:19:42 -0800 Subject: [PATCH 14/20] Add ability to move orbit camera using keys --- examples/editEntities.js | 3 + examples/libraries/entityCameraTool.js | 83 ++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index 10cc7df894..883362c4a4 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -826,6 +826,9 @@ Controller.keyPressEvent.connect(function(event) { }); Controller.keyReleaseEvent.connect(function (event) { + if (isActive) { + cameraManager.keyReleaseEvent(event); + } // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items if (event.text == "BACKSPACE" || event.text == "DELETE") { deleteSelectedEntities(); diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index f5095bb149..ddbb6fafd5 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -15,6 +15,9 @@ var MOUSE_SENSITIVITY = 0.9; var SCROLL_SENSITIVITY = 0.05; var PAN_ZOOM_SCALE_RATIO = 0.4; +var KEY_ORBIT_SENSITIVITY = 40; +var KEY_ZOOM_SENSITIVITY = 10; + // Scaling applied based on the size of the object being focused var FOCUS_ZOOM_SCALE = 1.3; @@ -43,6 +46,10 @@ var easeOutCubic = function(t) { EASE_TIME = 0.5; +function clamp(value, minimum, maximum) { + return Math.min(Math.max(value, minimum), maximum); +} + function mergeObjects(obj1, obj2) { var newObj = {}; for (key in obj1) { @@ -60,6 +67,49 @@ CameraManager = function() { that.enabled = false; that.mode = MODE_INACTIVE; + var actions = { + orbitLeft: 0, + orbitRight: 0, + orbitUp: 0, + orbitDown: 0, + orbitForward: 0, + orbitBackward: 0, + } + + var keyToActionMapping = { + "a": "orbitLeft", + "d": "orbitRight", + "w": "orbitForward", + "s": "orbitBackward", + "e": "orbitUp", + "c": "orbitDown", + + "LEFT": "orbitLeft", + "RIGHT": "orbitRight", + "UP": "orbitForward", + "DOWN": "orbitBackward", + } + + var CAPTURED_KEYS = []; + for (key in keyToActionMapping) { + CAPTURED_KEYS.push(key); + } + + function getActionForKeyEvent(event) { + var action = keyToActionMapping[event.text]; + if (action !== undefined) { + if (event.isShifted) { + if (action == "orbitForward") { + action = "orbitUp"; + } else if (action == "orbitBackward") { + action = "orbitDown"; + } + } + return action; + } + return null; + } + that.zoomDistance = INITIAL_ZOOM_DISTANCE; that.targetZoomDistance = INITIAL_ZOOM_DISTANCE; @@ -82,6 +132,11 @@ CameraManager = function() { that.enable = function() { if (Camera.mode == "independent" || that.enabled) return; + for (var i = 0; i < CAPTURED_KEYS.length; i++) { + print("capturing: " + CAPTURED_KEYS[i]); + Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); + } + that.enabled = true; that.mode = MODE_INACTIVE; @@ -112,6 +167,11 @@ CameraManager = function() { that.disable = function(ignoreCamera) { if (!that.enabled) return; + + for (var i = 0; i < CAPTURED_KEYS.length; i++) { + Controller.releaseKeyEvents({ text: CAPTURED_KEYS[i] }); + } + that.enabled = false; that.mode = MODE_INACTIVE; @@ -280,6 +340,20 @@ CameraManager = function() { that.mode = MODE_INACTIVE; } + that.keyPressEvent = function(event) { + var action = getActionForKeyEvent(event); + if (action) { + actions[action] = 1; + } + }; + + that.keyReleaseEvent = function(event) { + var action = getActionForKeyEvent(event); + if (action) { + actions[action] = 0; + } + }; + that.wheelEvent = function(event) { if (!that.enabled) return; @@ -333,6 +407,14 @@ CameraManager = function() { return; } + // Update based on current actions + that.targetYaw += (actions.orbitRight - actions.orbitLeft) * dt * KEY_ORBIT_SENSITIVITY; + that.targetPitch += (actions.orbitUp - actions.orbitDown) * dt * KEY_ORBIT_SENSITIVITY; + that.targetPitch = clamp(that.targetPitch, -90, 90); + var addZoom = (actions.orbitBackward - actions.orbitForward) * dt * KEY_ZOOM_SENSITIVITY; + that.targetZoomDistance = clamp(that.targetZoomDistance + addZoom, MIN_ZOOM_DISTANCE, MAX_ZOOM_DISTANCE); + + if (easing) { easingTime = Math.min(EASE_TIME, easingTime + dt); } @@ -384,6 +466,7 @@ CameraManager = function() { }); Script.update.connect(that.update); + Script.scriptEnding.connect(that.disable); Controller.wheelEvent.connect(that.wheelEvent); From 135c8c1bdf2ea17c4043d9c7243d615957f511c7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 Jan 2015 12:19:54 -0800 Subject: [PATCH 15/20] Disable move entity by arrows --- examples/editEntities.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index 883362c4a4..f88a0e44d9 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -856,23 +856,23 @@ Controller.keyReleaseEvent.connect(function (event) { var delta = null; var increment = event.isShifted ? grid.getMajorIncrement() : grid.getMinorIncrement(); - if (event.text == 'UP') { - if (event.isControl || event.isAlt) { - delta = { x: 0, y: increment, z: 0 }; - } else { - delta = { x: 0, y: 0, z: -increment }; - } - } else if (event.text == 'DOWN') { - if (event.isControl || event.isAlt) { - delta = { x: 0, y: -increment, z: 0 }; - } else { - delta = { x: 0, y: 0, z: increment }; - } - } else if (event.text == 'LEFT') { - delta = { x: -increment, y: 0, z: 0 }; - } else if (event.text == 'RIGHT') { - delta = { x: increment, y: 0, z: 0 }; - } + // if (event.text == 'UP') { + // if (event.isControl || event.isAlt) { + // delta = { x: 0, y: increment, z: 0 }; + // } else { + // delta = { x: 0, y: 0, z: -increment }; + // } + // } else if (event.text == 'DOWN') { + // if (event.isControl || event.isAlt) { + // delta = { x: 0, y: -increment, z: 0 }; + // } else { + // delta = { x: 0, y: 0, z: increment }; + // } + // } else if (event.text == 'LEFT') { + // delta = { x: -increment, y: 0, z: 0 }; + // } else if (event.text == 'RIGHT') { + // delta = { x: increment, y: 0, z: 0 }; + // } if (delta != null) { // Adjust delta so that movements are relative to the current camera orientation From 55f41eb452c1115f8872285408578dc819bf7a2a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 Jan 2015 12:20:08 -0800 Subject: [PATCH 16/20] Update gridTool to not use clone --- examples/libraries/gridTool.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 87b7f907e2..6fd3a8a660 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -292,7 +292,6 @@ GridTool = function(opts) { ]; // Add all overlays from spritesheet - var baseOverlay = null; var x = 0; for (var i = 0; i < UI_SPRITE_LIST.length; i++) { var info = UI_SPRITE_LIST[i]; @@ -306,17 +305,7 @@ GridTool = function(opts) { visible: false, }; - var overlay; - if (baseOverlay == null) { - overlay = Overlays.addOverlay("image", { - imageURL: UI_URL, - }); - baseOverlay = overlay; - } else { - overlay = Overlays.cloneOverlay(baseOverlay); - } - - Overlays.editOverlay(overlay, props); + var overlay = Overlays.addOverlay("image", props); addUIOverlay(info.name, overlay, x, 0, info.width, UI_HEIGHT); From a775476cfa87c1268604bc13f05d2748148423d9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 Jan 2015 12:21:50 -0800 Subject: [PATCH 17/20] Remove editEntities move-by-arrow-key completely --- examples/editEntities.js | 49 ---------------------------------------- 1 file changed, 49 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index f88a0e44d9..083887819f 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -852,55 +852,6 @@ Controller.keyReleaseEvent.connect(function (event) { newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 }); grid.setPosition(newPosition); } - } else if (isActive) { - var delta = null; - var increment = event.isShifted ? grid.getMajorIncrement() : grid.getMinorIncrement(); - - // if (event.text == 'UP') { - // if (event.isControl || event.isAlt) { - // delta = { x: 0, y: increment, z: 0 }; - // } else { - // delta = { x: 0, y: 0, z: -increment }; - // } - // } else if (event.text == 'DOWN') { - // if (event.isControl || event.isAlt) { - // delta = { x: 0, y: -increment, z: 0 }; - // } else { - // delta = { x: 0, y: 0, z: increment }; - // } - // } else if (event.text == 'LEFT') { - // delta = { x: -increment, y: 0, z: 0 }; - // } else if (event.text == 'RIGHT') { - // delta = { x: increment, y: 0, z: 0 }; - // } - - if (delta != null) { - // Adjust delta so that movements are relative to the current camera orientation - var lookDirection = Quat.getFront(Camera.getOrientation()); - lookDirection.z *= -1; - - var angle = Math.atan2(lookDirection.z, lookDirection.x); - angle -= (Math.PI / 4); - - var rotation = Math.floor(angle / (Math.PI / 2)) * (Math.PI / 2); - var rotator = Quat.fromPitchYawRollRadians(0, rotation, 0); - - delta = Vec3.multiplyQbyV(rotator, delta); - - SelectionManager.saveProperties(); - - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = selectionManager.selections[i]; - var properties = Entities.getEntityProperties(entityID); - Entities.editEntity(entityID, { - position: Vec3.sum(properties.position, delta) - }); - } - - pushCommandForSelections(); - - selectionManager._update(); - } } }); From 09af7ed10faed02dec6a363b844a9165d81caabd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 Jan 2015 12:21:58 -0800 Subject: [PATCH 18/20] Remove extra print statement --- examples/libraries/entityCameraTool.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index ddbb6fafd5..df5daa561f 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -133,7 +133,6 @@ CameraManager = function() { if (Camera.mode == "independent" || that.enabled) return; for (var i = 0; i < CAPTURED_KEYS.length; i++) { - print("capturing: " + CAPTURED_KEYS[i]); Controller.captureKeyEvents({ text: CAPTURED_KEYS[i] }); } From 1b81ee17ab35a5f27b3fcd4a4e160d6b414e93ec Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 Jan 2015 12:23:54 -0800 Subject: [PATCH 19/20] Update how orbit-by-key is appleid --- examples/libraries/entityCameraTool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index df5daa561f..609c1db076 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -410,8 +410,8 @@ CameraManager = function() { that.targetYaw += (actions.orbitRight - actions.orbitLeft) * dt * KEY_ORBIT_SENSITIVITY; that.targetPitch += (actions.orbitUp - actions.orbitDown) * dt * KEY_ORBIT_SENSITIVITY; that.targetPitch = clamp(that.targetPitch, -90, 90); - var addZoom = (actions.orbitBackward - actions.orbitForward) * dt * KEY_ZOOM_SENSITIVITY; - that.targetZoomDistance = clamp(that.targetZoomDistance + addZoom, MIN_ZOOM_DISTANCE, MAX_ZOOM_DISTANCE); + that.targetZoomDistance += (actions.orbitBackward - actions.orbitForward) * dt * KEY_ZOOM_SENSITIVITY; + that.targetZoomDistance = clamp(that.targetZoomDistance, MIN_ZOOM_DISTANCE, MAX_ZOOM_DISTANCE); if (easing) { From 0c3f4b894ce4d3819582753867a1bd5e7136733e Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 29 Jan 2015 10:53:50 -0800 Subject: [PATCH 20/20] Menu for handedness, that really works. --- examples/controllers/hydra/paddleBall.js | 43 +++++++++++++++++++----- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/examples/controllers/hydra/paddleBall.js b/examples/controllers/hydra/paddleBall.js index d6c39131c8..fb312739f4 100644 --- a/examples/controllers/hydra/paddleBall.js +++ b/examples/controllers/hydra/paddleBall.js @@ -24,7 +24,8 @@ var BALL_COLOR = { red: 255, green: 0, blue: 0 }; var LINE_COLOR = { red: 255, green: 255, blue: 0 }; var PADDLE_BOX_OFFSET = { x: 0.05, y: 0.0, z: 0.0 }; -var HOLD_POSITION_OFFSET = { x: -0.15, y: 0.05, z: -0.05 }; +var HOLD_POSITION_LEFT_OFFSET = { x: -0.15, y: 0.05, z: -0.05 }; +var HOLD_POSITION_RIGHT_OFFSET = { x: -0.15, y: 0.05, z: 0.05 }; var PADDLE_ORIENTATION = Quat.fromPitchYawRollDegrees(0,0,0); var GRAVITY = 0.0; var SPRING_FORCE = 15.0; @@ -33,12 +34,19 @@ var gameOn = false; var leftHanded = true; var controllerID; -if (leftHanded) { - controllerID = 1; -} else { - controllerID = 3; + +function setControllerID() { + if (leftHanded) { + controllerID = 1; + } else { + controllerID = 3; + } } +setControllerID(); +Menu.addMenu("PaddleBall"); +Menu.addMenuItem({ menuName: "PaddleBall", menuItemName: "Left-Handed", isCheckable: true, isChecked: true }); + var screenSize = Controller.getViewportDimensions(); var offButton = Overlays.addOverlay("image", { x: screenSize.x - 48, @@ -96,7 +104,8 @@ function createEntities() { visible: true, lineWidth: 2 }); - MyAvatar.stopAnimation(leftHanded ? leftHandAnimation: rightHandAnimation); + MyAvatar.stopAnimation(leftHandAnimation); + MyAvatar.stopAnimation(rightHandAnimation); MyAvatar.startAnimation(leftHanded ? leftHandAnimation: rightHandAnimation, 15.0, 1.0, false, true, 0.0, 6); } @@ -129,9 +138,10 @@ function update(deltaTime) { if (!ball.isKnownID) { ball = Entities.identifyEntity(ball); } else { - var paddleWorldOrientation = Quat.multiply(Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)), PADDLE_ORIENTATION); + var paddleOrientation = leftHanded ? PADDLE_ORIENTATION : Quat.multiply(PADDLE_ORIENTATION, Quat.fromPitchYawRollDegrees(0, 180, 0)); + var paddleWorldOrientation = Quat.multiply(Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)), paddleOrientation); var holdPosition = Vec3.sum(leftHanded ? MyAvatar.getLeftPalmPosition() : MyAvatar.getRightPalmPosition(), - Vec3.multiplyQbyV(paddleWorldOrientation, HOLD_POSITION_OFFSET)); + Vec3.multiplyQbyV(paddleWorldOrientation, leftHanded ? HOLD_POSITION_LEFT_OFFSET : HOLD_POSITION_RIGHT_OFFSET )); var props = Entities.getEntityProperties(ball); var spring = Vec3.subtract(holdPosition, props.position); @@ -172,15 +182,30 @@ function mousePressEvent(event) { } } +function menuItemEvent(menuItem) { + oldHanded = leftHanded; + if (menuItem == "Left-Handed") { + leftHanded = Menu.isOptionChecked("Left-Handed"); + } + if ((leftHanded != oldHanded) && gameOn) { + setControllerID(); + deleteEntities(); + createEntities(); + } +} + function scriptEnding() { if (gameOn) { deleteEntities(); } Overlays.deleteOverlay(offButton); - MyAvatar.stopAnimation(leftHanded ? leftHandAnimation: rightHandAnimation); + MyAvatar.stopAnimation(leftHandAnimation); + MyAvatar.stopAnimation(rightHandAnimation); + Menu.removeMenu("PaddleBall"); } Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); +Menu.menuItemEvent.connect(menuItemEvent); Controller.mousePressEvent.connect(mousePressEvent); Script.scriptEnding.connect(scriptEnding); Script.update.connect(update);