diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 4f041d3067..86b7a98b2d 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -7,11 +7,12 @@ /* jslint bitwise: true */ -/* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, +/* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, controllerDispatcherPlugins:true, controllerDispatcherPluginsNeedSort:true, LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES, getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, COLORS_GRAB_SEARCHING_HALF_SQUEEZE - COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, TRIGGER_ON_VALUE, PointerManager + COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, TRIGGER_ON_VALUE, PointerManager, print + Selection, DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE */ controllerDispatcherPlugins = {}; @@ -123,6 +124,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); return getControllerWorldLocation(Controller.Standard.RightHand, true); }; + Selection.enableListHighlight(DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE); + this.updateTimings = function () { _this.intervalCount++; var thisInterval = Date.now(); @@ -157,7 +160,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.update = function () { try { _this.updateInternal(); - } catch (e) { + } catch (e) { print(e); } Script.setTimeout(_this.update, BASIC_TIMER_INTERVAL_MS); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 53272c324d..9dd82e0363 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -14,7 +14,7 @@ PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI - Picks, makeLaserLockInfo Xform, makeLaserParams, AddressManager, getEntityParents, Selection + Picks, makeLaserLockInfo Xform, makeLaserParams, AddressManager, getEntityParents, Selection, DISPATCHER_HOVERING_LIST */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -103,6 +103,7 @@ Script.include("/~/system/libraries/Xform.js"); this.contextOverlayTimer = false; this.previousCollisionStatus = false; this.locked = false; + this.highlightedEntity = null; this.reticleMinX = MARGIN; this.reticleMaxX; this.reticleMinY = MARGIN; @@ -449,7 +450,9 @@ Script.include("/~/system/libraries/Xform.js"); if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; - + Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", + this.highlightedEntity); + this.highlightedEntity = null; var targetProps = Entities.getEntityProperties(entityID, [ "dynamic", "shapeType", "position", "rotation", "dimensions", "density", @@ -497,38 +500,62 @@ Script.include("/~/system/libraries/Xform.js"); this.startFarGrabAction(controllerData, targetProps); } } - } else if (!this.entityWithContextOverlay) { - var _this = this; + } else { + var targetEntityID = rayPickInfo.objectID; + if (this.highlightedEntity !== targetEntityID) { + Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", + this.highlightedEntity); + var selectionTargetProps = Entities.getEntityProperties(targetEntityID, [ + "dynamic", "shapeType", "position", + "rotation", "dimensions", "density", + "userData", "locked", "type", "href" + ]); - if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { - if (_this.contextOverlayTimer) { - Script.clearTimeout(_this.contextOverlayTimer); + var selectionTargetObject = new TargetObject(targetEntityID, selectionTargetProps); + selectionTargetObject.parentProps = getEntityParents(selectionTargetProps); + var selectionTargetEntity = selectionTargetObject.getTargetEntity(); + + if (entityIsGrabbable(selectionTargetEntity.props) || + entityIsGrabbable(selectionTargetObject.entityProps)) { + + Selection.addToSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", rayPickInfo.objectID); } - _this.contextOverlayTimer = false; - _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; + this.highlightedEntity = rayPickInfo.objectID; } - if (!_this.contextOverlayTimer) { - _this.contextOverlayTimer = Script.setTimeout(function () { - if (!_this.entityWithContextOverlay && - _this.contextOverlayTimer && - _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { - var props = Entities.getEntityProperties(rayPickInfo.objectID); - var pointerEvent = { - type: "Move", - id: _this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, rayPickInfo.intersection, props), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.surfaceNormal, - direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), - button: "Secondary" - }; - if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { - _this.entityWithContextOverlay = rayPickInfo.objectID; - } + if (!this.entityWithContextOverlay) { + var _this = this; + + if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { + if (_this.contextOverlayTimer) { + Script.clearTimeout(_this.contextOverlayTimer); } _this.contextOverlayTimer = false; - }, 500); + _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; + } + + if (!_this.contextOverlayTimer) { + _this.contextOverlayTimer = Script.setTimeout(function () { + if (!_this.entityWithContextOverlay && + _this.contextOverlayTimer && + _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { + var props = Entities.getEntityProperties(rayPickInfo.objectID); + var pointerEvent = { + type: "Move", + id: _this.hand + 1, // 0 is reserved for hardware mouse + pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, rayPickInfo.intersection, props), + pos3D: rayPickInfo.intersection, + normal: rayPickInfo.surfaceNormal, + direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), + button: "Secondary" + }; + if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { + _this.entityWithContextOverlay = rayPickInfo.objectID; + } + } + _this.contextOverlayTimer = false; + }, 500); + } } } } else if (this.distanceRotating) { diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 75e1d6668b..05f6aa9fbf 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -22,6 +22,8 @@ DISPATCHER_PROPERTIES:true, HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, + DISPATCHER_HOVERING_LIST:true, + DISPATCHER_HOVERING_STYLE:true, Entities, makeDispatcherModuleParameters:true, makeRunningValues:true, @@ -88,6 +90,19 @@ NEAR_GRAB_RADIUS = 1.0; TEAR_AWAY_DISTANCE = 0.1; // 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 +DISPATCHER_HOVERING_LIST = "dispactherHoveringList"; +DISPATCHER_HOVERING_STYLE = { + isOutlineSmooth: true, + outlineWidth: 5, + outlineUnoccludedColor: {red: 255, green: 128, blue: 128}, + outlineUnoccludedAlpha: 0.88, + outlineOccludedColor: {red: 255, green: 128, blue: 128}, + outlineOccludedAlpha:0.5, + fillUnoccludedColor: {red: 26, green: 0, blue: 0}, + fillUnoccludedAlpha: 0.0, + fillOccludedColor: {red: 26, green: 0, blue: 0}, + fillOccludedAlpha: 0.0 +}; DISPATCHER_PROPERTIES = [ "position", @@ -400,6 +415,7 @@ if (typeof module !== 'undefined') { projectOntoOverlayXYPlane: projectOntoOverlayXYPlane, projectOntoEntityXYPlane: projectOntoEntityXYPlane, TRIGGER_OFF_VALUE: TRIGGER_OFF_VALUE, - TRIGGER_ON_VALUE: TRIGGER_ON_VALUE + TRIGGER_ON_VALUE: TRIGGER_ON_VALUE, + DISPATCHER_HOVERING_LIST: DISPATCHER_HOVERING_LIST }; }