From ddca25672fd1e56763eefe159ceb8a3e5069133b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 15 Aug 2017 14:14:28 -0700 Subject: [PATCH] trying to get near-triggering working --- .../controllers/controllerDispatcher.js | 21 +--- .../controllers/controllerDispatcherUtils.js | 42 ++++++- .../controllerModules/nearActionGrabEntity.js | 34 ++--- .../controllerModules/nearParentGrabEntity.js | 19 +-- .../controllerModules/nearTrigger.js | 119 ++++++++++++++++++ .../system/controllers/controllerScripts.js | 3 +- 6 files changed, 182 insertions(+), 56 deletions(-) create mode 100644 scripts/system/controllers/controllerModules/nearTrigger.js diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 959f217eb4..94bc9851da 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -9,7 +9,7 @@ /* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, RayPick, controllerDispatcherPlugins, controllerDispatcherPluginsNeedSort, entityIsGrabbable, - LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE + LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES */ controllerDispatcherPlugins = {}; @@ -25,25 +25,6 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); var NEAR_MIN_RADIUS = 0.1; var NEAR_MAX_RADIUS = 1.0; - var DISPATCHER_PROPERTIES = [ - "position", - "registrationPoint", - "rotation", - "gravity", - "collidesWith", - "dynamic", - "collisionless", - "locked", - "name", - "shapeType", - "parentID", - "parentJointIndex", - "density", - "dimensions", - "userData" - ]; - - var TARGET_UPDATE_HZ = 60; // 50hz good enough, but we're using update var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ; var lastInterval = Date.now(); diff --git a/scripts/system/controllers/controllerDispatcherUtils.js b/scripts/system/controllers/controllerDispatcherUtils.js index 5b6d624892..913faf60bf 100644 --- a/scripts/system/controllers/controllerDispatcherUtils.js +++ b/scripts/system/controllers/controllerDispatcherUtils.js @@ -18,6 +18,7 @@ COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, NEAR_GRAB_RADIUS, + DISPATCHER_PROPERTIES, Entities, makeDispatcherModuleParameters, makeRunningValues, @@ -34,7 +35,8 @@ projectOntoEntityXYPlane, projectOntoOverlayXYPlane, entityHasActions, - ensureDynamic + ensureDynamic, + findGroupParent */ MSECS_PER_SEC = 1000.0; @@ -72,6 +74,27 @@ NEAR_GRAB_RADIUS = 0.1; +DISPATCHER_PROPERTIES = [ + "position", + "registrationPoint", + "rotation", + "gravity", + "collidesWith", + "dynamic", + "collisionless", + "locked", + "name", + "shapeType", + "parentID", + "parentJointIndex", + "density", + "dimensions", + "userData" +]; + + + + // priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step // activitySlots -- indicates which "slots" must not yet be in use for this module to start // requiredDataForReady -- which "situation" parts this module looks at to decide if it will start @@ -137,6 +160,9 @@ getGrabbableData = function (props) { if (!grabbableData.hasOwnProperty("kinematicGrab")) { grabbableData.kinematicGrab = true; } + if (!grabbableData.hasOwnProperty("wantsTrigger")) { + grabbableData.wantsTrigger = false; + } return grabbableData; }; @@ -258,3 +284,17 @@ ensureDynamic = function (entityID) { } } }; + +findGroupParent = function (controllerData, targetProps) { + while (targetProps.parentID && targetProps.parentID != NULL_UUID) { + var parentProps = Entities.getEntityProperties(targetProps.parentID, DISPATCHER_PROPERTIES); + if (!parentProps) { + break; + } + parentProps.id = targetProps.parentID; + targetProps = parentProps; + controllerData.nearbyEntityPropertiesByID[targetProps.id] = targetProps; + } + + return targetProps; +}; diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 217e90ef88..a2673f8bca 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -9,7 +9,7 @@ getControllerJointIndex, getGrabbableData, NULL_UUID, enableDispatcherModule, disableDispatcherModule, propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable, Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues, - TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS + TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent */ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); @@ -152,6 +152,11 @@ Script.include("/~/system/libraries/controllers.js"); break; } if (entityIsGrabbable(props)) { + // if we've attempted to grab a child, roll up to the root of the tree + var groupRootProps = findGroupParent(controllerData, props); + if (entityIsGrabbable(groupRootProps)) { + return groupRootProps; + } return props; } } @@ -162,23 +167,18 @@ Script.include("/~/system/libraries/controllers.js"); this.targetEntityID = null; if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { - makeRunningValues(false, [], []); + return makeRunningValues(false, [], []); } var targetProps = this.getTargetProps(controllerData); if (targetProps) { if (!propsArePhysical(targetProps)) { - // XXX make sure no highlights are enabled from this module return makeRunningValues(false, [], []); // let nearParentGrabEntity handle it } else { this.targetEntityID = targetProps.id; - ContextOverlay.entityWithContextOverlay = this.targetEntityID; - ContextOverlay.enabled = true; - // XXX highlight this.targetEntityID here return makeRunningValues(true, [this.targetEntityID], []); } } else { - // XXX make sure no highlights are enabled from this module return makeRunningValues(false, [], []); } }; @@ -204,26 +204,8 @@ Script.include("/~/system/libraries/controllers.js"); var targetProps = this.getTargetProps(controllerData); if (targetProps) { - - // XXX - var rayPickInfo = controllerData.rayPicks[this.hand]; - var pointerEvent = { - type: "Move", - id: this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(rayPickInfo.entityID, rayPickInfo.intersection, targetProps), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.normal, - direction: rayPickInfo.searchRay.direction, - button: "Secondary" - }; - if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.entityID, pointerEvent)) { - } - // XXX - - if (controllerData.triggerClicks[this.hand] == 1) { - // stop highlighting, switch to grabbing - // XXX stop highlight here + // switch to grabbing this.startNearGrabAction(controllerData, targetProps); } } diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index c5ca95fe3b..7d5d1163bf 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -9,7 +9,8 @@ /* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule, propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, - makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS + makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, + findGroupParent, Vec3 */ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); @@ -29,7 +30,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); this.parameters = makeDispatcherModuleParameters( 500, - this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], + this.hand === RIGHT_HAND ? ["rightHand", "rightHandTrigger"] : ["leftHand", "leftHandTrigger"], [], 100); @@ -64,6 +65,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); }; this.startNearParentingGrabEntity = function (controllerData, targetProps) { + Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); var handJointIndex; @@ -135,6 +137,11 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); break; } if (entityIsGrabbable(props)) { + // if we've attempted to grab a child, roll up to the root of the tree + var groupRootProps = findGroupParent(controllerData, props); + if (entityIsGrabbable(groupRootProps)) { + return groupRootProps; + } return props; } } @@ -146,21 +153,18 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); this.grabbing = false; if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { - makeRunningValues(false, [], []); + return makeRunningValues(false, [], []); } var targetProps = this.getTargetProps(controllerData); if (targetProps) { if (propsArePhysical(targetProps)) { - // XXX make sure no highlights are enabled from this module return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it } else { this.targetEntityID = targetProps.id; - // XXX highlight this.targetEntityID here return makeRunningValues(true, [this.targetEntityID], []); } } else { - // XXX make sure no highlights are enabled from this module return makeRunningValues(false, [], []); } }; @@ -181,8 +185,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); return readiness; } if (controllerData.triggerClicks[this.hand] == 1) { - // stop highlighting, switch to grabbing - // XXX stop highlight here + // switch to grab var targetProps = this.getTargetProps(controllerData); if (targetProps) { this.grabbing = true; diff --git a/scripts/system/controllers/controllerModules/nearTrigger.js b/scripts/system/controllers/controllerModules/nearTrigger.js new file mode 100644 index 0000000000..93f509c6b4 --- /dev/null +++ b/scripts/system/controllers/controllerModules/nearTrigger.js @@ -0,0 +1,119 @@ +"use strict"; + +// nearParentGrabEntity.js +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + + +/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, + enableDispatcherModule, disableDispatcherModule, getGrabbableData, Vec3, + TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS +*/ + +Script.include("/~/system/controllers/controllerDispatcherUtils.js"); + +(function() { + + function entityWantsNearTrigger(props) { + return getGrabbableData(props).triggerable; + } + + function NearTriggerEntity(hand) { + this.hand = hand; + this.targetEntityID = null; + this.grabbing = false; + this.previousParentID = {}; + this.previousParentJointIndex = {}; + this.previouslyUnhooked = {}; + + this.parameters = makeDispatcherModuleParameters( + 200, + this.hand === RIGHT_HAND ? ["rightHandTrigger"] : ["leftHandTrigger"], + [], + 100); + + this.getTargetProps = function (controllerData) { + // nearbyEntityProperties is already sorted by length from controller + var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; + for (var i = 0; i < nearbyEntityProperties.length; i++) { + var props = nearbyEntityProperties[i]; + var handPosition = controllerData.controllerLocations[this.hand].position; + var distance = Vec3.distance(props.position, handPosition); + // if (distance > NEAR_GRAB_RADIUS) { + // print("QQQ nop 0"); + // break; + // } + if (entityWantsNearTrigger(props)) { + return props; + } else { + print("QQQ nop 1"); + } + } + return null; + }; + + this.startNearTrigger = function (controllerData) { + Controller.triggerShortHapticPulse(1.0, this.hand); + var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; + Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args); + }; + + this.continueNearTrigger = function (controllerData) { + var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; + Entities.callEntityMethod(this.targetEntityID, "continueNearTrigger", args); + }; + + this.endNearTrigger = function (controllerData) { + var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; + Entities.callEntityMethod(this.targetEntityID, "endNearTrigger", args); + }; + + this.isReady = function (controllerData) { + this.targetEntityID = null; + + if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { + return makeRunningValues(false, [], []); + } + + var targetProps = this.getTargetProps(controllerData); + if (targetProps) { + this.targetEntityID = targetProps.id; + this.startNearTrigger(controllerData); + return makeRunningValues(true, [this.targetEntityID], []); + } else { + return makeRunningValues(false, [], []); + } + }; + + this.run = function (controllerData) { + if (controllerData.triggerClicks[this.hand] == 0) { + this.endNearTrigger(controllerData); + return makeRunningValues(false, [], []); + } + + this.continueNearTrigger(controllerData); + return makeRunningValues(true, [this.targetEntityID], []); + }; + + this.cleanup = function () { + if (this.targetEntityID) { + this.endNearParentingGrabEntity(); + } + }; + } + + var leftNearParentingGrabEntity = new NearTriggerEntity(LEFT_HAND); + var rightNearParentingGrabEntity = new NearTriggerEntity(RIGHT_HAND); + + enableDispatcherModule("LeftNearParentingGrabEntity", leftNearParentingGrabEntity); + enableDispatcherModule("RightNearParentingGrabEntity", rightNearParentingGrabEntity); + + this.cleanup = function () { + leftNearParentingGrabEntity.cleanup(); + rightNearParentingGrabEntity.cleanup(); + disableDispatcherModule("LeftNearParentingGrabEntity"); + disableDispatcherModule("RightNearParentingGrabEntity"); + }; + Script.scriptEnding.connect(this.cleanup); +}()); diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index ea45f0a2c6..d41dec6de1 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -24,7 +24,8 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/nearActionGrabEntity.js", "controllerModules/farActionGrabEntity.js", "controllerModules/tabletStylusInput.js", - "controllerModules/equipEntity.js" + "controllerModules/equipEntity.js", + "controllerModules/nearTrigger.js" ]; var DEBUG_MENU_ITEM = "Debug defaultScripts.js";