diff --git a/scripts/system/controllers/controllerModules/farParentGrabEntity.js b/scripts/system/controllers/controllerModules/farParentGrabEntity.js index f85869aa7f..230c4f06db 100644 --- a/scripts/system/controllers/controllerModules/farParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farParentGrabEntity.js @@ -61,6 +61,8 @@ Script.include("/~/system/libraries/controllers.js"); this.reticleMinY = MARGIN; this.reticleMaxY = 0; this.lastUnexpectedChildrenCheckTime = 0; + this.endedGrab = 0; + this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms var FAR_GRAB_JOINTS = [65527, 65528]; // FARGRAB_LEFTHAND_INDEX, FARGRAB_RIGHTHAND_INDEX @@ -144,7 +146,12 @@ Script.include("/~/system/libraries/controllers.js"); // compute the mass for the purpose of energy and how quickly to move object this.mass = this.getMass(grabbedProperties.dimensions, grabbedProperties.density); - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); + // Debounce haptic pules. Can occur as near grab controller module vacillates between being ready or not due to + // changing positions and floating point rounding. + if (Date.now() - this.endedGrab > this.MIN_HAPTIC_PULSE_INTERVAL) { + Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); + } + unhighlightTargetEntity(this.targetEntityID); var message = { hand: this.hand, @@ -256,7 +263,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endFarParentGrab = function (controllerData) { - this.hapticTargetID = null; + this.endedGrab = Date.now(); // var endProps = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; var endProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); if (this.thisFarGrabJointIsParent(endProps)) { @@ -410,11 +417,6 @@ Script.include("/~/system/libraries/controllers.js"); if (targetEntity) { var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES); if (entityIsGrabbable(gtProps)) { - // give haptic feedback - if (gtProps.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = gtProps.id; - } // if we've attempted to grab a child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, gtProps); if (entityIsGrabbable(groupRootProps)) { diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index dac98a7e0a..bb563a269c 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -24,7 +24,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.hand = hand; this.targetEntityID = null; this.actionID = null; // action this script created... - this.hapticTargetID = null; this.parameters = makeDispatcherModuleParameters( 500, @@ -164,10 +163,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); break; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { - if (props.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = props.id; - } if (!entityIsCloneable(props)) { // if we've attempted to grab a non-cloneable child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, props); @@ -199,7 +194,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); return makeRunningValues(true, [this.targetEntityID], []); } } else { - this.hapticTargetID = null; return makeRunningValues(false, [], []); } }; @@ -209,7 +203,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { this.endNearGrabAction(); - this.hapticTargetID = null; return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index b327b88e1b..13557bdb7e 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -11,7 +11,7 @@ TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME, - TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, + TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, NEAR_GRAB_DISTANCE, distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES */ @@ -24,15 +24,6 @@ Script.include("/~/system/libraries/controllers.js"); // XXX this.ignoreIK = (grabbableData.ignoreIK !== undefined) ? grabbableData.ignoreIK : true; // XXX this.kinematicGrab = (grabbableData.kinematic !== undefined) ? grabbableData.kinematic : NEAR_GRABBING_KINEMATIC; - // this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378 - var GRAB_POINT_SPHERE_OFFSET = { x: 0.04, y: 0.13, z: 0.039 }; // x = upward, y = forward, z = lateral - - function getGrabOffset(handController) { - var offset = getGrabPointSphereOffset(handController, true); - offset.y = -offset.y; - return Vec3.multiply(MyAvatar.sensorToWorldScale, offset); - } - function NearParentingGrabEntity(hand) { this.hand = hand; this.targetEntityID = null; @@ -40,7 +31,6 @@ Script.include("/~/system/libraries/controllers.js"); this.previousParentID = {}; this.previousParentJointIndex = {}; this.previouslyUnhooked = {}; - this.hapticTargetID = null; this.lastUnequipCheckTime = 0; this.autoUnequipCounter = 0; this.lastUnexpectedChildrenCheckTime = 0; @@ -138,7 +128,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endNearParentingGrabEntity = function (controllerData) { - this.hapticTargetID = null; var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; if (this.thisHandIsParent(props) && !this.robbed) { Entities.editEntity(this.targetEntityID, { @@ -169,8 +158,10 @@ Script.include("/~/system/libraries/controllers.js"); this.lastUnequipCheckTime = now; if (props.parentID === MyAvatar.SELF_ID) { var tearAwayDistance = TEAR_AWAY_DISTANCE * MyAvatar.sensorToWorldScale; - var controllerIndex = (this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand); - var controllerGrabOffset = getGrabOffset(controllerIndex); + var controllerIndex = + this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand; + var controllerGrabOffset = getGrabPointSphereOffset(controllerIndex, true); + controllerGrabOffset = Vec3.multiply(-MyAvatar.sensorToWorldScale, controllerGrabOffset); var distance = distanceBetweenEntityLocalPositionAndBoundingBox(props, controllerGrabOffset); if (distance > tearAwayDistance) { this.autoUnequipCounter++; @@ -233,21 +224,18 @@ Script.include("/~/system/libraries/controllers.js"); // nearbyEntityProperties is already sorted by length from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var nearGrabDistance = NEAR_GRAB_DISTANCE * sensorScaleFactor; + var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; - var handPosition = controllerData.controllerLocations[this.hand].position; - var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props); - var distance = Vec3.distance(handPosition, props.position); - if ((dist > TEAR_AWAY_DISTANCE) || - (distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { + var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position. + var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props); + var distance = Vec3.distance(grabPosition, props.position); + if ((dist > nearGrabDistance) || + (distance > nearGrabRadius)) { // Only smallish entities can be near grabbed. continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { - // give haptic feedback - if (props.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = props.id; - } if (!entityIsCloneable(props)) { // if we've attempted to grab a non-cloneable child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, props); @@ -284,7 +272,6 @@ Script.include("/~/system/libraries/controllers.js"); return makeRunningValues(true, [this.targetEntityID], []); } } else { - this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); } @@ -303,7 +290,6 @@ Script.include("/~/system/libraries/controllers.js"); // entity was deleted this.grabbing = false; this.targetEntityID = null; - this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index e9d5255d28..ab2801087e 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -53,6 +53,7 @@ TEAR_AWAY_DISTANCE:true, TEAR_AWAY_COUNT:true, TEAR_AWAY_CHECK_TIME:true, + NEAR_GRAB_DISTANCE: true, distanceBetweenPointAndEntityBoundingBox:true, entityIsEquipped:true, entityIsFarGrabbedByOther:true, @@ -99,6 +100,10 @@ NEAR_GRAB_RADIUS = 1.0; TEAR_AWAY_DISTANCE = 0.15; // ungrab an entity if its bounding-box moves this far from the hand TEAR_AWAY_COUNT = 2; // multiply by TEAR_AWAY_CHECK_TIME to know how long the item must be away TEAR_AWAY_CHECK_TIME = 0.15; // seconds, duration between checks + +NEAR_GRAB_DISTANCE = 0.14; // Grab an entity if its bounding box is within this distance. +// Smaller than TEAR_AWAY_DISTANCE for hysteresis. + DISPATCHER_HOVERING_LIST = "dispactherHoveringList"; DISPATCHER_HOVERING_STYLE = { isOutlineSmooth: true,