From c9c3d8f3327711ecb15b5500fcf0b1f523544d0a Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Wed, 4 Apr 2018 08:07:35 -0700
Subject: [PATCH 01/13] adding entity selection for far grabbing

---
 .../controllers/controllerDispatcher.js       |  9 +-
 .../controllerModules/farActionGrabEntity.js  | 83 ++++++++++++-------
 .../libraries/controllerDispatcherUtils.js    | 18 +++-
 3 files changed, 78 insertions(+), 32 deletions(-)

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
     };
 }

From 42149e295d2dc4a7ac606a8c3b397628a1f72a3d Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Wed, 4 Apr 2018 12:55:28 -0700
Subject: [PATCH 02/13] editing seletion style

---
 .../controllerModules/farActionGrabEntity.js         |  4 ++++
 .../system/libraries/controllerDispatcherUtils.js    | 12 ++++++------
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js
index 9dd82e0363..58f032de08 100644
--- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js
+++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js
@@ -402,6 +402,8 @@ Script.include("/~/system/libraries/Xform.js");
             if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE ||
                 this.notPointingAtEntity(controllerData) || this.targetIsNull()) {
                 this.endNearGrabAction();
+                Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
+                    this.highlightedEntity);
                 return makeRunningValues(false, [], []);
             }
             this.intersectionDistance = controllerData.rayPicks[this.hand].distance;
@@ -571,6 +573,8 @@ Script.include("/~/system/libraries/Xform.js");
             if (disableModule) {
                 if (disableModule.disableModules) {
                     this.endNearGrabAction();
+                    Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
+                        this.highlightedEntity);
                     return makeRunningValues(false, [], []);
                 }
             }
diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js
index 05f6aa9fbf..f82de4b71d 100644
--- a/scripts/system/libraries/controllerDispatcherUtils.js
+++ b/scripts/system/libraries/controllerDispatcherUtils.js
@@ -93,14 +93,14 @@ TEAR_AWAY_CHECK_TIME = 0.15; // seconds, duration between checks
 DISPATCHER_HOVERING_LIST = "dispactherHoveringList";
 DISPATCHER_HOVERING_STYLE = {
     isOutlineSmooth: true,
-    outlineWidth: 5,
+    outlineWidth: 0,
     outlineUnoccludedColor: {red: 255, green: 128, blue: 128},
-    outlineUnoccludedAlpha: 0.88,
+    outlineUnoccludedAlpha: 0,
     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},
+    outlineOccludedAlpha:0.0,
+    fillUnoccludedColor: {red: 255, green: 255, blue: 255},
+    fillUnoccludedAlpha: 0.15,
+    fillOccludedColor: {red: 255, green: 255, blue: 255},
     fillOccludedAlpha: 0.0
 };
 

From cc341e8ad7c14b7b74b6819da3bb17dcd742c458 Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Thu, 5 Apr 2018 15:38:56 -0700
Subject: [PATCH 03/13] highlight nearby entities

---
 .../controllerModules/farActionGrabEntity.js  |  2 +
 .../highlightNearbyEntities.js                | 88 +++++++++++++++++++
 .../controllerModules/nearActionGrabEntity.js |  3 +-
 .../controllerModules/nearParentGrabEntity.js | 11 ++-
 .../controllerModules/nearTrigger.js          |  3 +-
 .../system/controllers/controllerScripts.js   |  1 +
 .../libraries/controllerDispatcherUtils.js    | 24 ++++-
 7 files changed, 126 insertions(+), 6 deletions(-)
 create mode 100644 scripts/system/controllers/controllerModules/highlightNearbyEntities.js

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,

From 07b1a6be01365304f44cfdc5f7ba735175e715a3 Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Fri, 6 Apr 2018 11:01:40 -0700
Subject: [PATCH 04/13] saving work

---
 .../controllers/controllerDispatcher.js       |  2 +-
 .../controllerModules/equipEntity.js          | 50 ++++++++++++++++++-
 .../highlightNearbyEntities.js                |  3 +-
 3 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js
index 86b7a98b2d..f4fd933ce4 100644
--- a/scripts/system/controllers/controllerDispatcher.js
+++ b/scripts/system/controllers/controllerDispatcher.js
@@ -30,7 +30,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
     var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ;
 
     var PROFILE = false;
-    var DEBUG = false;
+    var DEBUG = true;
 
     if (typeof Test !== "undefined") {
         PROFILE = true;
diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js
index 252f6efa9e..c5ec76ccfd 100644
--- a/scripts/system/controllers/controllerModules/equipEntity.js
+++ b/scripts/system/controllers/controllerModules/equipEntity.js
@@ -23,6 +23,27 @@ var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/eq
 var EQUIP_SPHERE_SCALE_FACTOR = 0.65;
 
 
+var EQUIPPING_OUTER_COLOR = { red: 0, green: 100, blue: 0 };
+var EQUIPPING_INNER_COLOR = { red: 0, green: 150, blue: 0 };
+var UNEQUIPPING_OUTER_COLOR = { red: 100, green: 0, blue: 0 };
+var UNEQUIPPING_INNER_COLOR = { red: 150, green: 0, blue: 0 };
+
+var CIRCLE_3D_PROPERTIES = {
+    solid: true,
+    innerRadius: 0.0,
+    outerRadius: 1.0,
+    startAt: 0,
+    endAt: 180,
+    outerColor: EQUIPPING_OUTER_COLOR,
+    innerColor: EQUIPPING_INNER_COLOR,
+    alpha: 1.0,
+    innerAlpha: 0.9,
+    Alpha: 1.0
+};
+
+var EQUIP_TIME = 3000;
+var UNEQUIP_TIME = 4000;
+
 // Each overlayInfoSet describes a single equip hotspot.
 // It is an object with the following keys:
 //   timestamp - last time this object was updated, used to delete stale hotspot overlays.
@@ -158,6 +179,29 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
     }
 };
 
+
+function EquipTimer(hand) {
+    this.hand = hand;
+    this.controllerTriggerPressed = false;
+    this.equipTime = EQUIP_TIME;
+    this.currentTimeLapse = 0;
+    this.equip = true;
+    this.finished = false;
+    this.circle3dProperties = CIRCLE_3D_PROPERTIES;
+    this.circle3dOverlay = Overlays.addOverlay("circle3d", this.circle3dProperties);
+}
+
+EquipTimer.prototype.update = function(deltaTime, timestamp, controllerData) {
+};
+
+EquipTimer.prototype.finished = function() {
+    return this.finished;
+};
+
+EquipTimer.prototype.cleanup = function() {
+    Overlays.deleteOverlay(this.circle3dOverlay);
+};
+
 (function() {
 
     var ATTACH_POINT_SETTINGS = "io.highfidelity.attachPoints";
@@ -279,6 +323,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
 
         var equipHotspotBuddy = new EquipHotspotBuddy();
 
+        this.equipTimer = new EquipTimer(this.hand);
+
         this.setMessageGrabData = function(entityProperties) {
             if (entityProperties) {
                 this.messageGrabEntity = true;
@@ -621,8 +667,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
             // if the potentialHotspot os not cloneable and locked return null
 
             if (potentialEquipHotspot &&
-                (((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) ||
-                 this.messageGrabEntity)) {
+                (((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease &&
+                  this.equipTimer.finished()) || this.messageGrabEntity)) {
                 this.grabbedHotspot = potentialEquipHotspot;
                 this.targetEntityID = this.grabbedHotspot.entityID;
                 this.startEquipEntity(controllerData);
diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
index de58c5a388..d204499c05 100644
--- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
+++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
@@ -45,7 +45,8 @@
 
         this.highlightEntities = function(controllerData) {
             if (this.highlightedEntities.length > 0) {
-                dispatcherUtils.clearHighlightedEntities();
+                //print("-----> clearing 
+                //dispatcherUtils.clearHighlightedEntities();
                 this.highlightedEntities = [];
             }
 

From fd478328579c3d6a95188c3103943e88cf22a7af Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Fri, 6 Apr 2018 11:47:09 -0700
Subject: [PATCH 05/13] saving changes

---
 scripts/system/controllers/controllerDispatcher.js |  1 +
 .../controllers/controllerModules/equipEntity.js   | 14 ++++++++++++--
 .../controllerModules/highlightNearbyEntities.js   |  3 +--
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js
index f4fd933ce4..12f9fdbba0 100644
--- a/scripts/system/controllers/controllerDispatcher.js
+++ b/scripts/system/controllers/controllerDispatcher.js
@@ -125,6 +125,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
         };
 
         Selection.enableListHighlight(DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE);
+        Selection.enableListToScene(DISPATCHER_HOVERING_LIST);
 
         this.updateTimings = function () {
             _this.intervalCount++;
diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js
index c5ec76ccfd..60a36ea06d 100644
--- a/scripts/system/controllers/controllerModules/equipEntity.js
+++ b/scripts/system/controllers/controllerModules/equipEntity.js
@@ -30,6 +30,7 @@ var UNEQUIPPING_INNER_COLOR = { red: 150, green: 0, blue: 0 };
 
 var CIRCLE_3D_PROPERTIES = {
     solid: true,
+    visible: false,
     innerRadius: 0.0,
     outerRadius: 1.0,
     startAt: 0,
@@ -182,7 +183,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
 
 function EquipTimer(hand) {
     this.hand = hand;
-    this.controllerTriggerPressed = false;
+    this.primaryTriggerPressed = false;
+    this.secondaryTriggerPressed = false;
     this.equipTime = EQUIP_TIME;
     this.currentTimeLapse = 0;
     this.equip = true;
@@ -192,6 +194,14 @@ function EquipTimer(hand) {
 }
 
 EquipTimer.prototype.update = function(deltaTime, timestamp, controllerData) {
+    /*var TRIGGER_ON_VALUE = 0.105;
+    var BUMPER_ON_VALUE = 0.5;
+    var primaryTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE;
+    var secondaryTriggerPressed = controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE;
+
+    if (primaryTriggerPressed || secondaryTriggerPressed) {
+        if (primaryTriggerPressed === this.primaryTriggerPressed &&
+            */
 };
 
 EquipTimer.prototype.finished = function() {
@@ -662,7 +672,7 @@ EquipTimer.prototype.cleanup = function() {
             }
 
             equipHotspotBuddy.update(deltaTime, timestamp, controllerData);
-
+            this.equiptTimer.update(deltaTime, timestamp, controllerData);
             // if the potentialHotspot is cloneable, clone it and return it
             // if the potentialHotspot os not cloneable and locked return null
 
diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
index d204499c05..de58c5a388 100644
--- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
+++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
@@ -45,8 +45,7 @@
 
         this.highlightEntities = function(controllerData) {
             if (this.highlightedEntities.length > 0) {
-                //print("-----> clearing 
-                //dispatcherUtils.clearHighlightedEntities();
+                dispatcherUtils.clearHighlightedEntities();
                 this.highlightedEntities = [];
             }
 

From 2c20593b6defe3a4bf1a421518a2e6a46976edbd Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Fri, 6 Apr 2018 16:30:45 -0700
Subject: [PATCH 06/13] editing equip code

---
 .../controllers/controllerDispatcher.js       |  2 +-
 .../controllerModules/equipEntity.js          | 74 +++++++++++++++----
 .../highlightNearbyEntities.js                |  5 +-
 3 files changed, 65 insertions(+), 16 deletions(-)

diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js
index 12f9fdbba0..04f9b3e43a 100644
--- a/scripts/system/controllers/controllerDispatcher.js
+++ b/scripts/system/controllers/controllerDispatcher.js
@@ -30,7 +30,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
     var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ;
 
     var PROFILE = false;
-    var DEBUG = true;
+    var DEBUG = false;
 
     if (typeof Test !== "undefined") {
         PROFILE = true;
diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js
index 60a36ea06d..2d74bbe9ae 100644
--- a/scripts/system/controllers/controllerModules/equipEntity.js
+++ b/scripts/system/controllers/controllerModules/equipEntity.js
@@ -183,31 +183,62 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
 
 function EquipTimer(hand) {
     this.hand = hand;
+    this.timelapsed = 0;
     this.primaryTriggerPressed = false;
     this.secondaryTriggerPressed = false;
-    this.equipTime = EQUIP_TIME;
-    this.currentTimeLapse = 0;
-    this.equip = true;
+    this.targetTime = EQUIP_TIME;
     this.finished = false;
     this.circle3dProperties = CIRCLE_3D_PROPERTIES;
     this.circle3dOverlay = Overlays.addOverlay("circle3d", this.circle3dProperties);
 }
 
-EquipTimer.prototype.update = function(deltaTime, timestamp, controllerData) {
-    /*var TRIGGER_ON_VALUE = 0.105;
+EquipTimer.prototype.update = function(deltaTime, targetEntityID, controllerData) {
+    var TRIGGER_ON_VALUE = 0.105;
     var BUMPER_ON_VALUE = 0.5;
     var primaryTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE;
     var secondaryTriggerPressed = controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE;
 
     if (primaryTriggerPressed || secondaryTriggerPressed) {
-        if (primaryTriggerPressed === this.primaryTriggerPressed &&
-            */
+        if ((primaryTriggerPressed === this.primaryTriggerPressed) &&
+            (secondaryTriggerPressed === this.secondaryTriggerPressed)) {
+            this.timelapsed += deltaTime * 1000; // convert to ms
+            // update overlay
+
+            var entityProperties = Entities.getEntityProperties(targetEntityID, ["position", "rotation"]);
+            if (entityProperties) {
+                var PI = 3.14159;
+                var TWO_PI = PI * 2;
+                var FORWARD_OFFSET = 0.1 * MyAvatar.sensorToWorldScale;
+                var direction = Vec3.subtract(entityProperties.position - HMD.position);
+                var overlayPosition = Vec3.sum(entityProperties.position, Vec3.multiply(FORWARD_OFFSET, direction));
+            }
+            if (this.timelapsed >= this.targetTime) {
+                print("finished");
+                this.finished = true;
+            }
+
+            return;
+        }
+
+        this.reset();
+        this.primaryTriggerPressed = primaryTriggerPressed;
+        this.secondaryTriggerPressed = secondaryTriggerPressed;
+    } else {
+        this.reset();
+    }
 };
 
-EquipTimer.prototype.finished = function() {
+EquipTimer.prototype.done = function() {
     return this.finished;
 };
 
+EquipTimer.prototype.reset = function() {
+    this.finished = false;
+    this.timelapsed = 0;
+    this.primaryTriggerPressed = false;
+    this.secondaryTriggerPressed = false;
+};
+
 EquipTimer.prototype.cleanup = function() {
     Overlays.deleteOverlay(this.circle3dOverlay);
 };
@@ -324,6 +355,7 @@ EquipTimer.prototype.cleanup = function() {
         this.shouldSendStart = false;
         this.equipedWithSecondary = false;
         this.handHasBeenRightsideUp = false;
+        this.equipAtRun = false;
 
         this.parameters = makeDispatcherModuleParameters(
             300,
@@ -672,20 +704,23 @@ EquipTimer.prototype.cleanup = function() {
             }
 
             equipHotspotBuddy.update(deltaTime, timestamp, controllerData);
-            this.equiptTimer.update(deltaTime, timestamp, controllerData);
             // if the potentialHotspot is cloneable, clone it and return it
             // if the potentialHotspot os not cloneable and locked return null
 
             if (potentialEquipHotspot &&
-                (((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease &&
-                  this.equipTimer.finished()) || this.messageGrabEntity)) {
+                (((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) || this.messageGrabEntity)) {
                 this.grabbedHotspot = potentialEquipHotspot;
                 this.targetEntityID = this.grabbedHotspot.entityID;
-                this.startEquipEntity(controllerData);
+                this.equipAtRun = true;
                 this.messageGrabEntity = false;
-                this.equipedWithSecondary = this.secondarySmoothedSqueezed();
+                if (this.messageGrabEntity) {
+                    this.startEquipEntity(controllerData);
+                    this.equipedWithSecondary = this.secondarySmoothedSqueezed();
+                    this.equipAtRun = false;
+                }
                 return makeRunningValues(true, [potentialEquipHotspot.entityID], []);
             } else {
+                this.equipAtRun = false;
                 return makeRunningValues(false, [], []);
             }
         };
@@ -706,6 +741,19 @@ EquipTimer.prototype.cleanup = function() {
             var timestamp = Date.now();
             this.updateInputs(controllerData);
 
+            if (this.equipAtRun) {
+                if ((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) {
+                    this.equipTimer.update(deltaTime, this.targetEntityID, controllerData);
+                    if (this.equipTimer.done()) {
+                        this.equipAtRun = false;
+                        this.startEquipEntity(controllerData);
+                        this.equipedWithSecondary = this.secondarySmoothedSqueezed();
+                        this.equipTimer.reset();
+                    }
+                    return makeRunningValues(true, [], []);
+                }
+            }
+
             if (!this.isTargetIDValid(controllerData)) {
                 this.endEquipEntity();
                 return makeRunningValues(false, [], []);
diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
index de58c5a388..2b9b79578f 100644
--- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
+++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
@@ -9,12 +9,13 @@
 /* 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
+   DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData, makeLaserParams, entityIsCloneable
 */
 
 (function () {
     Script.include("/~/system/libraries/controllerDispatcherUtils.js");
     Script.include("/~/system/libraries/controllers.js");
+    Script.include("/~/system/libraries/cloneEntityUtils.js");
     var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
     function HighlightNearbyEntities(hand) {
         this.hand = hand;
@@ -28,7 +29,7 @@
 
 
         this.isGrabable = function(controllerData, props) {
-            if (dispatcherUtils.entityIsGrabbable(props) || dispatcherUtils.entityIsCloneable(props)) {
+            if (dispatcherUtils.entityIsGrabbable(props) || 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)) {

From 1113202a906783a492dccf9c3581a7f9d0ea038e Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Mon, 9 Apr 2018 16:51:20 -0700
Subject: [PATCH 07/13] reverting file

---
 .../controllerModules/equipEntity.js          | 114 +-----------------
 1 file changed, 5 insertions(+), 109 deletions(-)

diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js
index 2d74bbe9ae..252f6efa9e 100644
--- a/scripts/system/controllers/controllerModules/equipEntity.js
+++ b/scripts/system/controllers/controllerModules/equipEntity.js
@@ -23,28 +23,6 @@ var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/eq
 var EQUIP_SPHERE_SCALE_FACTOR = 0.65;
 
 
-var EQUIPPING_OUTER_COLOR = { red: 0, green: 100, blue: 0 };
-var EQUIPPING_INNER_COLOR = { red: 0, green: 150, blue: 0 };
-var UNEQUIPPING_OUTER_COLOR = { red: 100, green: 0, blue: 0 };
-var UNEQUIPPING_INNER_COLOR = { red: 150, green: 0, blue: 0 };
-
-var CIRCLE_3D_PROPERTIES = {
-    solid: true,
-    visible: false,
-    innerRadius: 0.0,
-    outerRadius: 1.0,
-    startAt: 0,
-    endAt: 180,
-    outerColor: EQUIPPING_OUTER_COLOR,
-    innerColor: EQUIPPING_INNER_COLOR,
-    alpha: 1.0,
-    innerAlpha: 0.9,
-    Alpha: 1.0
-};
-
-var EQUIP_TIME = 3000;
-var UNEQUIP_TIME = 4000;
-
 // Each overlayInfoSet describes a single equip hotspot.
 // It is an object with the following keys:
 //   timestamp - last time this object was updated, used to delete stale hotspot overlays.
@@ -180,69 +158,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
     }
 };
 
-
-function EquipTimer(hand) {
-    this.hand = hand;
-    this.timelapsed = 0;
-    this.primaryTriggerPressed = false;
-    this.secondaryTriggerPressed = false;
-    this.targetTime = EQUIP_TIME;
-    this.finished = false;
-    this.circle3dProperties = CIRCLE_3D_PROPERTIES;
-    this.circle3dOverlay = Overlays.addOverlay("circle3d", this.circle3dProperties);
-}
-
-EquipTimer.prototype.update = function(deltaTime, targetEntityID, controllerData) {
-    var TRIGGER_ON_VALUE = 0.105;
-    var BUMPER_ON_VALUE = 0.5;
-    var primaryTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE;
-    var secondaryTriggerPressed = controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE;
-
-    if (primaryTriggerPressed || secondaryTriggerPressed) {
-        if ((primaryTriggerPressed === this.primaryTriggerPressed) &&
-            (secondaryTriggerPressed === this.secondaryTriggerPressed)) {
-            this.timelapsed += deltaTime * 1000; // convert to ms
-            // update overlay
-
-            var entityProperties = Entities.getEntityProperties(targetEntityID, ["position", "rotation"]);
-            if (entityProperties) {
-                var PI = 3.14159;
-                var TWO_PI = PI * 2;
-                var FORWARD_OFFSET = 0.1 * MyAvatar.sensorToWorldScale;
-                var direction = Vec3.subtract(entityProperties.position - HMD.position);
-                var overlayPosition = Vec3.sum(entityProperties.position, Vec3.multiply(FORWARD_OFFSET, direction));
-            }
-            if (this.timelapsed >= this.targetTime) {
-                print("finished");
-                this.finished = true;
-            }
-
-            return;
-        }
-
-        this.reset();
-        this.primaryTriggerPressed = primaryTriggerPressed;
-        this.secondaryTriggerPressed = secondaryTriggerPressed;
-    } else {
-        this.reset();
-    }
-};
-
-EquipTimer.prototype.done = function() {
-    return this.finished;
-};
-
-EquipTimer.prototype.reset = function() {
-    this.finished = false;
-    this.timelapsed = 0;
-    this.primaryTriggerPressed = false;
-    this.secondaryTriggerPressed = false;
-};
-
-EquipTimer.prototype.cleanup = function() {
-    Overlays.deleteOverlay(this.circle3dOverlay);
-};
-
 (function() {
 
     var ATTACH_POINT_SETTINGS = "io.highfidelity.attachPoints";
@@ -355,7 +270,6 @@ EquipTimer.prototype.cleanup = function() {
         this.shouldSendStart = false;
         this.equipedWithSecondary = false;
         this.handHasBeenRightsideUp = false;
-        this.equipAtRun = false;
 
         this.parameters = makeDispatcherModuleParameters(
             300,
@@ -365,8 +279,6 @@ EquipTimer.prototype.cleanup = function() {
 
         var equipHotspotBuddy = new EquipHotspotBuddy();
 
-        this.equipTimer = new EquipTimer(this.hand);
-
         this.setMessageGrabData = function(entityProperties) {
             if (entityProperties) {
                 this.messageGrabEntity = true;
@@ -704,23 +616,20 @@ EquipTimer.prototype.cleanup = function() {
             }
 
             equipHotspotBuddy.update(deltaTime, timestamp, controllerData);
+
             // if the potentialHotspot is cloneable, clone it and return it
             // if the potentialHotspot os not cloneable and locked return null
 
             if (potentialEquipHotspot &&
-                (((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) || this.messageGrabEntity)) {
+                (((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) ||
+                 this.messageGrabEntity)) {
                 this.grabbedHotspot = potentialEquipHotspot;
                 this.targetEntityID = this.grabbedHotspot.entityID;
-                this.equipAtRun = true;
+                this.startEquipEntity(controllerData);
                 this.messageGrabEntity = false;
-                if (this.messageGrabEntity) {
-                    this.startEquipEntity(controllerData);
-                    this.equipedWithSecondary = this.secondarySmoothedSqueezed();
-                    this.equipAtRun = false;
-                }
+                this.equipedWithSecondary = this.secondarySmoothedSqueezed();
                 return makeRunningValues(true, [potentialEquipHotspot.entityID], []);
             } else {
-                this.equipAtRun = false;
                 return makeRunningValues(false, [], []);
             }
         };
@@ -741,19 +650,6 @@ EquipTimer.prototype.cleanup = function() {
             var timestamp = Date.now();
             this.updateInputs(controllerData);
 
-            if (this.equipAtRun) {
-                if ((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) {
-                    this.equipTimer.update(deltaTime, this.targetEntityID, controllerData);
-                    if (this.equipTimer.done()) {
-                        this.equipAtRun = false;
-                        this.startEquipEntity(controllerData);
-                        this.equipedWithSecondary = this.secondarySmoothedSqueezed();
-                        this.equipTimer.reset();
-                    }
-                    return makeRunningValues(true, [], []);
-                }
-            }
-
             if (!this.isTargetIDValid(controllerData)) {
                 this.endEquipEntity();
                 return makeRunningValues(false, [], []);

From 2e1ebac03ffcfb7b7180330c1d51b9ecd6b226e9 Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Mon, 9 Apr 2018 18:07:03 -0700
Subject: [PATCH 08/13] clean up functionality

---
 .../controllerModules/equipEntity.js          |  4 +-
 .../highlightNearbyEntities.js                | 41 ++++++++++++++++---
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js
index 252f6efa9e..8ad5c80cb8 100644
--- a/scripts/system/controllers/controllerModules/equipEntity.js
+++ b/scripts/system/controllers/controllerModules/equipEntity.js
@@ -10,7 +10,7 @@
    getControllerJointIndex, enableDispatcherModule, disableDispatcherModule,
    Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions,
    Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, entityIsCloneable,
-   cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE, Uuid
+   cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE, Uuid, unhighlightTargetEntity
 */
 
 Script.include("/~/system/libraries/Xform.js");
@@ -483,7 +483,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
             this.dropGestureReset();
             this.clearEquipHaptics();
             Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
-
+            unhighlightTargetEntity(this.targetEntityID);
             var grabbedProperties = Entities.getEntityProperties(this.targetEntityID);
 
             // if an object is "equipped" and has a predefined offset, use it.
diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
index 2b9b79578f..44d48138d2 100644
--- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
+++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
@@ -17,8 +17,21 @@
     Script.include("/~/system/libraries/controllers.js");
     Script.include("/~/system/libraries/cloneEntityUtils.js");
     var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
+
+    function differenceInArrays(firstArray, secondArray) {
+        print("first " + firstArray);
+        print("second " + secondArray);
+        var differenceArray = firstArray.filter(function(element) {
+            return secondArray.indexOf(element) < 0;
+        });
+
+        return differenceArray;
+    }
+
     function HighlightNearbyEntities(hand) {
         this.hand = hand;
+        this.otherHand = hand === dispatcherUtils.RIGHT_HAND ? dispatcherUtils.LEFT_HAND :
+            dispatcherUtils.RIGHT_HAND;
         this.highlightedEntities = [];
 
         this.parameters = dispatcherUtils.makeDispatcherModuleParameters(
@@ -44,13 +57,20 @@
             return (props.href !== "" && props.href !== undefined);
         };
 
-        this.highlightEntities = function(controllerData) {
-            if (this.highlightedEntities.length > 0) {
-                dispatcherUtils.clearHighlightedEntities();
-                this.highlightedEntities = [];
-            }
+        this.getOtherModule = function() {
+            var otherModule = this.hand === dispatcherUtils.RIGHT_HAND ? leftHighlightNearbyEntities :
+                rightHighlightNearbyEntities;
+            return otherModule;
+        };
 
+        this.getOtherHandHighlightedEntities = function() {
+            return this.getOtherModule().highlightedEntities;
+        };
+
+        this.highlightEntities = function(controllerData) {
             var nearbyEntitiesProperties = controllerData.nearbyEntityProperties[this.hand];
+            var otherHandHighlightedEntities = this.getOtherHandHighlightedEntities();
+            var newHighlightedEntities = [];
             var sensorScaleFactor = MyAvatar.sensorToWorldScale;
             for (var i = 0; i < nearbyEntitiesProperties.length; i++) {
                 var props = nearbyEntitiesProperties[i];
@@ -59,9 +79,18 @@
                 }
                 if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) {
                     dispatcherUtils.highlightTargetEntity(props.id);
-                    this.highlightedEntities.push(props.id);
+                    newHighlightedEntities.push(props.id);
                 }
             }
+
+            var unhighlightEntities = differenceInArrays(this.highlightedEntities, newHighlightedEntities);
+
+            unhighlightEntities.forEach(function(entityID) {
+                if (otherHandHighlightedEntities.indexOf(entityID) < 0 ) {
+                    dispatcherUtils.unhighlightTargetEntity(entityID);
+                }
+            });
+            this.highlightedEntities = newHighlightedEntities;
         };
 
         this.isReady = function(controllerData) {

From 447163bd07e40b62bd832ac7271bd71a5e1b8285 Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Tue, 10 Apr 2018 09:23:40 -0700
Subject: [PATCH 09/13] clean up scripts

---
 .../controllerModules/equipEntity.js          |  6 ++++
 .../highlightNearbyEntities.js                | 33 ++++++++++++++++---
 .../controllerModules/nearActionGrabEntity.js |  6 ++++
 .../controllerModules/nearParentGrabEntity.js |  6 ++++
 4 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js
index 8ad5c80cb8..09d64b5d05 100644
--- a/scripts/system/controllers/controllerModules/equipEntity.js
+++ b/scripts/system/controllers/controllerModules/equipEntity.js
@@ -484,6 +484,12 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
             this.clearEquipHaptics();
             Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
             unhighlightTargetEntity(this.targetEntityID);
+            var message = {
+                hand: this.hand,
+                entityID: this.targetEntityID
+            };
+
+            Messages.sendMessage('Hifi-unhighlight-entity', JSON.stringify(message));
             var grabbedProperties = Entities.getEntityProperties(this.targetEntityID);
 
             // if an object is "equipped" and has a predefined offset, use it.
diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
index 44d48138d2..a102a5d735 100644
--- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
+++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
@@ -9,7 +9,7 @@
 /* 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, entityIsCloneable
+   DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData, makeLaserParams, entityIsCloneable, Messages, print
 */
 
 (function () {
@@ -19,8 +19,6 @@
     var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
 
     function differenceInArrays(firstArray, secondArray) {
-        print("first " + firstArray);
-        print("second " + secondArray);
         var differenceArray = firstArray.filter(function(element) {
             return secondArray.indexOf(element) < 0;
         });
@@ -57,6 +55,13 @@
             return (props.href !== "" && props.href !== undefined);
         };
 
+        this.removeEntityFromHighlightList = function(entityID) {
+            var index = this.highlightedEntities.indexOf(entityID);
+            if (index > -1) {
+                this.highlightedEntities.splice(index, 1);
+            }
+        };
+
         this.getOtherModule = function() {
             var otherModule = this.hand === dispatcherUtils.RIGHT_HAND ? leftHighlightNearbyEntities :
                 rightHighlightNearbyEntities;
@@ -103,6 +108,25 @@
         };
     }
 
+    var handleMessage = function(channel, message, sender) {
+        var data;
+        if (sender === MyAvatar.sessionUUID) {
+            if (channel === 'Hifi-unhighlight-entity') {
+                try {
+                    data = JSON.parse(message);
+
+                    var hand = data.hand;
+                    if (hand === dispatcherUtils.LEFT_HAND) {
+                        leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID);
+                    } else if (hand === dispatcherUtils.RIGHT_HAND) {
+                        rightHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID);
+                    }
+                } catch (e) {
+                    print("Failed to parse message");
+                }
+            }
+        }
+    };
     var leftHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.LEFT_HAND);
     var rightHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.RIGHT_HAND);
 
@@ -113,6 +137,7 @@
         dispatcherUtils.disableDispatcherModule("LeftHighlightNearbyEntities");
         dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities");
     }
-
+    Messages.subscribe('Hifi-unhighlight-entity');
+    Messages.messageReceived.connect(handleMessage);
     Script.scriptEnding.connect(cleanup);
 }());
diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js
index da9cafbe07..a1e4cff40d 100644
--- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js
+++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js
@@ -115,6 +115,12 @@ 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);
+            var message = {
+                hand: this.hand,
+                entityID: this.targetEntityID
+            };
+
+            Messages.sendMessage('Hifi-unhighlight-entity', JSON.stringify(message));
         };
 
         // 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 945c091f7e..55dde21f46 100644
--- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
+++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
@@ -90,6 +90,12 @@ 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 message = {
+                hand: this.hand,
+                entityID: this.targetEntityID
+            };
+
+            Messages.sendMessage('Hifi-unhighlight-entity', JSON.stringify(message));
             var handJointIndex;
             // if (this.ignoreIK) {
             //     handJointIndex = this.controllerJointIndex;

From ba9d5d18bccca3a19b824388f109aabaaf48420a Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Wed, 11 Apr 2018 13:30:21 -0700
Subject: [PATCH 10/13] make requested changes

---
 .../controllerModules/equipEntity.js          |  2 +-
 .../highlightNearbyEntities.js                | 17 ++--
 .../mouseHighlightEntities.js                 | 77 +++++++++++++++++++
 .../controllerModules/nearActionGrabEntity.js |  2 +-
 .../controllerModules/nearParentGrabEntity.js |  2 +-
 .../system/controllers/controllerScripts.js   |  3 +-
 6 files changed, 93 insertions(+), 10 deletions(-)
 create mode 100644 scripts/system/controllers/controllerModules/mouseHighlightEntities.js

diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js
index 09d64b5d05..10bd5d28d3 100644
--- a/scripts/system/controllers/controllerModules/equipEntity.js
+++ b/scripts/system/controllers/controllerModules/equipEntity.js
@@ -489,7 +489,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
                 entityID: this.targetEntityID
             };
 
-            Messages.sendMessage('Hifi-unhighlight-entity', JSON.stringify(message));
+            Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
             var grabbedProperties = Entities.getEntityProperties(this.targetEntityID);
 
             // if an object is "equipped" and has a predefined offset, use it.
diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
index a102a5d735..5def5dcd3b 100644
--- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
+++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
@@ -1,7 +1,9 @@
-"use strict";
-
+//
 //  highlightNearbyEntities.js
 //
+//  Created by Dante Ruiz 2018-4-10
+//  Copyright 2017 High Fidelity, Inc.
+//
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
 
@@ -12,6 +14,8 @@
    DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData, makeLaserParams, entityIsCloneable, Messages, print
 */
 
+"use strict";
+
 (function () {
     Script.include("/~/system/libraries/controllerDispatcherUtils.js");
     Script.include("/~/system/libraries/controllers.js");
@@ -40,15 +44,16 @@
 
 
         this.isGrabable = function(controllerData, props) {
+            var entityIsGrabable = false;
             if (dispatcherUtils.entityIsGrabbable(props) || 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;
+                entityIsGrabable = true;
+                if (!dispatcherUtils.entityIsGrabbable(groupRootProps)) {
+                    entityIsGrabable = false;
                 }
-                return true;
             }
-            return false;
+            return entityIsGrabable;
         };
 
         this.hasHyperLink = function(props) {
diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js
new file mode 100644
index 0000000000..696c819143
--- /dev/null
+++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js
@@ -0,0 +1,77 @@
+//
+//  mouseHighlightEntities.js
+//
+//  scripts/system/controllers/controllerModules/
+//
+//  Created by Dante Ruiz 2018-4-11
+//  Copyright 2017 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+/* jslint bitwise: true */
+
+/* global Script, print, Entities, Picks, HMD */
+
+
+(function() {
+    var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
+
+    function MouseHighlightEntities() {
+        this.highlightedEntity = null;
+
+        this.parameters = dispatcherUtils.makeDispatcherModuleParameters(
+            5,
+            ["mouse"],
+            [],
+            100);
+
+        this.isReady = function(controllerData) {
+            if (HMD.active) {
+                print("????");
+                if (this.highlightedEntity) {
+                    // unhighlight entity
+                }
+            } else {
+                var pickResult = controllerData.mouseRayPick;
+                if (pickResult.type === Picks.INTERSECTED_ENTITY) {
+                    var targetEntityID = pickResult.objectID;
+
+                    if (this.highlightedEntity !== targetEntityID) {
+                        var targetProps = Entities.getEntityProperties(targetEntityID, [
+                            "dynamic", "shapeType", "position",
+                            "rotation", "dimensions", "density",
+                            "userData", "locked", "type", "href"
+                        ]);
+
+                        if (this.highlightedEntity) {
+                            dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity);
+                            this.highlightedEntity = null;
+                        }
+
+                        if (dispatcherUtils.entityIsGrabbable(targetProps)) {
+                            // highlight entity
+                            dispatcherUtils.highlightTargetEntity(targetEntityID);
+                            this.highlightedEntity = targetEntityID;
+                        }
+                    }
+                }
+            }
+
+            return dispatcherUtils.makeRunningValues(false, [], []);
+        };
+
+        this.run = function(controllerData) {
+            return this.isReady(controllerData);
+        };
+    }
+
+    var mouseHighlightEntities = new MouseHighlightEntities();
+    dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities);
+
+    function cleanup() {
+        dispatcherUtils.disableDispatcherModule("MouseHighlightEntities");
+    }
+    Script.scriptEnding.connect(cleanup);
+})();
diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js
index a1e4cff40d..a4e439fe2f 100644
--- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js
+++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js
@@ -120,7 +120,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
                 entityID: this.targetEntityID
             };
 
-            Messages.sendMessage('Hifi-unhighlight-entity', JSON.stringify(message));
+            Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
         };
 
         // 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 55dde21f46..d454d20a02 100644
--- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
+++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
@@ -95,7 +95,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
                 entityID: this.targetEntityID
             };
 
-            Messages.sendMessage('Hifi-unhighlight-entity', JSON.stringify(message));
+            Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
             var handJointIndex;
             // if (this.ignoreIK) {
             //     handJointIndex = this.controllerJointIndex;
diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js
index 058c99349d..50e627fe5d 100644
--- a/scripts/system/controllers/controllerScripts.js
+++ b/scripts/system/controllers/controllerScripts.js
@@ -33,7 +33,8 @@ var CONTOLLER_SCRIPTS = [
     "controllerModules/mouseHMD.js",
     "controllerModules/scaleEntity.js",
     "controllerModules/highlightNearbyEntities.js",
-    "controllerModules/nearGrabHyperLinkEntity.js"
+    "controllerModules/nearGrabHyperLinkEntity.js",
+    "controllerModules/mouseHighlightEntities.js"
 ];
 
 var DEBUG_MENU_ITEM = "Debug defaultScripts.js";

From 7243160dace682f48443554693beca351db34fbe Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Wed, 11 Apr 2018 14:42:26 -0700
Subject: [PATCH 11/13] making requested changes

---
 .../controllerModules/highlightNearbyEntities.js          | 8 ++++----
 .../controllerModules/mouseHighlightEntities.js           | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
index 5def5dcd3b..a66f7bd144 100644
--- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
+++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js
@@ -44,16 +44,16 @@
 
 
         this.isGrabable = function(controllerData, props) {
-            var entityIsGrabable = false;
+            var canGrabEntity = false;
             if (dispatcherUtils.entityIsGrabbable(props) || entityIsCloneable(props)) {
                 // if we've attempted to grab a child, roll up to the root of the tree
                 var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props);
-                entityIsGrabable = true;
+                canGrabEntity = true;
                 if (!dispatcherUtils.entityIsGrabbable(groupRootProps)) {
-                    entityIsGrabable = false;
+                    canGrabEntity = false;
                 }
             }
-            return entityIsGrabable;
+            return canGrabEntity;
         };
 
         this.hasHyperLink = function(props) {
diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js
index 696c819143..6af1055a69 100644
--- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js
+++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js
@@ -29,9 +29,9 @@
 
         this.isReady = function(controllerData) {
             if (HMD.active) {
-                print("????");
                 if (this.highlightedEntity) {
-                    // unhighlight entity
+                    dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity);
+                    this.highlightedEntity = null;
                 }
             } else {
                 var pickResult = controllerData.mouseRayPick;

From 43b92299d6b60a787648061210f623a34f29c1df Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Thu, 12 Apr 2018 10:35:29 -0700
Subject: [PATCH 12/13] changing highlighting percentage

---
 scripts/system/controllers/grab.js                    | 3 ++-
 scripts/system/libraries/controllerDispatcherUtils.js | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js
index 1171703847..333180a631 100644
--- a/scripts/system/controllers/grab.js
+++ b/scripts/system/controllers/grab.js
@@ -15,7 +15,7 @@
 //
 
 /* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller,
-   isInEditMode, HMD entityIsGrabbable, Picks, PickType, Pointers*/
+   isInEditMode, HMD entityIsGrabbable, Picks, PickType, Pointers, unhighlightTargetEntity*/
 
 
 (function() { // BEGIN LOCAL_SCOPE
@@ -354,6 +354,7 @@ Grabber.prototype.pressEvent = function(event) {
 
     Pointers.setRenderState(this.mouseRayEntities, "grabbed");
     Pointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false);
+    unhighlightTargetEntity(pickResults.objectID);
 
     mouse.startDrag(event);
 
diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js
index 827b29e78a..9edd6d006a 100644
--- a/scripts/system/libraries/controllerDispatcherUtils.js
+++ b/scripts/system/libraries/controllerDispatcherUtils.js
@@ -103,7 +103,7 @@ DISPATCHER_HOVERING_STYLE = {
     outlineOccludedColor: {red: 255, green: 128, blue: 128},
     outlineOccludedAlpha:0.0,
     fillUnoccludedColor: {red: 255, green: 255, blue: 255},
-    fillUnoccludedAlpha: 0.15,
+    fillUnoccludedAlpha: 0.12,
     fillOccludedColor: {red: 255, green: 255, blue: 255},
     fillOccludedAlpha: 0.0
 };

From cf22f613610727bc6e615b19762228533ed71b3a Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Wed, 18 Apr 2018 13:30:14 -0700
Subject: [PATCH 13/13] adding cleanup of selection

---
 scripts/system/controllers/controllerDispatcher.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js
index 04f9b3e43a..4002fd297b 100644
--- a/scripts/system/controllers/controllerDispatcher.js
+++ b/scripts/system/controllers/controllerDispatcher.js
@@ -481,6 +481,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
             Controller.disableMapping(MAPPING_NAME);
             _this.pointerManager.removePointers();
             Pointers.removePointer(this.mouseRayPick);
+            Selection.disableListHighlight(DISPATCHER_HOVERING_LIST);
         };
     }
     function mouseReleaseOnOverlay(overlayID, event) {