From b9db495ebf78e85ada8f1b5faf1fa954fe6ecfbb Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 22 Sep 2015 09:38:06 -0700 Subject: [PATCH 1/7] Modified handControllerGrab script to trigger entity touch events for non-physical entities --- examples/controllers/handControllerGrab.js | 100 +++++++++++++++------ 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index f57e79e974..0fa32baf53 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -29,9 +29,21 @@ var TRIGGER_ON_VALUE = 0.2; var DISTANCE_HOLDING_RADIUS_FACTOR = 5; // multiplied by distance between hand and object var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did -var NO_INTERSECT_COLOR = {red: 10, green: 10, blue: 255}; // line color when pick misses -var INTERSECT_COLOR = {red: 250, green: 10, blue: 10}; // line color when pick hits -var LINE_ENTITY_DIMENSIONS = {x: 1000, y: 1000, z: 1000}; +var NO_INTERSECT_COLOR = { + red: 10, + green: 10, + blue: 255 +}; // line color when pick misses +var INTERSECT_COLOR = { + red: 250, + green: 10, + blue: 10 +}; // line color when pick hits +var LINE_ENTITY_DIMENSIONS = { + x: 1000, + y: 1000, + z: 1000 +}; var LINE_LENGTH = 500; @@ -54,7 +66,11 @@ var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things var RIGHT_HAND = 1; var LEFT_HAND = 0; -var ZERO_VEC = {x: 0, y: 0, z: 0}; +var ZERO_VEC = { + x: 0, + y: 0, + z: 0 +}; var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}"; var MSEC_PER_SEC = 1000.0; @@ -68,7 +84,9 @@ var STATE_DISTANCE_HOLDING = 1; var STATE_CONTINUE_DISTANCE_HOLDING = 2; var STATE_NEAR_GRABBING = 3; var STATE_CONTINUE_NEAR_GRABBING = 4; -var STATE_RELEASE = 5; +var STATE_NEAR_TOUCHING = 5; +var STATE_CONTINUE_NEAR_TOUCHING = 6; +var STATE_RELEASE = 7; var GRAB_USER_DATA_KEY = "grabKey"; @@ -93,7 +111,7 @@ function controller(hand, triggerAction) { this.triggerValue = 0; // rolling average of trigger value this.update = function() { - switch(this.state) { + switch (this.state) { case STATE_SEARCHING: this.search(); break; @@ -109,6 +127,12 @@ function controller(hand, triggerAction) { case STATE_CONTINUE_NEAR_GRABBING: this.continueNearGrabbing(); break; + case STATE_NEAR_TOUCHING: + this.nearTouching(); + break; + case STATE_CONTINUE_NEAR_TOUCHING: + this.continueNearTouching(); + break; case STATE_RELEASE: this.release(); break; @@ -125,14 +149,14 @@ function controller(hand, triggerAction) { dimensions: LINE_ENTITY_DIMENSIONS, visible: true, position: closePoint, - linePoints: [ ZERO_VEC, farPoint ], + linePoints: [ZERO_VEC, farPoint], color: color, lifetime: LIFETIME }); } else { Entities.editEntity(this.pointer, { position: closePoint, - linePoints: [ ZERO_VEC, farPoint ], + linePoints: [ZERO_VEC, farPoint], color: color, lifetime: (Date.now() - startTime) / MSEC_PER_SEC + LIFETIME }); @@ -171,7 +195,10 @@ function controller(hand, triggerAction) { // the trigger is being pressed, do a ray test var handPosition = this.getHandPosition(); - var pickRay = {origin: handPosition, direction: Quat.getUp(this.getHandRotation())}; + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; var intersection = Entities.findRayIntersection(pickRay, true); if (intersection.intersects && intersection.properties.collisionsWillMove === 1 && @@ -189,24 +216,25 @@ function controller(hand, triggerAction) { this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); } } else { - // forward ray test failed, try sphere test. + // forward ray test failed, try sphere test. var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); var minDistance = GRAB_RADIUS; var grabbedEntity = null; for (var i = 0; i < nearbyEntities.length; i++) { var props = Entities.getEntityProperties(nearbyEntities[i]); var distance = Vec3.distance(props.position, handPosition); - if (distance < minDistance && props.name !== "pointer" && - props.collisionsWillMove === 1 && - props.locked === 0) { + if (distance < minDistance && props.name !== "pointer") { this.grabbedEntity = nearbyEntities[i]; minDistance = distance; } } if (this.grabbedEntity === null) { this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); - } else { + } else if (props.locked === 0 && props.collisionsWillMove === 1) { this.state = STATE_NEAR_GRABBING; + } else if (props.collisionsWillMove === 0) { + // We have grabbed a non-physical object, so we want to trigger a touch event as opposed to a grab event + this.state = STATE_NEAR_TOUCHING; } } } @@ -215,7 +243,7 @@ function controller(hand, triggerAction) { this.distanceHolding = function() { var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position","rotation"]); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]); // add the action and initialize some variables this.currentObjectPosition = grabbedProperties.position; @@ -263,8 +291,8 @@ function controller(hand, triggerAction) { // the action was set up on a previous call. update the targets. var radius = Math.max(Vec3.distance(this.currentObjectPosition, - handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR, - DISTANCE_HOLDING_RADIUS_FACTOR); + handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR, + DISTANCE_HOLDING_RADIUS_FACTOR); var handMoved = Vec3.subtract(handControllerPosition, this.handPreviousPosition); this.handPreviousPosition = handControllerPosition; @@ -281,16 +309,18 @@ function controller(hand, triggerAction) { // this doubles hand rotation var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation, - DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), - Quat.inverse(this.handPreviousRotation)); + DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), + Quat.inverse(this.handPreviousRotation)); this.handPreviousRotation = handRotation; this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab"); Entities.updateAction(this.grabbedEntity, this.actionID, { - targetPosition: this.currentObjectPosition, linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, - targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME + targetPosition: this.currentObjectPosition, + linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, + targetRotation: this.currentObjectRotation, + angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME }); } @@ -339,6 +369,23 @@ function controller(hand, triggerAction) { this.currentObjectTime = Date.now(); } + this.nearTouching = function() { + if (!this.triggerSmoothedSqueezed()) { + this.state = STATE_RELEASE; + return; + } + Entities.callEntityMethod(this.grabbedEntity, "startNearTouch") + this.state = STATE_CONTINUE_NEAR_TOUCHING; + } + + this.continueNearTouching = function() { + if (!this.triggerSmoothedSqueezed()) { + this.state = STATE_RELEASE; + return; + } + Entities.callEntityMethod(this.grabbedEntity, "continueNearTouch"); + } + this.continueNearGrabbing = function() { if (!this.triggerSmoothedSqueezed()) { @@ -367,9 +414,8 @@ function controller(hand, triggerAction) { // value would otherwise give the held object time to slow down. if (this.triggerSqueezed()) { this.grabbedVelocity = - Vec3.sum(Vec3.multiply(this.grabbedVelocity, - (1.0 - NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)), - Vec3.multiply(grabbedVelocity, NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)); + Vec3.sum(Vec3.multiply(this.grabbedVelocity, (1.0 - NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)), + Vec3.multiply(grabbedVelocity, NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)); } if (useMultiplier) { @@ -389,7 +435,9 @@ function controller(hand, triggerAction) { // the action will tend to quickly bring an object's velocity to zero. now that // the action is gone, set the objects velocity to something the holder might expect. - Entities.editEntity(this.grabbedEntity, {velocity: this.grabbedVelocity}); + Entities.editEntity(this.grabbedEntity, { + velocity: this.grabbedVelocity + }); this.deactivateEntity(this.grabbedEntity); this.grabbedVelocity = ZERO_VEC; @@ -438,4 +486,4 @@ function cleanup() { Script.scriptEnding.connect(cleanup); -Script.update.connect(update) +Script.update.connect(update) \ No newline at end of file From 42a2125336a7edfba03b9e662f1e175ef85fd7ff Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 22 Sep 2015 13:29:54 -0700 Subject: [PATCH 2/7] Only asking for needed props --- examples/controllers/handControllerGrab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 0fa32baf53..af1c97da68 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -216,12 +216,12 @@ function controller(hand, triggerAction) { this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); } } else { - // forward ray test failed, try sphere test. + // forward ray test failed, try sphere test. var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); var minDistance = GRAB_RADIUS; var grabbedEntity = null; for (var i = 0; i < nearbyEntities.length; i++) { - var props = Entities.getEntityProperties(nearbyEntities[i]); + var props = Entities.getEntityProperties(nearbyEntities[i], ["position", "name", "collisionsWillMove", "locked"]); var distance = Vec3.distance(props.position, handPosition); if (distance < minDistance && props.name !== "pointer") { this.grabbedEntity = nearbyEntities[i]; From ba44390f79fc51ce26c31efb50e5b6d22d450e31 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 23 Sep 2015 13:20:21 -0700 Subject: [PATCH 3/7] Rename touch to grab non colliding --- examples/controllers/handControllerGrab.js | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index af1c97da68..bb806e14f1 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -84,10 +84,11 @@ var STATE_DISTANCE_HOLDING = 1; var STATE_CONTINUE_DISTANCE_HOLDING = 2; var STATE_NEAR_GRABBING = 3; var STATE_CONTINUE_NEAR_GRABBING = 4; -var STATE_NEAR_TOUCHING = 5; -var STATE_CONTINUE_NEAR_TOUCHING = 6; +var STATE_NEAR_GRABBING_NON_COLLIDING = 5; +var STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING = 6; var STATE_RELEASE = 7; + var GRAB_USER_DATA_KEY = "grabKey"; function controller(hand, triggerAction) { @@ -127,11 +128,11 @@ function controller(hand, triggerAction) { case STATE_CONTINUE_NEAR_GRABBING: this.continueNearGrabbing(); break; - case STATE_NEAR_TOUCHING: - this.nearTouching(); + case STATE_NEAR_GRABBING_NON_COLLIDING: + this.nearGrabbingNonColliding(); break; - case STATE_CONTINUE_NEAR_TOUCHING: - this.continueNearTouching(); + case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: + this.continueNearGrabbingNonColliding(); break; case STATE_RELEASE: this.release(); @@ -233,8 +234,8 @@ function controller(hand, triggerAction) { } else if (props.locked === 0 && props.collisionsWillMove === 1) { this.state = STATE_NEAR_GRABBING; } else if (props.collisionsWillMove === 0) { - // We have grabbed a non-physical object, so we want to trigger a touch event as opposed to a grab event - this.state = STATE_NEAR_TOUCHING; + // We have grabbed a non-physical object, so we want to trigger a non-colliding event as opposed to a grab event + this.state = STATE_NEAR_GRABBING_NON_COLLIDING; } } } @@ -369,21 +370,21 @@ function controller(hand, triggerAction) { this.currentObjectTime = Date.now(); } - this.nearTouching = function() { + this.nearGrabbingNonColliding = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; } - Entities.callEntityMethod(this.grabbedEntity, "startNearTouch") - this.state = STATE_CONTINUE_NEAR_TOUCHING; + Entities.callEntityMethod(this.grabbedEntity, "startNearGrabNonColliding") + this.state = STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING; } - this.continueNearTouching = function() { + this.continueNearGrabNonColliding = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; } - Entities.callEntityMethod(this.grabbedEntity, "continueNearTouch"); + Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabNonColliding"); } From 381a24951e68ccff1b4ce52bdd350cd20be70dea Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 23 Sep 2015 16:56:46 -0700 Subject: [PATCH 4/7] Update grab script to handle touching, better naming for non colliding grab functions --- examples/controllers/handControllerGrab.js | 266 ++++++++++++------- examples/entityScripts/changeColorOnTouch.js | 71 +++++ 2 files changed, 243 insertions(+), 94 deletions(-) create mode 100644 examples/entityScripts/changeColorOnTouch.js diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index bb806e14f1..5818815bb2 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -8,11 +8,10 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ Script.include("../libraries/utils.js"); - ///////////////////////////////////////////////////////////////// // // these tune time-averaging and "on" value for analog trigger @@ -110,40 +109,40 @@ function controller(hand, triggerAction) { this.state = 0; this.pointer = null; // entity-id of line object this.triggerValue = 0; // rolling average of trigger value - - this.update = function() { + var _this = this; + this.update = function () { switch (this.state) { - case STATE_SEARCHING: - this.search(); - break; - case STATE_DISTANCE_HOLDING: - this.distanceHolding(); - break; - case STATE_CONTINUE_DISTANCE_HOLDING: - this.continueDistanceHolding(); - break; - case STATE_NEAR_GRABBING: - this.nearGrabbing(); - break; - case STATE_CONTINUE_NEAR_GRABBING: - this.continueNearGrabbing(); - break; - case STATE_NEAR_GRABBING_NON_COLLIDING: - this.nearGrabbingNonColliding(); - break; - case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: - this.continueNearGrabbingNonColliding(); - break; - case STATE_RELEASE: - this.release(); - break; + case STATE_SEARCHING: + this.search(); + this.touchTest(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + this.nearGrabbing(); + break; + case STATE_CONTINUE_NEAR_GRABBING: + this.continueNearGrabbing(); + break; + case STATE_NEAR_GRABBING_NON_COLLIDING: + this.nearGrabbingNonColliding(); + break; + case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: + this.continueNearGrabbingNonColliding(); + break; + case STATE_RELEASE: + this.release(); + break; } - } - - - this.lineOn = function(closePoint, farPoint, color) { + }; + _this.pointerIDs = []; + this.lineOn = function (closePoint, farPoint, color) { // draw a line - if (this.pointer == null) { + if (this.pointer === null) { this.pointer = Entities.addEntity({ type: "Line", name: "pointer", @@ -154,6 +153,7 @@ function controller(hand, triggerAction) { color: color, lifetime: LIFETIME }); + _this.pointerIDs.push(this.pointer); } else { Entities.editEntity(this.pointer, { position: closePoint, @@ -162,33 +162,40 @@ function controller(hand, triggerAction) { lifetime: (Date.now() - startTime) / MSEC_PER_SEC + LIFETIME }); } - } + + }; - this.lineOff = function() { - if (this.pointer != null) { + this.lineOff = function () { + if (this.pointer !== null) { Entities.deleteEntity(this.pointer); } + var index = _this.pointerIDs.indexOf(this.pointer); + if (index > -1) { + _this.pointerIDs.splice(index, 1); + } this.pointer = null; - } + }; - this.triggerSmoothedSqueezed = function() { + this.triggerSmoothedSqueezed = function () { var triggerValue = Controller.getActionValue(this.triggerAction); // smooth out trigger value this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); return this.triggerValue > TRIGGER_ON_VALUE; - } + }; - this.triggerSqueezed = function() { + this.triggerSqueezed = function () { var triggerValue = Controller.getActionValue(this.triggerAction); return triggerValue > TRIGGER_ON_VALUE; - } + }; + + + this.search = function () { - this.search = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -220,10 +227,10 @@ function controller(hand, triggerAction) { // forward ray test failed, try sphere test. var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); var minDistance = GRAB_RADIUS; - var grabbedEntity = null; - for (var i = 0; i < nearbyEntities.length; i++) { - var props = Entities.getEntityProperties(nearbyEntities[i], ["position", "name", "collisionsWillMove", "locked"]); - var distance = Vec3.distance(props.position, handPosition); + var i, props, distance; + for (i = 0; i < nearbyEntities.length; i++) { + props = Entities.getEntityProperties(nearbyEntities[i], ["position", "name", "collisionsWillMove", "locked"]); + distance = Vec3.distance(props.position, handPosition); if (distance < minDistance && props.name !== "pointer") { this.grabbedEntity = nearbyEntities[i]; minDistance = distance; @@ -238,10 +245,11 @@ function controller(hand, triggerAction) { this.state = STATE_NEAR_GRABBING_NON_COLLIDING; } } - } + + }; - this.distanceHolding = function() { + this.distanceHolding = function () { var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]); @@ -259,25 +267,26 @@ function controller(hand, triggerAction) { targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME }); - if (this.actionID == NULL_ACTION_ID) { + if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } - if (this.actionID != null) { + if (this.actionID !== null) { this.state = STATE_CONTINUE_DISTANCE_HOLDING; this.activateEntity(this.grabbedEntity); - Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); - if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); } else { Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); } } - } + Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); - this.continueDistanceHolding = function() { + }; + + + this.continueDistanceHolding = function () { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -323,10 +332,10 @@ function controller(hand, triggerAction) { targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME }); - } + }; - this.nearGrabbing = function() { + this.nearGrabbing = function () { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -344,51 +353,34 @@ function controller(hand, triggerAction) { var objectRotation = grabbedProperties.rotation; var offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation); - currentObjectPosition = grabbedProperties.position; + var currentObjectPosition = grabbedProperties.position; var offset = Vec3.subtract(currentObjectPosition, handPosition); var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset); this.actionID = Entities.addAction("hold", this.grabbedEntity, { - hand: this.hand == RIGHT_HAND ? "right" : "left", + hand: this.hand === RIGHT_HAND ? "right" : "left", timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, relativePosition: offsetPosition, relativeRotation: offsetRotation }); - if (this.actionID == NULL_ACTION_ID) { + if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } else { this.state = STATE_CONTINUE_NEAR_GRABBING; - Entities.callEntityMethod(this.grabbedEntity, "startNearGrab"); if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); } else { Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); } + Entities.callEntityMethod(this.grabbedEntity, "startNearGrab"); + } this.currentHandControllerPosition = Controller.getSpatialControlPosition(this.palm); this.currentObjectTime = Date.now(); - } + }; - this.nearGrabbingNonColliding = function() { - if (!this.triggerSmoothedSqueezed()) { - this.state = STATE_RELEASE; - return; - } - Entities.callEntityMethod(this.grabbedEntity, "startNearGrabNonColliding") - this.state = STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING; - } - - this.continueNearGrabNonColliding = function() { - if (!this.triggerSmoothedSqueezed()) { - this.state = STATE_RELEASE; - return; - } - Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabNonColliding"); - } - - - this.continueNearGrabbing = function() { + this.continueNearGrabbing = function () { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -405,10 +397,96 @@ function controller(hand, triggerAction) { this.currentHandControllerPosition = handControllerPosition; this.currentObjectTime = now; Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); - } + }; + this.nearGrabbingNonColliding = function () { + if (!this.triggerSmoothedSqueezed()) { + this.state = STATE_RELEASE; + return; + } + Entities.callEntityMethod(this.grabbedEntity, "startNearGrabNonColliding"); + this.state = STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING; + }; - this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) { + this.continueNearGrabbingNonColliding = function () { + if (!this.triggerSmoothedSqueezed()) { + this.state = STATE_RELEASE; + return; + } + Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding"); + }; + + _this.allTouchedIDs = {}; + this.touchTest = function () { + //print('touch test'); + var maxDistance = 0.05; + var leftHandPosition = MyAvatar.getLeftPalmPosition(); + var rightHandPosition = MyAvatar.getRightPalmPosition(); + var leftEntities = Entities.findEntities(leftHandPosition, maxDistance); + var rightEntities = Entities.findEntities(rightHandPosition, maxDistance); + var ids = []; + if (leftEntities.length !== 0) { + leftEntities.forEach(function (entity) { + ids.push(entity); + }); + + } + if (rightEntities.length !== 0) { + rightEntities.forEach(function (entity) { + ids.push(entity); + }); + } + + ids.forEach(function (id) { + + var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); + if (props.name === 'pointer') { + return; + } else { + var entityMinPoint = props.boundingBox.brn; + var entityMaxPoint = props.boundingBox.tfl; + var leftIsTouching = pointInExtents(leftHandPosition, entityMinPoint, entityMaxPoint); + var rightIsTouching = pointInExtents(rightHandPosition, entityMinPoint, entityMaxPoint); + + if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === undefined) { + // we haven't been touched before, but either right or left is touching us now + _this.allTouchedIDs[id] = true; + _this.startTouch(id); + } else if ((leftIsTouching || rightIsTouching) && _this.allTouchedIDs[id] === true) { + // we have been touched before and are still being touched + // continue touch + _this.continueTouch(id); + } else if (_this.allTouchedIDs[id] === true) { + delete _this.allTouchedIDs[id]; + _this.stopTouch(id); + + } else { + //we are in another state + return; + } + } + + }); + + }; + + this.startTouch = function (entityID) { + // print('START TOUCH' + entityID); + Entities.callEntityMethod(entityID, "startTouch"); + }; + + this.continueTouch = function (entityID) { + // print('CONTINUE TOUCH' + entityID); + Entities.callEntityMethod(entityID, "continueTouch"); + }; + + this.stopTouch = function (entityID) { + // print('STOP TOUCH' + entityID); + Entities.callEntityMethod(entityID, "stopTouch"); + + }; + + this.computeReleaseVelocity = function (deltaPosition, deltaTime, useMultiplier) { if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) { var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime); // don't update grabbedVelocity if the trigger is off. the smoothing of the trigger @@ -423,13 +501,13 @@ function controller(hand, triggerAction) { this.grabbedVelocity = Vec3.multiply(this.grabbedVelocity, RELEASE_VELOCITY_MULTIPLIER); } } - } + }; - this.release = function() { + this.release = function () { this.lineOff(); - if (this.grabbedEntity != null && this.actionID != null) { + if (this.grabbedEntity !== null && this.actionID !== null) { Entities.deleteAction(this.grabbedEntity, this.actionID); Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); } @@ -445,28 +523,28 @@ function controller(hand, triggerAction) { this.grabbedEntity = null; this.actionID = null; this.state = STATE_SEARCHING; - } + }; - this.cleanup = function() { - release(); - } + this.cleanup = function () { + this.release(); + }; - this.activateEntity = function(entity) { + this.activateEntity = function () { var data = { activated: true, avatarId: MyAvatar.sessionUUID }; setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data); - } + }; - this.deactivateEntity = function(entity) { + this.deactivateEntity = function () { var data = { activated: false, avatarId: null }; setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data); - } + }; } @@ -487,4 +565,4 @@ function cleanup() { Script.scriptEnding.connect(cleanup); -Script.update.connect(update) \ No newline at end of file +Script.update.connect(update); \ No newline at end of file diff --git a/examples/entityScripts/changeColorOnTouch.js b/examples/entityScripts/changeColorOnTouch.js new file mode 100644 index 0000000000..b3082fa9d5 --- /dev/null +++ b/examples/entityScripts/changeColorOnTouch.js @@ -0,0 +1,71 @@ +// +// changeColorOnTouch.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 11/1/14. +// Additions by James B. Pollack @imgntn on 9/23/2015 +// Copyright 2014 High Fidelity, Inc. +// +// ATTENTION: Requires you to run handControllerGrab.js +// This is an example of an entity script which when assigned to a non-model entity like a box or sphere, will +// change the color of the entity when you touch it. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function () { + ChangeColorOnTouch = function () { + this.oldColor = {}; + this.oldColorKnown = false; + }; + + ChangeColorOnTouch.prototype = { + + storeOldColor: function (entityID) { + var oldProperties = Entities.getEntityProperties(entityID); + this.oldColor = oldProperties.color; + this.oldColorKnown = true; + print("storing old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); + }, + + preload: function (entityID) { + print("preload"); + this.entityID = entityID; + this.storeOldColor(entityID); + }, + + startTouch: function () { + print("startTouch"); + if (!this.oldColorKnown) { + this.storeOldColor(this.entityID); + } + Entities.editEntity(this.entityID, { + color: { + red: 0, + green: 255, + blue: 255 + } + }); + }, + + continueTouch: function () { + //unused here + return; + }, + + stopTouch: function () { + print("stopTouch"); + if (this.oldColorKnown) { + print("leave restoring old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); + Entities.editEntity(this.entityID, { + color: this.oldColor + }); + } + } + + + }; + + return new ChangeColorOnTouch(); +}) \ No newline at end of file From 37ecd180545dcec7b6812af728c270518eceaaf7 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 23 Sep 2015 17:44:28 -0700 Subject: [PATCH 5/7] put distant grab inside of conditional --- examples/controllers/handControllerGrab.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 5818815bb2..c6c1befda7 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -279,8 +279,9 @@ function controller(hand, triggerAction) { } else { Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); } + Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); } - Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); + }; From 9eb3b56e5da5ee3eb4b04df4bfc3c54287f24b7e Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 24 Sep 2015 15:03:02 -0700 Subject: [PATCH 6/7] Remove space before and after function calls, add spaces btw functions --- examples/controllers/handControllerGrab.js | 165 +++++++------------ examples/entityScripts/changeColorOnTouch.js | 38 ++--- 2 files changed, 82 insertions(+), 121 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index c6c1befda7..df7f67169c 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -2,6 +2,7 @@ // examples // // Created by Eric Levin on 9/2/15 +// Additions by James B. Pollack @imgntn on 9/24/2015 // Copyright 2015 High Fidelity, Inc. // // Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects. @@ -28,21 +29,9 @@ var TRIGGER_ON_VALUE = 0.2; var DISTANCE_HOLDING_RADIUS_FACTOR = 5; // multiplied by distance between hand and object var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did -var NO_INTERSECT_COLOR = { - red: 10, - green: 10, - blue: 255 -}; // line color when pick misses -var INTERSECT_COLOR = { - red: 250, - green: 10, - blue: 10 -}; // line color when pick hits -var LINE_ENTITY_DIMENSIONS = { - x: 1000, - y: 1000, - z: 1000 -}; +var NO_INTERSECT_COLOR = { red: 10, green: 10, blue: 255}; // line color when pick misses +var INTERSECT_COLOR = { red: 250, green: 10, blue: 10}; // line color when pick hits +var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000, z: 1000}; var LINE_LENGTH = 500; @@ -65,11 +54,7 @@ var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things var RIGHT_HAND = 1; var LEFT_HAND = 0; -var ZERO_VEC = { - x: 0, - y: 0, - z: 0 -}; +var ZERO_VEC = { x: 0, y: 0, z: 0}; var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}"; var MSEC_PER_SEC = 1000.0; @@ -89,8 +74,7 @@ var STATE_RELEASE = 7; var GRAB_USER_DATA_KEY = "grabKey"; - -function controller(hand, triggerAction) { +function MyController(hand, triggerAction) { this.hand = hand; if (this.hand === RIGHT_HAND) { this.getHandPosition = MyAvatar.getRightPalmPosition; @@ -99,6 +83,7 @@ function controller(hand, triggerAction) { this.getHandPosition = MyAvatar.getLeftPalmPosition; this.getHandRotation = MyAvatar.getLeftPalmRotation; } + this.triggerAction = triggerAction; this.palm = 2 * hand; // this.tip = 2 * hand + 1; // unused, but I'm leaving this here for fear it will be needed @@ -110,37 +95,38 @@ function controller(hand, triggerAction) { this.pointer = null; // entity-id of line object this.triggerValue = 0; // rolling average of trigger value var _this = this; - this.update = function () { + + this.update = function() { switch (this.state) { - case STATE_SEARCHING: - this.search(); - this.touchTest(); - break; - case STATE_DISTANCE_HOLDING: - this.distanceHolding(); - break; - case STATE_CONTINUE_DISTANCE_HOLDING: - this.continueDistanceHolding(); - break; - case STATE_NEAR_GRABBING: - this.nearGrabbing(); - break; - case STATE_CONTINUE_NEAR_GRABBING: - this.continueNearGrabbing(); - break; - case STATE_NEAR_GRABBING_NON_COLLIDING: - this.nearGrabbingNonColliding(); - break; - case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: - this.continueNearGrabbingNonColliding(); - break; - case STATE_RELEASE: - this.release(); - break; + case STATE_SEARCHING: + this.search(); + this.touchTest(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + this.nearGrabbing(); + break; + case STATE_CONTINUE_NEAR_GRABBING: + this.continueNearGrabbing(); + break; + case STATE_NEAR_GRABBING_NON_COLLIDING: + this.nearGrabbingNonColliding(); + break; + case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: + this.continueNearGrabbingNonColliding(); + break; + case STATE_RELEASE: + this.release(); + break; } }; - _this.pointerIDs = []; - this.lineOn = function (closePoint, farPoint, color) { + + this.lineOn = function(closePoint, farPoint, color) { // draw a line if (this.pointer === null) { this.pointer = Entities.addEntity({ @@ -153,7 +139,6 @@ function controller(hand, triggerAction) { color: color, lifetime: LIFETIME }); - _this.pointerIDs.push(this.pointer); } else { Entities.editEntity(this.pointer, { position: closePoint, @@ -165,20 +150,14 @@ function controller(hand, triggerAction) { }; - - this.lineOff = function () { + this.lineOff = function() { if (this.pointer !== null) { Entities.deleteEntity(this.pointer); } - var index = _this.pointerIDs.indexOf(this.pointer); - if (index > -1) { - _this.pointerIDs.splice(index, 1); - } this.pointer = null; }; - - this.triggerSmoothedSqueezed = function () { + this.triggerSmoothedSqueezed = function() { var triggerValue = Controller.getActionValue(this.triggerAction); // smooth out trigger value this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + @@ -186,16 +165,12 @@ function controller(hand, triggerAction) { return this.triggerValue > TRIGGER_ON_VALUE; }; - - this.triggerSqueezed = function () { + this.triggerSqueezed = function() { var triggerValue = Controller.getActionValue(this.triggerAction); return triggerValue > TRIGGER_ON_VALUE; }; - - this.search = function () { - - + this.search = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -248,8 +223,7 @@ function controller(hand, triggerAction) { }; - - this.distanceHolding = function () { + this.distanceHolding = function() { var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]); @@ -282,12 +256,9 @@ function controller(hand, triggerAction) { Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab"); } - - }; - - this.continueDistanceHolding = function () { + this.continueDistanceHolding = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -319,9 +290,7 @@ function controller(hand, triggerAction) { this.currentObjectTime = now; // this doubles hand rotation - var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation, - DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), - Quat.inverse(this.handPreviousRotation)); + var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation, DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR), Quat.inverse(this.handPreviousRotation)); this.handPreviousRotation = handRotation; this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation); @@ -335,8 +304,7 @@ function controller(hand, triggerAction) { }); }; - - this.nearGrabbing = function () { + this.nearGrabbing = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -381,7 +349,7 @@ function controller(hand, triggerAction) { this.currentObjectTime = Date.now(); }; - this.continueNearGrabbing = function () { + this.continueNearGrabbing = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -400,7 +368,7 @@ function controller(hand, triggerAction) { Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); }; - this.nearGrabbingNonColliding = function () { + this.nearGrabbingNonColliding = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -409,7 +377,7 @@ function controller(hand, triggerAction) { this.state = STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING; }; - this.continueNearGrabbingNonColliding = function () { + this.continueNearGrabbingNonColliding = function() { if (!this.triggerSmoothedSqueezed()) { this.state = STATE_RELEASE; return; @@ -417,28 +385,28 @@ function controller(hand, triggerAction) { Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding"); }; - _this.allTouchedIDs = {}; - this.touchTest = function () { - //print('touch test'); + this.touchTest = function() { var maxDistance = 0.05; var leftHandPosition = MyAvatar.getLeftPalmPosition(); var rightHandPosition = MyAvatar.getRightPalmPosition(); var leftEntities = Entities.findEntities(leftHandPosition, maxDistance); var rightEntities = Entities.findEntities(rightHandPosition, maxDistance); var ids = []; + if (leftEntities.length !== 0) { - leftEntities.forEach(function (entity) { + leftEntities.forEach(function(entity) { ids.push(entity); }); } + if (rightEntities.length !== 0) { - rightEntities.forEach(function (entity) { + rightEntities.forEach(function(entity) { ids.push(entity); }); } - ids.forEach(function (id) { + ids.forEach(function(id) { var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); if (props.name === 'pointer') { @@ -471,23 +439,22 @@ function controller(hand, triggerAction) { }; - this.startTouch = function (entityID) { + this.startTouch = function(entityID) { // print('START TOUCH' + entityID); Entities.callEntityMethod(entityID, "startTouch"); }; - this.continueTouch = function (entityID) { + this.continueTouch = function(entityID) { // print('CONTINUE TOUCH' + entityID); Entities.callEntityMethod(entityID, "continueTouch"); }; - this.stopTouch = function (entityID) { + this.stopTouch = function(entityID) { // print('STOP TOUCH' + entityID); Entities.callEntityMethod(entityID, "stopTouch"); - }; - this.computeReleaseVelocity = function (deltaPosition, deltaTime, useMultiplier) { + this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) { if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) { var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime); // don't update grabbedVelocity if the trigger is off. the smoothing of the trigger @@ -504,8 +471,7 @@ function controller(hand, triggerAction) { } }; - - this.release = function () { + this.release = function() { this.lineOff(); if (this.grabbedEntity !== null && this.actionID !== null) { @@ -526,12 +492,11 @@ function controller(hand, triggerAction) { this.state = STATE_SEARCHING; }; - - this.cleanup = function () { + this.cleanup = function() { this.release(); }; - this.activateEntity = function () { + this.activateEntity = function() { var data = { activated: true, avatarId: MyAvatar.sessionUUID @@ -539,7 +504,7 @@ function controller(hand, triggerAction) { setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data); }; - this.deactivateEntity = function () { + this.deactivateEntity = function() { var data = { activated: false, avatarId: null @@ -548,22 +513,18 @@ function controller(hand, triggerAction) { }; } - -var rightController = new controller(RIGHT_HAND, Controller.findAction("RIGHT_HAND_CLICK")); -var leftController = new controller(LEFT_HAND, Controller.findAction("LEFT_HAND_CLICK")); - +var rightController = new MyController(RIGHT_HAND, Controller.findAction("RIGHT_HAND_CLICK")); +var leftController = new MyController(LEFT_HAND, Controller.findAction("LEFT_HAND_CLICK")); function update() { rightController.update(); leftController.update(); } - function cleanup() { rightController.cleanup(); leftController.cleanup(); } - Script.scriptEnding.connect(cleanup); Script.update.connect(update); \ No newline at end of file diff --git a/examples/entityScripts/changeColorOnTouch.js b/examples/entityScripts/changeColorOnTouch.js index b3082fa9d5..3a8ebae956 100644 --- a/examples/entityScripts/changeColorOnTouch.js +++ b/examples/entityScripts/changeColorOnTouch.js @@ -13,54 +13,54 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ -(function () { - ChangeColorOnTouch = function () { + +(function() { + + function ChangeColorOnTouch () { this.oldColor = {}; this.oldColorKnown = false; - }; + } ChangeColorOnTouch.prototype = { - storeOldColor: function (entityID) { + storeOldColor: function(entityID) { var oldProperties = Entities.getEntityProperties(entityID); this.oldColor = oldProperties.color; this.oldColorKnown = true; + print("storing old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); }, - preload: function (entityID) { + preload: function(entityID) { print("preload"); + this.entityID = entityID; this.storeOldColor(entityID); }, - startTouch: function () { + startTouch: function() { print("startTouch"); + if (!this.oldColorKnown) { this.storeOldColor(this.entityID); } - Entities.editEntity(this.entityID, { - color: { - red: 0, - green: 255, - blue: 255 - } - }); + + Entities.editEntity(this.entityID, {color: { red: 0, green: 255, blue: 255 }}); }, - continueTouch: function () { + continueTouch: function() { //unused here return; }, - stopTouch: function () { + stopTouch: function() { print("stopTouch"); + if (this.oldColorKnown) { print("leave restoring old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); - Entities.editEntity(this.entityID, { - color: this.oldColor - }); + Entities.editEntity(this.entityID, {color: this.oldColor}); } } @@ -68,4 +68,4 @@ }; return new ChangeColorOnTouch(); -}) \ No newline at end of file +}); \ No newline at end of file From 8dacd736df9793e9352f7008844f4144e520eef6 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 24 Sep 2015 15:27:26 -0700 Subject: [PATCH 7/7] fix weird multi line thing --- examples/controllers/handControllerGrab.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index df7f67169c..ce2f1b5249 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -272,9 +272,7 @@ function MyController(hand, triggerAction) { this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); // the action was set up on a previous call. update the targets. - var radius = Math.max(Vec3.distance(this.currentObjectPosition, - handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR, - DISTANCE_HOLDING_RADIUS_FACTOR); + var radius = Math.max(Vec3.distance(this.currentObjectPosition, handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR, DISTANCE_HOLDING_RADIUS_FACTOR); var handMoved = Vec3.subtract(handControllerPosition, this.handPreviousPosition); this.handPreviousPosition = handControllerPosition;