From e0b08a5e4e108500f2fbb3f62f70cf846ffee61c Mon Sep 17 00:00:00 2001 From: volansystech Date: Fri, 7 Apr 2017 21:55:26 +0530 Subject: [PATCH 1/6] Initial Commit of far to near grab conversion. Works only if object drawn at chest level And Object is near by to hand. --- .../system/controllers/handControllerGrab.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 9a6760a37b..e42b8d1c13 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -189,6 +189,10 @@ var blacklist = []; var FORBIDDEN_GRAB_NAMES = ["Grab Debug Entity", "grab pointer"]; var FORBIDDEN_GRAB_TYPES = ["Unknown", "Light", "PolyLine", "Zone"]; +var MAX_SECONDARY_PRESS_VALUE = 1; +var MIN_SECONDARY_PRESS_VALUE = 0; +var farToNearGrab = false; + var holdEnabled = true; var nearGrabEnabled = true; var farGrabEnabled = true; @@ -2082,6 +2086,15 @@ function MyController(hand) { return true; }; + this.entityIsFartoNearGrabbable = function (objectPosition, handPosition, maxDistance) { + var distanceToObjectFromHand = Vec3.length(Vec3.subtract(handPosition, objectPosition)); + + if (distanceToObjectFromHand > maxDistance) { + return false; + } + return true; + }; + this.chooseNearEquipHotspots = function(candidateEntities, distance) { var equippableHotspots = flatten(candidateEntities.map(function(entityID) { return _this.collectEquipHotspots(entityID); @@ -2661,6 +2674,15 @@ function MyController(hand) { this.grabbedThingID); var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, this.currentObjectPosition)); + var controllerLocation = getControllerWorldLocation(this.handToController(), true); + var handPosition = controllerLocation.position; + + //Far to Near Grab: If object is draw by user inside NEAR_GRAB_MAX_DISTANCE, grab it + if (this.entityIsFartoNearGrabbable(this.currentObjectPosition, handPosition, NEAR_GRAB_MAX_DISTANCE)) { + this.secondaryPress(MAX_SECONDARY_PRESS_VALUE); + this.farToNearGrab = true; + this.setState(STATE_NEAR_GRABBING, "near grab entity '" + this.grabbedThingID + "'"); + } var success = Entities.updateAction(this.grabbedThingID, this.actionID, { targetPosition: newTargetPosition, linearTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), @@ -3036,6 +3058,11 @@ function MyController(hand) { this.nearGrabbing = function(deltaTime, timestamp) { this.grabPointSphereOff(); + if (this.farToNearGrab && !this.triggerClicked) { + this.farToNearGrab = false; + this.secondaryPress(MIN_SECONDARY_PRESS_VALUE); + } + if (this.state == STATE_NEAR_GRABBING && (!this.triggerClicked && this.secondaryReleased())) { this.callEntityMethodOnGrabbed("releaseGrab"); this.setState(STATE_OFF, "trigger released"); From 99af493ac8bc221e559713e87933d2b4c44f243f Mon Sep 17 00:00:00 2001 From: volansystech Date: Tue, 11 Apr 2017 21:57:01 +0530 Subject: [PATCH 2/6] Resolved the issue from the Initial commit - "grabbedEntity" stays into that grabbed position for a few seconds (hanging into mid of air) before dropping down automatically. Successfully converted far grab into near grab when entity is closer to the Avatar. When Trigger is released after converted far grab into near grab far, the obect is dropped successfully. --- .../system/controllers/handControllerGrab.js | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index e42b8d1c13..317a6d5ef8 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -155,6 +155,7 @@ var INCHES_TO_METERS = 1.0 / 39.3701; // these control how long an abandoned pointer line or action will hang around var ACTION_TTL = 15; // seconds +var ACTION_TTL_ZERO = 0; // seconds var ACTION_TTL_REFRESH = 5; var PICKS_PER_SECOND_PER_HAND = 60; var MSECS_PER_SEC = 1000.0; @@ -189,13 +190,10 @@ var blacklist = []; var FORBIDDEN_GRAB_NAMES = ["Grab Debug Entity", "grab pointer"]; var FORBIDDEN_GRAB_TYPES = ["Unknown", "Light", "PolyLine", "Zone"]; -var MAX_SECONDARY_PRESS_VALUE = 1; -var MIN_SECONDARY_PRESS_VALUE = 0; -var farToNearGrab = false; - var holdEnabled = true; var nearGrabEnabled = true; var farGrabEnabled = true; +var farToNearGrab = false; var myAvatarScalingEnabled = true; var objectScalingEnabled = true; var mostRecentSearchingHand = RIGHT_HAND; @@ -2086,7 +2084,7 @@ function MyController(hand) { return true; }; - this.entityIsFartoNearGrabbable = function (objectPosition, handPosition, maxDistance) { + this.entityIsFarToNearGrabbable = function (objectPosition, handPosition, maxDistance) { var distanceToObjectFromHand = Vec3.length(Vec3.subtract(handPosition, objectPosition)); if (distanceToObjectFromHand > maxDistance) { @@ -2677,11 +2675,27 @@ function MyController(hand) { var controllerLocation = getControllerWorldLocation(this.handToController(), true); var handPosition = controllerLocation.position; + var ttl = ACTION_TTL; + //Far to Near Grab: If object is draw by user inside NEAR_GRAB_MAX_DISTANCE, grab it - if (this.entityIsFartoNearGrabbable(this.currentObjectPosition, handPosition, NEAR_GRAB_MAX_DISTANCE)) { - this.secondaryPress(MAX_SECONDARY_PRESS_VALUE); + if (this.entityIsFarToNearGrabbable(this.currentObjectPosition, handPosition, NEAR_GRAB_MAX_DISTANCE)) { this.farToNearGrab = true; - this.setState(STATE_NEAR_GRABBING, "near grab entity '" + this.grabbedThingID + "'"); + ttl = ACTION_TTL_ZERO; // Overriding ACTION_TTL,Assign ACTION_TTL_ZERO so that the object is dropped down immediately after the trigger is released. + + var success = Entities.updateAction(this.grabbedThingID, this.actionID, { + targetPosition: newTargetPosition, + linearTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), + targetRotation: this.currentObjectRotation, + angularTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), + ttl: ttl + }); + if (success) { + this.actionTimeout = now + (ttl * MSECS_PER_SEC); + } else { + print("continueDistanceHolding -- updateAction failed"); + } + this.setState(STATE_NEAR_GRABBING , "near grab entity '" + this.grabbedThingID + "'"); + return; } var success = Entities.updateAction(this.grabbedThingID, this.actionID, { targetPosition: newTargetPosition, @@ -3058,9 +3072,13 @@ function MyController(hand) { this.nearGrabbing = function(deltaTime, timestamp) { this.grabPointSphereOff(); - if (this.farToNearGrab && !this.triggerClicked) { - this.farToNearGrab = false; - this.secondaryPress(MIN_SECONDARY_PRESS_VALUE); + var ttl = ACTION_TTL; + + if (this.farToNearGrab) { + ttl = ACTION_TTL_ZERO; // farToNearGrab - Assign ACTION_TTL_ZERO so that, the object is dropped down immediately after the trigger is released. + if(!this.triggerClicked){ + this.farToNearGrab = false; + } } if (this.state == STATE_NEAR_GRABBING && (!this.triggerClicked && this.secondaryReleased())) { @@ -3230,20 +3248,20 @@ function MyController(hand) { this.maybeScale(props); } - if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSECS_PER_SEC) { + if (this.actionID && this.actionTimeout - now < ttl * MSECS_PER_SEC) { // if less than a 5 seconds left, refresh the actions ttl var success = Entities.updateAction(this.grabbedThingID, this.actionID, { hand: this.hand === RIGHT_HAND ? "right" : "left", timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, - ttl: ACTION_TTL, + ttl: ttl, kinematic: NEAR_GRABBING_KINEMATIC, kinematicSetVelocity: true, ignoreIK: this.ignoreIK }); if (success) { - this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC); + this.actionTimeout = now + (ttl * MSECS_PER_SEC); } else { print("continueNearGrabbing -- updateAction failed"); Entities.deleteAction(this.grabbedThingID, this.actionID); From 5639a3f92a476cd9194e0bf156e30c0c6e6d7d53 Mon Sep 17 00:00:00 2001 From: volansystech Date: Wed, 12 Apr 2017 20:08:26 +0530 Subject: [PATCH 3/6] Far to near grab: If the object is capable of being equipped, transfer from far-grab to an equipped state. --- .../system/controllers/handControllerGrab.js | 63 +++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 317a6d5ef8..828a1926e1 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2121,8 +2121,36 @@ function MyController(hand) { return null; } }; + + this.chooseNearEquipHotspotsForDistanceToNearEquip = function(candidateEntities, distance) { + var equippableHotspots = flatten(candidateEntities.map(function(entityID) { + return _this.collectEquipHotspots(entityID); + })).filter(function(hotspot) { + return (Vec3.distance(hotspot.worldPosition, getControllerWorldLocation(_this.handToController(), true).position) < + hotspot.radius + distance); + }); + return equippableHotspots; + }; - this.searchEnter = function() { + this.chooseBestEquipHotspotForDistanceToNearEquip = function(candidateEntities) { + var DISTANCE = 1; + var equippableHotspots = this.chooseNearEquipHotspotsForDistanceToNearEquip(candidateEntities, DISTANCE); + var _this = this; + if (equippableHotspots.length > 0) { + // sort by distance + equippableHotspots.sort(function(a, b) { + var handControllerLocation = getControllerWorldLocation(_this.handToController(), true); + var aDistance = Vec3.distance(a.worldPosition, handControllerLocation.position); + var bDistance = Vec3.distance(b.worldPosition, handControllerLocation.position); + return aDistance - bDistance; + }); + return equippableHotspots[0]; + } else { + return null; + } + }; + + this.searchEnter = function() { mostRecentSearchingHand = this.hand; var rayPickInfo = this.calcRayPickInfo(this.hand); if (rayPickInfo.entityID || rayPickInfo.overlayID) { @@ -2675,22 +2703,47 @@ function MyController(hand) { var controllerLocation = getControllerWorldLocation(this.handToController(), true); var handPosition = controllerLocation.position; - var ttl = ACTION_TTL; + var candidateHotSpotEntities = Entities.findEntities(handPosition,MAX_EQUIP_HOTSPOT_RADIUS); + entityPropertiesCache.addEntities(candidateHotSpotEntities); + + var potentialEquipHotspot = this.chooseBestEquipHotspotForDistanceToNearEquip(candidateHotSpotEntities); + if (potentialEquipHotspot) { + if ((this.triggerSmoothedGrab() || this.secondarySqueezed()) && holdEnabled) { + this.grabbedHotspot = potentialEquipHotspot; + this.grabbedThingID = potentialEquipHotspot.entityID; + this.grabbedIsOverlay = false; + + var success = Entities.updateAction(this.grabbedThingID, this.actionID, { + targetPosition: newTargetPosition, + linearTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), + targetRotation: this.currentObjectRotation, + angularTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), + ttl: ACTION_TTL_ZERO + }); + + if (success) { + this.actionTimeout = now + (ACTION_TTL_ZERO * MSECS_PER_SEC); + } else { + print("continueDistanceHolding -- updateAction failed"); + } + this.setState(STATE_HOLD, "equipping '" + entityPropertiesCache.getProps(this.grabbedThingID).name + "'"); + return; + } + } //Far to Near Grab: If object is draw by user inside NEAR_GRAB_MAX_DISTANCE, grab it if (this.entityIsFarToNearGrabbable(this.currentObjectPosition, handPosition, NEAR_GRAB_MAX_DISTANCE)) { this.farToNearGrab = true; - ttl = ACTION_TTL_ZERO; // Overriding ACTION_TTL,Assign ACTION_TTL_ZERO so that the object is dropped down immediately after the trigger is released. var success = Entities.updateAction(this.grabbedThingID, this.actionID, { targetPosition: newTargetPosition, linearTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), targetRotation: this.currentObjectRotation, angularTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), - ttl: ttl + ttl: ACTION_TTL_ZERO // Overriding ACTION_TTL,Assign ACTION_TTL_ZERO so that the object is dropped down immediately after the trigger is released. }); if (success) { - this.actionTimeout = now + (ttl * MSECS_PER_SEC); + this.actionTimeout = now + (ACTION_TTL_ZERO * MSECS_PER_SEC); } else { print("continueDistanceHolding -- updateAction failed"); } From 70855b1c5318288040314e6008b69e2ef7d6f1ae Mon Sep 17 00:00:00 2001 From: volansystech Date: Thu, 13 Apr 2017 18:21:42 +0530 Subject: [PATCH 4/6] Improve the accuracy of Far to near Equip State. --- .../system/controllers/handControllerGrab.js | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 828a1926e1..c25b6c8cc4 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -111,12 +111,12 @@ var EQUIP_RADIUS = 0.2; // radius used for palm vs equip-hotspot for equipping. // has reached the required position, and then grow larger once the hand is close enough to equip. var EQUIP_HOTSPOT_RENDER_RADIUS = 0.0; // radius used for palm vs equip-hotspot for rendering hot-spots var MAX_EQUIP_HOTSPOT_RADIUS = 1.0; - +var MAX_FAR_TO_NEAR_EQUIP_HOTSPOT_RADIUS = 0.5; // radius used for far to near equipping object. var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position var NEAR_GRAB_RADIUS = 0.1; // radius used for palm vs object for near grabbing. var NEAR_GRAB_MAX_DISTANCE = 1.0; // you cannot grab objects that are this far away from your hand - +var FAR_TO_NEAR_GRAB_MAX_DISTANCE = 0.75; // In far to near grabbing conversion,grab the object if distancetoObject from hand is less than this. var NEAR_GRAB_PICK_RADIUS = 0.25; // radius used for search ray vs object for near grabbing. var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed @@ -2122,7 +2122,7 @@ function MyController(hand) { } }; - this.chooseNearEquipHotspotsForDistanceToNearEquip = function(candidateEntities, distance) { + this.chooseNearEquipHotspotsForFarToNearEquip = function(candidateEntities, distance) { var equippableHotspots = flatten(candidateEntities.map(function(entityID) { return _this.collectEquipHotspots(entityID); })).filter(function(hotspot) { @@ -2132,9 +2132,9 @@ function MyController(hand) { return equippableHotspots; }; - this.chooseBestEquipHotspotForDistanceToNearEquip = function(candidateEntities) { + this.chooseBestEquipHotspotForFarToNearEquip = function(candidateEntities) { var DISTANCE = 1; - var equippableHotspots = this.chooseNearEquipHotspotsForDistanceToNearEquip(candidateEntities, DISTANCE); + var equippableHotspots = this.chooseNearEquipHotspotsForFarToNearEquip(candidateEntities, DISTANCE); var _this = this; if (equippableHotspots.length > 0) { // sort by distance @@ -2700,14 +2700,12 @@ function MyController(hand) { this.grabbedThingID); var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, this.currentObjectPosition)); - var controllerLocation = getControllerWorldLocation(this.handToController(), true); - var handPosition = controllerLocation.position; - var candidateHotSpotEntities = Entities.findEntities(handPosition,MAX_EQUIP_HOTSPOT_RADIUS); + var candidateHotSpotEntities = Entities.findEntities(controllerLocation.position,MAX_FAR_TO_NEAR_EQUIP_HOTSPOT_RADIUS); entityPropertiesCache.addEntities(candidateHotSpotEntities); - var potentialEquipHotspot = this.chooseBestEquipHotspotForDistanceToNearEquip(candidateHotSpotEntities); - if (potentialEquipHotspot) { + var potentialEquipHotspot = this.chooseBestEquipHotspotForFarToNearEquip(candidateHotSpotEntities); + if (potentialEquipHotspot && (potentialEquipHotspot.entityID == this.grabbedThingID)) { if ((this.triggerSmoothedGrab() || this.secondarySqueezed()) && holdEnabled) { this.grabbedHotspot = potentialEquipHotspot; this.grabbedThingID = potentialEquipHotspot.entityID; @@ -2731,8 +2729,8 @@ function MyController(hand) { } } - //Far to Near Grab: If object is draw by user inside NEAR_GRAB_MAX_DISTANCE, grab it - if (this.entityIsFarToNearGrabbable(this.currentObjectPosition, handPosition, NEAR_GRAB_MAX_DISTANCE)) { + //Far to Near Grab: If object is draw by user inside FAR_TO_NEAR_GRAB_MAX_DISTANCE, grab it + if (this.entityIsFarToNearGrabbable(this.currentObjectPosition, controllerLocation.position, FAR_TO_NEAR_GRAB_MAX_DISTANCE)) { this.farToNearGrab = true; var success = Entities.updateAction(this.grabbedThingID, this.actionID, { From abc87c0338c1417a86a9813a57a039864eacc256 Mon Sep 17 00:00:00 2001 From: volansystech Date: Thu, 20 Apr 2017 23:37:16 +0530 Subject: [PATCH 5/6] Increased accuracy for converting far-grab to near-grab for every object Near-grab radius reduced to its default = 0.3 --- scripts/system/controllers/handControllerGrab.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index c25b6c8cc4..97bf213b4e 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -116,7 +116,7 @@ var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their var NEAR_GRAB_RADIUS = 0.1; // radius used for palm vs object for near grabbing. var NEAR_GRAB_MAX_DISTANCE = 1.0; // you cannot grab objects that are this far away from your hand -var FAR_TO_NEAR_GRAB_MAX_DISTANCE = 0.75; // In far to near grabbing conversion,grab the object if distancetoObject from hand is less than this. +var FAR_TO_NEAR_GRAB_MAX_DISTANCE = 0.3; // In far to near grabbing conversion,grab the object if distancetoObject from hand is less than this. var NEAR_GRAB_PICK_RADIUS = 0.25; // radius used for search ray vs object for near grabbing. var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed @@ -2728,9 +2728,9 @@ function MyController(hand) { return; } } - + var rayPositionOnEntity = Vec3.subtract(grabbedProperties.position, this.offsetPosition); //Far to Near Grab: If object is draw by user inside FAR_TO_NEAR_GRAB_MAX_DISTANCE, grab it - if (this.entityIsFarToNearGrabbable(this.currentObjectPosition, controllerLocation.position, FAR_TO_NEAR_GRAB_MAX_DISTANCE)) { + if (this.entityIsFarToNearGrabbable(rayPositionOnEntity, controllerLocation.position, FAR_TO_NEAR_GRAB_MAX_DISTANCE)) { this.farToNearGrab = true; var success = Entities.updateAction(this.grabbedThingID, this.actionID, { From 9e2899678a95c882f1de9749029a11433ccb2487 Mon Sep 17 00:00:00 2001 From: volansystech Date: Thu, 20 Apr 2017 23:54:41 +0530 Subject: [PATCH 6/6] Resolving conflicts of #21206 --- scripts/system/controllers/handControllerGrab.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 97bf213b4e..7b00b78e17 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -75,7 +75,7 @@ var WEB_TOUCH_Y_OFFSET = 0.05; // how far forward (or back with a negative numbe // // distant manipulation // - +var linearTimeScale = 0; var DISTANCE_HOLDING_RADIUS_FACTOR = 3.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_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified @@ -2150,7 +2150,7 @@ function MyController(hand) { } }; - this.searchEnter = function() { + this.searchEnter = function() { mostRecentSearchingHand = this.hand; var rayPickInfo = this.calcRayPickInfo(this.hand); if (rayPickInfo.entityID || rayPickInfo.overlayID) { @@ -2565,7 +2565,7 @@ function MyController(hand) { this.mass = this.getMass(grabbedProperties.dimensions, grabbedProperties.density); var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, grabbedProperties.position)); var timeScale = this.distanceGrabTimescale(this.mass, distanceToObject); - + this.linearTimeScale = timeScale; this.actionID = NULL_UUID; this.actionID = Entities.addAction("spring", this.grabbedThingID, { targetPosition: this.currentObjectPosition, @@ -2615,7 +2615,6 @@ function MyController(hand) { var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition); var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES); - var now = Date.now(); var deltaObjectTime = (now - this.currentObjectTime) / MSECS_PER_SEC; // convert to seconds this.currentObjectTime = now; @@ -2663,11 +2662,9 @@ function MyController(hand) { if (this.grabRadius < MINIMUM_GRAB_RADIUS) { this.grabRadius = MINIMUM_GRAB_RADIUS; } - var newTargetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation)); newTargetPosition = Vec3.sum(newTargetPosition, worldControllerPosition); newTargetPosition = Vec3.sum(newTargetPosition, this.offsetPosition); - var objectToAvatar = Vec3.subtract(this.currentObjectPosition, MyAvatar.position); var handControllerData = getEntityCustomData('handControllerKey', this.grabbedThingID, defaultMoveWithHeadData); if (handControllerData.disableMoveWithHead !== true) { @@ -2748,9 +2745,14 @@ function MyController(hand) { this.setState(STATE_NEAR_GRABBING , "near grab entity '" + this.grabbedThingID + "'"); return; } + + this.linearTimeScale = (this.linearTimeScale / 2); + if (this.linearTimeScale <= DISTANCE_HOLDING_ACTION_TIMEFRAME) { + this.linearTimeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME; + } var success = Entities.updateAction(this.grabbedThingID, this.actionID, { targetPosition: newTargetPosition, - linearTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), + linearTimeScale: this.linearTimeScale, targetRotation: this.currentObjectRotation, angularTimeScale: this.distanceGrabTimescale(this.mass, distanceToObject), ttl: ACTION_TTL