From 4344a35c60f421e99e48df11612ac75c1cd21f28 Mon Sep 17 00:00:00 2001
From: howard-stearns <howard.stearns@gmail.com>
Date: Fri, 10 Jun 2016 16:00:16 -0700
Subject: [PATCH 1/3] Use the new system pointer functionality.

---
 .../controllers/handControllerPointer.js      | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js
index 7b45babf4d..1728647e5e 100644
--- a/scripts/system/controllers/handControllerPointer.js
+++ b/scripts/system/controllers/handControllerPointer.js
@@ -305,13 +305,19 @@ var leftTrigger = new Trigger();
 var rightTrigger = new Trigger();
 var activeTrigger = rightTrigger;
 var activeHand = Controller.Standard.RightHand;
+var LEFT_HUD_LASER = 1;
+var RIGHT_HUD_LASER = 2;
+var BOTH_HUD_LASERS = LEFT_HUD_LASER + RIGHT_HUD_LASER;
+var activeHudLaser = RIGHT_HUD_LASER;
 function toggleHand() { // unequivocally switch which hand controls mouse position
     if (activeHand === Controller.Standard.RightHand) {
         activeHand = Controller.Standard.LeftHand;
         activeTrigger = leftTrigger;
+        activeHudLaser = LEFT_HUD_LASER;
     } else {
         activeHand = Controller.Standard.RightHand;
         activeTrigger = rightTrigger;
+        activeHudLaser = RIGHT_HUD_LASER;
     }
 }
 function makeToggleAction(hand) { // return a function(0|1) that makes the specified hand control mouse when 1
@@ -342,6 +348,7 @@ clickMapping.enable();
 // Same properties as handControllerGrab search sphere
 var BALL_SIZE = 0.011;
 var BALL_ALPHA = 0.5;
+var LASER_COLOR_XYZW = {x: 10 / 255, y: 10 / 255, z: 255 / 255, w: BALL_ALPHA};
 var fakeProjectionBall = Overlays.addOverlay("sphere", {
     size: 5 * BALL_SIZE,
     color: {red: 255, green: 10, blue: 10},
@@ -356,9 +363,24 @@ Script.scriptEnding.connect(function () {
     overlays.forEach(Overlays.deleteOverlay);
 });
 var visualizationIsShowing = false; // Not whether it desired, but simply whether it is. Just an optimziation.
+var systemLaserOn = false;
+var SYSTEM_LASER_DIRECTION = Vec3.normalize({x: 0, y: -1, z: -1}); // Guessing 45 degrees.
+function clearSystemLaser() {
+    if (!systemLaserOn) {
+        return;
+    }
+    print('FIXME remove: disableHandLasers', BOTH_HUD_LASERS);
+    HMD.disableHandLasers(BOTH_HUD_LASERS);
+    systemLaserOn = false;
+}
 function turnOffVisualization(optionalEnableClicks) { // because we're showing cursor on HUD
     if (!optionalEnableClicks) {
         expireMouseCursor();
+        clearSystemLaser();
+    } else if (!systemLaserOn) {
+        print('FIXME remove: setHandLasers', activeHudLaser, true, JSON.stringify(LASER_COLOR_XYZW), JSON.stringify(SYSTEM_LASER_DIRECTION));
+        HMD.setHandLasers(activeHudLaser, true, LASER_COLOR_XYZW, SYSTEM_LASER_DIRECTION);
+        systemLaserOn = true;
     }
     if (!visualizationIsShowing) {
         return;
@@ -371,6 +393,7 @@ function turnOffVisualization(optionalEnableClicks) { // because we're showing c
 var MAX_RAY_SCALE = 32000; // Anything large. It's a scale, not a distance.
 function updateVisualization(controllerPosition, controllerDirection, hudPosition3d, hudPosition2d) {
     ignore(controllerPosition, controllerDirection, hudPosition2d);
+    clearSystemLaser();
     // Show an indication of where the cursor will appear when crossing a HUD element,
     // and where in-world clicking will occur.
     //

From 526fc7d062366dbf3b2be7c8e87b80c70d01e391 Mon Sep 17 00:00:00 2001
From: howard-stearns <howard.stearns@gmail.com>
Date: Mon, 13 Jun 2016 17:13:10 -0700
Subject: [PATCH 2/3] Make handControllerGrab independent of whether we're
 using laser or Reticle.

---
 scripts/system/controllers/handControllerGrab.js | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js
index 25cd100991..53c16f26c1 100644
--- a/scripts/system/controllers/handControllerGrab.js
+++ b/scripts/system/controllers/handControllerGrab.js
@@ -300,7 +300,10 @@ function propsArePhysical(props) {
 // and we should not be showing lasers when someone else is using the Reticle to indicate a 2D minor mode.
 var EXTERNALLY_MANAGED_2D_MINOR_MODE = true;
 function isIn2DMode() {
-    return EXTERNALLY_MANAGED_2D_MINOR_MODE && Reticle.visible;
+    // In this version, we make our own determination of whether we're aimed a HUD element,
+    // because other scripts (such as handControllerPointer) might be using some other visualization
+    // instead of setting Reticle.visible.
+    return EXTERNALLY_MANAGED_2D_MINOR_MODE && (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position));
 }
 function restore2DMode() {
     if (!EXTERNALLY_MANAGED_2D_MINOR_MODE) {

From dfd03d5e6184ffb7a0f3b9a0b81e584dcf78e2a6 Mon Sep 17 00:00:00 2001
From: howard-stearns <howard.stearns@gmail.com>
Date: Mon, 13 Jun 2016 17:15:51 -0700
Subject: [PATCH 3/3] Prepare for working laser. But at this point, we still
 show the laser AND the Reticle.

---
 .../system/controllers/handControllerPointer.js  | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js
index 1728647e5e..f5c0c4bb7c 100644
--- a/scripts/system/controllers/handControllerPointer.js
+++ b/scripts/system/controllers/handControllerPointer.js
@@ -319,6 +319,7 @@ function toggleHand() { // unequivocally switch which hand controls mouse positi
         activeTrigger = rightTrigger;
         activeHudLaser = RIGHT_HUD_LASER;
     }
+    clearSystemLaser();
 }
 function makeToggleAction(hand) { // return a function(0|1) that makes the specified hand control mouse when 1
     return function (on) {
@@ -335,8 +336,8 @@ Script.scriptEnding.connect(clickMapping.disable);
 clickMapping.from(Controller.Standard.RT).peek().to(rightTrigger.triggerPress);
 clickMapping.from(Controller.Standard.LT).peek().to(leftTrigger.triggerPress);
 // Full smoothed trigger is a click.
-clickMapping.from(rightTrigger.full).to(Controller.Actions.ReticleClick);
-clickMapping.from(leftTrigger.full).to(Controller.Actions.ReticleClick);
+clickMapping.from(rightTrigger.full).when(isPointingAtOverlay).to(Controller.Actions.ReticleClick);
+clickMapping.from(leftTrigger.full).when(isPointingAtOverlay).to(Controller.Actions.ReticleClick);
 clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(Controller.Actions.ContextMenu);
 clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(Controller.Actions.ContextMenu);
 // Partial smoothed trigger is activation.
@@ -363,8 +364,8 @@ Script.scriptEnding.connect(function () {
     overlays.forEach(Overlays.deleteOverlay);
 });
 var visualizationIsShowing = false; // Not whether it desired, but simply whether it is. Just an optimziation.
-var systemLaserOn = false;
 var SYSTEM_LASER_DIRECTION = Vec3.normalize({x: 0, y: -1, z: -1}); // Guessing 45 degrees.
+var systemLaserOn = false;
 function clearSystemLaser() {
     if (!systemLaserOn) {
         return;
@@ -379,8 +380,12 @@ function turnOffVisualization(optionalEnableClicks) { // because we're showing c
         clearSystemLaser();
     } else if (!systemLaserOn) {
         print('FIXME remove: setHandLasers', activeHudLaser, true, JSON.stringify(LASER_COLOR_XYZW), JSON.stringify(SYSTEM_LASER_DIRECTION));
-        HMD.setHandLasers(activeHudLaser, true, LASER_COLOR_XYZW, SYSTEM_LASER_DIRECTION);
+        // If the active plugin doesn't implement hand lasers, show the mouse reticle instead.
+        /*Reticle.visible = !*/HMD.setHandLasers(activeHudLaser, true, LASER_COLOR_XYZW, SYSTEM_LASER_DIRECTION);
+        Reticle.visible = true; // FIXME: just for now, while hand lasers has the bug that requires this.
         systemLaserOn = true;
+    } else {
+        Reticle.visible = true;
     }
     if (!visualizationIsShowing) {
         return;
@@ -415,9 +420,11 @@ function updateVisualization(controllerPosition, controllerDirection, hudPositio
     // For now, though, we present a false projection of the cursor onto whatever is below it. This is
     // different from the hand beam termination because the false projection is from the camera, while
     // the hand beam termination is from the hand.
+    /* // FIXME: We can tighten this up later, once we know what will and won't be included.
     var eye = Camera.getPosition();
     var falseProjection = intersection3d(eye, Vec3.subtract(hudPosition3d, eye));
     Overlays.editOverlay(fakeProjectionBall, {visible: true, position: falseProjection});
+    */
     Reticle.visible = false;
 
     return visualizationIsShowing; // In case we change caller to act conditionally.
@@ -465,7 +472,6 @@ function update() {
         if (HMD.active) {  // Doesn't hurt anything without the guard, but consider it documentation.
             Reticle.depth = SPHERICAL_HUD_DISTANCE; // NOT CORRECT IF WE SWITCH TO OFFSET SPHERE!
         }
-        Reticle.visible = true;
         return turnOffVisualization(true);
     }
     // We are not pointing at a HUD element (but it could be a 3d overlay).