Merge pull request #14464 from ctrlaltdavid/M17406

Fix fax grab to near grab transition and haptic pulses
This commit is contained in:
Jeff Clinton 2018-11-30 09:18:51 -08:00 committed by GitHub
commit 04f09d70e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 40 deletions

View file

@ -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)) {

View file

@ -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, [], []);
}

View file

@ -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, [], []);
}

View file

@ -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,