diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 58f032de08..b7fdacfe38 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -404,6 +404,7 @@ Script.include("/~/system/libraries/Xform.js"); this.endNearGrabAction(); Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); + this.highlightedEntity = null; return makeRunningValues(false, [], []); } this.intersectionDistance = controllerData.rayPicks[this.hand].distance; @@ -575,6 +576,7 @@ Script.include("/~/system/libraries/Xform.js"); this.endNearGrabAction(); Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); + this.highlightedEntity = null; return makeRunningValues(false, [], []); } } diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js new file mode 100644 index 0000000000..de58c5a388 --- /dev/null +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -0,0 +1,88 @@ +"use strict"; + +// highlightNearbyEntities.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, Controller, RIGHT_HAND, LEFT_HAND, MyAvatar, getGrabPointSphereOffset, + makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters, + PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, + DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData, makeLaserParams +*/ + +(function () { + Script.include("/~/system/libraries/controllerDispatcherUtils.js"); + Script.include("/~/system/libraries/controllers.js"); + var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); + function HighlightNearbyEntities(hand) { + this.hand = hand; + this.highlightedEntities = []; + + this.parameters = dispatcherUtils.makeDispatcherModuleParameters( + 480, + this.hand === dispatcherUtils.RIGHT_HAND ? ["rightHand"] : ["leftHand"], + [], + 100); + + + this.isGrabable = function(controllerData, props) { + if (dispatcherUtils.entityIsGrabbable(props) || dispatcherUtils.entityIsCloneable(props)) { + // if we've attempted to grab a child, roll up to the root of the tree + var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props); + if (dispatcherUtils.entityIsGrabbable(groupRootProps)) { + return true; + } + return true; + } + return false; + }; + + this.hasHyperLink = function(props) { + return (props.href !== "" && props.href !== undefined); + }; + + this.highlightEntities = function(controllerData) { + if (this.highlightedEntities.length > 0) { + dispatcherUtils.clearHighlightedEntities(); + this.highlightedEntities = []; + } + + var nearbyEntitiesProperties = controllerData.nearbyEntityProperties[this.hand]; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + for (var i = 0; i < nearbyEntitiesProperties.length; i++) { + var props = nearbyEntitiesProperties[i]; + if (props.distance > dispatcherUtils.NEAR_GRAB_RADIUS * sensorScaleFactor) { + continue; + } + if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) { + dispatcherUtils.highlightTargetEntity(props.id); + this.highlightedEntities.push(props.id); + } + } + }; + + this.isReady = function(controllerData) { + this.highlightEntities(controllerData); + return dispatcherUtils.makeRunningValues(false, [], []); + }; + + this.run = function(controllerData) { + return this.isReady(controllerData); + }; + } + + var leftHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.LEFT_HAND); + var rightHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.RIGHT_HAND); + + dispatcherUtils.enableDispatcherModule("LeftHighlightNearbyEntities", leftHighlightNearbyEntities); + dispatcherUtils.enableDispatcherModule("RightHighlightNearbyEntities", rightHighlightNearbyEntities); + + function cleanup() { + dispatcherUtils.disableDispatcherModule("LeftHighlightNearbyEntities"); + dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); + } + + Script.scriptEnding.connect(cleanup); +}()); diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 147d6b807f..da9cafbe07 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -10,7 +10,7 @@ propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable, Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues, TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity, - HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE + HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, unhighlightTargetEntity */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -114,6 +114,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "startNearGrab", args); + unhighlightTargetEntity(this.targetEntityID); }; // this is for when the action is going to time-out diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 01c8424e0c..945c091f7e 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -11,7 +11,8 @@ 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 + TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Selection, DISPATCHER_HOVERING_LIST, Uuid, + highlightTargetEntity, unhighlightTargetEntity */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -34,6 +35,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.autoUnequipCounter = 0; this.lastUnexpectedChildrenCheckTime = 0; this.robbed = false; + this.highlightedEntity = null; this.parameters = makeDispatcherModuleParameters( 500, @@ -87,7 +89,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.startNearParentingGrabEntity = function (controllerData, targetProps) { Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - + unhighlightTargetEntity(this.targetEntityID); var handJointIndex; // if (this.ignoreIK) { // handJointIndex = this.controllerJointIndex; @@ -158,6 +160,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); grabbedEntity: this.targetEntityID, joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" })); + unhighlightTargetEntity(this.targetEntityID); this.grabbing = false; this.targetEntityID = null; this.robbed = false; @@ -280,6 +283,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it } else { this.targetEntityID = targetProps.id; + this.highlightedEntity = this.targetEntityID; + highlightTargetEntity(this.targetEntityID); return makeRunningValues(true, [this.targetEntityID], []); } } else { @@ -300,6 +305,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; if (!props) { // entity was deleted + unhighlightTargetEntity(this.targetEntityID); this.grabbing = false; this.targetEntityID = null; this.hapticTargetID = null; @@ -321,6 +327,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var readiness = this.isReady(controllerData); if (!readiness.active) { this.robbed = false; + unhighlightTargetEntity(this.highlightedEntity); return readiness; } if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) { diff --git a/scripts/system/controllers/controllerModules/nearTrigger.js b/scripts/system/controllers/controllerModules/nearTrigger.js index 42db3d6f61..6a9cd9fbcd 100644 --- a/scripts/system/controllers/controllerModules/nearTrigger.js +++ b/scripts/system/controllers/controllerModules/nearTrigger.js @@ -7,7 +7,7 @@ /* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData, - Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS + Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS, unhighlightTargetEntity */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -55,6 +55,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.startNearTrigger = function (controllerData) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args); + unhighlightTargetEntity(this.targetEntityID); }; this.continueNearTrigger = function (controllerData) { diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 8db8e29f37..058c99349d 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -32,6 +32,7 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/hudOverlayPointer.js", "controllerModules/mouseHMD.js", "controllerModules/scaleEntity.js", + "controllerModules/highlightNearbyEntities.js", "controllerModules/nearGrabHyperLinkEntity.js" ]; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index f82de4b71d..827b29e78a 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -7,6 +7,7 @@ /* global module, Camera, HMD, MyAvatar, controllerDispatcherPlugins:true, Quat, Vec3, Overlays, Xform, + Selection, MSECS_PER_SEC:true , LEFT_HAND:true, RIGHT_HAND:true, FORBIDDEN_GRAB_TYPES:true, HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, ZERO_VEC:true, ONE_VEC:true, DEFAULT_REGISTRATION_POINT:true, INCHES_TO_METERS:true, @@ -51,7 +52,10 @@ TEAR_AWAY_DISTANCE:true, TEAR_AWAY_COUNT:true, TEAR_AWAY_CHECK_TIME:true, - distanceBetweenPointAndEntityBoundingBox:true + distanceBetweenPointAndEntityBoundingBox:true, + highlightTargetEntity:true, + clearHighlightedEntities:true, + unhighlightTargetEntity:true */ MSECS_PER_SEC = 1000.0; @@ -95,7 +99,7 @@ DISPATCHER_HOVERING_STYLE = { isOutlineSmooth: true, outlineWidth: 0, outlineUnoccludedColor: {red: 255, green: 128, blue: 128}, - outlineUnoccludedAlpha: 0, + outlineUnoccludedAlpha: 0.0, outlineOccludedColor: {red: 255, green: 128, blue: 128}, outlineOccludedAlpha:0.0, fillUnoccludedColor: {red: 255, green: 255, blue: 255}, @@ -235,6 +239,18 @@ entityIsGrabbable = function (props) { return true; }; +clearHighlightedEntities = function() { + Selection.clearSelectedItemsList(DISPATCHER_HOVERING_LIST); +}; + +highlightTargetEntity = function(entityID) { + Selection.addToSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", entityID); +}; + +unhighlightTargetEntity = function(entityID) { + Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", entityID); +}; + entityIsDistanceGrabbable = function(props) { if (!entityIsGrabbable(props)) { return false; @@ -404,7 +420,11 @@ if (typeof module !== 'undefined') { makeDispatcherModuleParameters: makeDispatcherModuleParameters, enableDispatcherModule: enableDispatcherModule, disableDispatcherModule: disableDispatcherModule, + highlightTargetEntity: highlightTargetEntity, + unhighlightTargetEntity: unhighlightTargetEntity, + clearHighlightedEntities: clearHighlightedEntities, makeRunningValues: makeRunningValues, + findGroupParent: findGroupParent, LEFT_HAND: LEFT_HAND, RIGHT_HAND: RIGHT_HAND, BUMPER_ON_VALUE: BUMPER_ON_VALUE,