From adb6f66a05a7ce4d9181712e5c24b8222983e70b Mon Sep 17 00:00:00 2001
From: David Rowe <david@ctrlaltstudio.com>
Date: Thu, 8 Feb 2018 09:51:48 +1300
Subject: [PATCH] Handle tablet entities and overlays not being available

---
 scripts/system/audio.js                          |  5 +++--
 .../system/controllers/controllerDispatcher.js   |  2 +-
 .../controllers/controllerModules/inEditMode.js  |  7 ++++---
 .../controllerModules/inVREditMode.js            |  5 +++--
 .../controllerModules/nearParentGrabOverlay.js   |  4 ++--
 .../controllers/controllerModules/stylusInput.js |  4 ++--
 scripts/system/controllers/grab.js               |  5 ++++-
 scripts/system/edit.js                           |  8 ++++----
 scripts/system/help.js                           |  5 ++---
 scripts/system/libraries/WebTablet.js            |  5 ++++-
 scripts/system/libraries/entitySelectionTool.js  | 11 ++++++++---
 scripts/system/libraries/utils.js                | 14 ++++++++++++++
 scripts/system/marketplaces/marketplaces.js      |  5 +++--
 scripts/system/menu.js                           |  5 +++--
 scripts/system/tablet-ui/tabletUI.js             | 16 ++++++++--------
 scripts/system/tablet-users.js                   |  5 ++---
 .../marketplace/shapes/modules/laser.js          | 12 +++++++++++-
 17 files changed, 78 insertions(+), 40 deletions(-)

diff --git a/scripts/system/audio.js b/scripts/system/audio.js
index a93177ca38..ee82c0c6ea 100644
--- a/scripts/system/audio.js
+++ b/scripts/system/audio.js
@@ -42,8 +42,9 @@ function onClicked() {
         // for toolbar-mode: go back to home screen, this will close the window.
         tablet.gotoHomeScreen();
     } else {
-        var entity = HMD.tabletID;
-        Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
+        if (HMD.tabletID) {
+            Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
+        }
         tablet.loadQMLSource(AUDIO_QML_SOURCE);
     }
 }
diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js
index 16f1d086b7..b2455b3f5a 100644
--- a/scripts/system/controllers/controllerDispatcher.js
+++ b/scripts/system/controllers/controllerDispatcher.js
@@ -146,7 +146,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
         };
 
         this.setIgnorePointerItems = function() {
-            if (HMD.tabletID !== this.tabletID) {
+            if (HMD.tabletID && HMD.tabletID !== this.tabletID) {
                 this.tabletID = HMD.tabletID;
                 Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist);
                 Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist);
diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js
index 763258573d..202290f2df 100644
--- a/scripts/system/controllers/controllerModules/inEditMode.js
+++ b/scripts/system/controllers/controllerModules/inEditMode.js
@@ -32,7 +32,7 @@ Script.include("/~/system/libraries/utils.js");
 
         this.nearTablet = function(overlays) {
             for (var i = 0; i < overlays.length; i++) {
-                if (overlays[i] === HMD.tabletID) {
+                if (HMD.tabletID && overlays[i] === HMD.tabletID) {
                     return true;
                 }
             }
@@ -44,7 +44,8 @@ Script.include("/~/system/libraries/utils.js");
         };
 
         this.pointingAtTablet = function(objectID) {
-            return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID;
+            return (HMD.tabletScreenID && objectID === HMD.tabletScreenID)
+                || (HMD.homeButtonID && objectID === HMD.homeButtonID);
         };
 
         this.sendPickData = function(controllerData) {
@@ -106,7 +107,7 @@ Script.include("/~/system/libraries/utils.js");
             if (nearOverlay) {
                 var nearOverlayReady = nearOverlay.isReady(controllerData);
 
-                if (nearOverlayReady.active && nearOverlay.grabbedThingID === HMD.tabletID) {
+                if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
                     return this.exitModule();
                 }
             }
diff --git a/scripts/system/controllers/controllerModules/inVREditMode.js b/scripts/system/controllers/controllerModules/inVREditMode.js
index 38eca65dd3..7b78d5e1c4 100644
--- a/scripts/system/controllers/controllerModules/inVREditMode.js
+++ b/scripts/system/controllers/controllerModules/inVREditMode.js
@@ -31,7 +31,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
         );
 
         this.pointingAtTablet = function (objectID) {
-            return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID;
+            return (HMD.tabletScreenID && objectID === HMD.tabletScreenID)
+                || (HMD.homeButtonID && objectID === HMD.homeButtonID);
         };
 
         this.isReady = function (controllerData) {
@@ -76,7 +77,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
                 : "LeftNearParentingGrabOverlay");
             if (nearOverlay) {
                 var nearOverlayReady = nearOverlay.isReady(controllerData);
-                if (nearOverlayReady.active && nearOverlay.grabbedThingID === HMD.tabletID) {
+                if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
                     return makeRunningValues(false, [], []);
                 }
             }
diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js
index fa0fe31de2..0f876816b3 100644
--- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js
+++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js
@@ -117,7 +117,7 @@ Script.include("/~/system/libraries/utils.js");
             Overlays.editOverlay(this.grabbedThingID, reparentProps);
 
             // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix
-            if (this.grabbedThingID === HMD.tabletID) {
+            if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) {
                 resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex);
             }
 
@@ -143,7 +143,7 @@ Script.include("/~/system/libraries/utils.js");
                 });
 
                 // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix
-                if (this.grabbedThingID === HMD.tabletID) {
+                if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) {
                     resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]);
                 }
             }
diff --git a/scripts/system/controllers/controllerModules/stylusInput.js b/scripts/system/controllers/controllerModules/stylusInput.js
index aa65135289..a512fd89db 100644
--- a/scripts/system/controllers/controllerModules/stylusInput.js
+++ b/scripts/system/controllers/controllerModules/stylusInput.js
@@ -20,7 +20,7 @@ Script.include("/~/system/libraries/controllers.js");
         var stylusTargetIDs = [];
         for (var index = 0; index < stylusTargets.length; index++) {
             var stylusTarget = stylusTargets[index];
-            if (stylusTarget.distance <= maxNormalDistance && stylusTarget.id !== HMD.tabletID) {
+            if (stylusTarget.distance <= maxNormalDistance && !(HMD.tabletID && stylusTarget.id === HMD.tabletID)) {
                 stylusTargetIDs.push(stylusTarget.id);
             }
         }
@@ -96,7 +96,7 @@ Script.include("/~/system/libraries/controllers.js");
             var i, stylusTarget;
 
             for (i = 0; i < candidateOverlays.length; i++) {
-                if (candidateOverlays[i] !== HMD.tabletID &&
+                if (!(HMD.tabletID && candidateOverlays[i] === HMD.tabletID) &&
                     Overlays.getProperty(candidateOverlays[i], "visible")) {
                     stylusTarget = getOverlayDistance(controllerPosition, candidateOverlays[i]);
                     if (stylusTarget) {
diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js
index a51cea67f8..b62cb3dd90 100644
--- a/scripts/system/controllers/grab.js
+++ b/scripts/system/controllers/grab.js
@@ -263,7 +263,10 @@ function Grabber() {
         filter: Picks.PICK_OVERLAYS,
         enabled: true
     });
-    RayPick.setIncludeItems(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
+    var tabletItems = getMainTabletIDs();
+    if (tabletItems.length > 0) {
+        RayPick.setIncludeItems(this.mouseRayOverlays, tabletItems);
+    }
     var renderStates = [{name: "grabbed", end: beacon}];
     this.mouseRayEntities = Pointers.createPointer(PickType.Ray, {
         joint: "Mouse",
diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index 863c185cb4..42c1cc4b51 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -31,6 +31,7 @@ Script.include([
     "libraries/entityCameraTool.js",
     "libraries/gridTool.js",
     "libraries/entityList.js",
+    "libraries/utils.js",
     "particle_explorer/particleExplorerTool.js",
     "libraries/entityIconOverlayManager.js"
 ]);
@@ -733,8 +734,7 @@ function findClickedEntity(event) {
     }
 
     var pickRay = Camera.computePickRay(event.x, event.y);
-
-    var overlayResult = Overlays.findRayIntersection(pickRay, true, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
+    var overlayResult = Overlays.findRayIntersection(pickRay, true, getMainTabletIDs());
     if (overlayResult.intersects) {
         return null;
     }
@@ -922,7 +922,7 @@ function mouseReleaseEvent(event) {
 
 function wasTabletClicked(event) {
     var rayPick = Camera.computePickRay(event.x, event.y);
-    var result = Overlays.findRayIntersection(rayPick, true, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
+    var result = Overlays.findRayIntersection(rayPick, true, getMainTabletIDs());
     return result.intersects;
 }
 
@@ -945,7 +945,7 @@ function mouseClickEvent(event) {
         toolBar.setActive(true);
         var pickRay = result.pickRay;
         var foundEntity = result.entityID;
-        if (foundEntity === HMD.tabletID) {
+        if (HMD.tabletID && foundEntity === HMD.tabletID) {
             return;
         }
         properties = Entities.getEntityProperties(foundEntity);
diff --git a/scripts/system/help.js b/scripts/system/help.js
index 9ab7fa3fb3..6fe0da8a86 100644
--- a/scripts/system/help.js
+++ b/scripts/system/help.js
@@ -30,9 +30,8 @@
         if (onHelpScreen) {
             tablet.gotoHomeScreen();
         } else {
-            var tabletEntity = HMD.tabletID;
-            if (tabletEntity) {
-                Entities.editEntity(tabletEntity, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
+            if (HMD.tabletID) {
+                Entities.editEntity(HMD.tabletID, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
             }
             Menu.triggerOption('Help...');
             onHelpScreen = true;
diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js
index 05b4963280..c4ad2b43a7 100644
--- a/scripts/system/libraries/WebTablet.js
+++ b/scripts/system/libraries/WebTablet.js
@@ -334,7 +334,7 @@ WebTablet.prototype.destroy = function () {
 };
 
 WebTablet.prototype.geometryChanged = function (geometry) {
-    if (!HMD.active) {
+    if (!HMD.active && HMD.tabletID) {
         var tabletProperties = {};
         // compute position, rotation & parentJointIndex of the tablet
         this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
@@ -462,6 +462,9 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMou
 };
 
 WebTablet.prototype.onHmdChanged = function () {
+    if (!HMD.tabletID) {
+        return;
+    }
     var tabletProperties = {};
     // compute position, rotation & parentJointIndex of the tablet
     this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js
index b8ba146757..eea541a430 100644
--- a/scripts/system/libraries/entitySelectionTool.js
+++ b/scripts/system/libraries/entitySelectionTool.js
@@ -19,7 +19,10 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
 SPACE_LOCAL = "local";
 SPACE_WORLD = "world";
 
-Script.include("./controllers.js");
+Script.include([
+    "./controllers.js",
+    "./utils.js"
+]);
 
 function objectTranslationPlanePoint(position, dimensions) {
     var newPosition = { x: position.x, y: position.y, z: position.z };
@@ -3650,7 +3653,8 @@ SelectionDisplay = (function() {
 
         var pickRay = generalComputePickRay(event.x, event.y);
         // TODO_Case6491:  Move this out to setup just to make it once
-        var interactiveOverlays = [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, selectionBox];
+        var interactiveOverlays = getMainTabletIDs();
+        interactiveOverlays.push(selectionBox);
         for (var key in grabberTools) {
             if (grabberTools.hasOwnProperty(key)) {
                 interactiveOverlays.push(key);
@@ -3663,7 +3667,8 @@ SelectionDisplay = (function() {
         var results = testRayIntersect(pickRay, interactiveOverlays);
         if (results.intersects) {
             var hitOverlayID = results.overlayID;
-            if ((hitOverlayID === HMD.tabletID) || (hitOverlayID === HMD.tabletScreenID) || (hitOverlayID === HMD.homeButtonID)) {
+            if ((HMD.tabletID && hitOverlayID === HMD.tabletID) || (HMD.tabletScreenID && hitOverlayID === HMD.tabletScreenID)
+                    || (HMD.homeButtonID && hitOverlayID === HMD.homeButtonID)) {
                 // EARLY EXIT-(mouse clicks on the tablet should override the edit affordances)
                 return false;
             }
diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js
index bc83cc582c..442a9f6d24 100644
--- a/scripts/system/libraries/utils.js
+++ b/scripts/system/libraries/utils.js
@@ -428,3 +428,17 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
         dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
     });
 };
+
+getMainTabletIDs = function () {
+    var tabletIDs = [];
+    if (HMD.tabletID) {
+        tabletIDs.push(HMD.tabletID);
+    }
+    if (HMD.tabletScreenID) {
+        tabletIDs.push(HMD.tabletScreenID);
+    }
+    if (HMD.homeButtonID) {
+        tabletIDs.push(HMD.homeButtonID);
+    }
+    return tabletIDs;
+};
\ No newline at end of file
diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js
index facb932eb0..5d905f7553 100644
--- a/scripts/system/marketplaces/marketplaces.js
+++ b/scripts/system/marketplaces/marketplaces.js
@@ -104,8 +104,9 @@ var selectionDisplay = null; // for gridTool.js to ignore
             tablet.gotoHomeScreen();
         } else {
             Wallet.refreshWalletStatus();
-            var entity = HMD.tabletID;
-            Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
+            if (HMD.tabletID) {
+                Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
+            }
             showMarketplace();
         }
     }
diff --git a/scripts/system/menu.js b/scripts/system/menu.js
index c7a44d3e48..c27dae6780 100644
--- a/scripts/system/menu.js
+++ b/scripts/system/menu.js
@@ -28,8 +28,9 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-
             // for toolbar-mode: go back to home screen, this will close the window.
             tablet.gotoHomeScreen();
         } else {
-            var entity = HMD.tabletID;
-            Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})});
+            if (HMD.tabletID) {
+                Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
+            }
             tablet.gotoMenuScreen();
         }
     }
diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js
index 36a1cbcdd9..100d0e82ee 100644
--- a/scripts/system/tablet-ui/tabletUI.js
+++ b/scripts/system/tablet-ui/tabletUI.js
@@ -41,14 +41,14 @@
         if (!UIWebTablet) {
             return false;
         }
-        if (Overlays.getProperty(HMD.tabletID, "type") != "model") {
+        if (Overlays.getProperty(HMD.tabletID, "type") !== "model") {
             if (debugTablet) {
                 print("TABLET is invalid due to frame: " + JSON.stringify(Overlays.getProperty(HMD.tabletID, "type")));
             }
             return false;
         }
-        if (Overlays.getProperty(HMD.homeButtonID, "type") != "circle3d" ||
-            Overlays.getProperty(HMD.tabletScreenID, "type") != "web3d") {
+        if (Overlays.getProperty(HMD.homeButtonID, "type") !== "circle3d" ||
+                Overlays.getProperty(HMD.tabletScreenID, "type") !== "web3d") {
             if (debugTablet) {
                 print("TABLET is invalid due to other");
             }
@@ -112,7 +112,7 @@
     }
 
     function showTabletUI() {
-        checkTablet()
+        checkTablet();
 
         if (!tabletRezzed || !tabletIsValid()) {
             closeTabletUI();
@@ -157,7 +157,7 @@
     }
 
     function closeTabletUI() {
-        checkTablet()
+        checkTablet();
         gTablet.tabletShown = false;
         if (UIWebTablet) {
             if (UIWebTablet.onClose) {
@@ -178,14 +178,14 @@
             print("TABLET closeTabletUI, UIWebTablet is null");
         }
         tabletRezzed = false;
-        gTablet = null
+        gTablet = null;
     }
 
 
     function updateShowTablet() {
         var now = Date.now();
 
-        checkTablet()
+        checkTablet();
 
         // close the WebTablet if it we go into toolbar mode.
         var tabletShown = gTablet.tabletShown;
@@ -270,7 +270,7 @@
         }
         if (channel === "home") {
             if (UIWebTablet) {
-                checkTablet()
+                checkTablet();
                 gTablet.landscape = false;
             }
         }
diff --git a/scripts/system/tablet-users.js b/scripts/system/tablet-users.js
index 6181173818..92aefd1e80 100644
--- a/scripts/system/tablet-users.js
+++ b/scripts/system/tablet-users.js
@@ -48,9 +48,8 @@
             // for toolbar-mode: go back to home screen, this will close the window.
             tablet.gotoHomeScreen();
         } else {
-            var tabletEntity = HMD.tabletID;
-            if (tabletEntity) {
-                Entities.editEntity(tabletEntity, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
+            if (HMD.tabletID) {
+                Entities.editEntity(HMD.tabletID, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
             }
             shouldActivateButton = true;
             tablet.gotoWebScreen(USERS_URL);
diff --git a/unpublishedScripts/marketplace/shapes/modules/laser.js b/unpublishedScripts/marketplace/shapes/modules/laser.js
index d5feda0e1f..067b605047 100644
--- a/unpublishedScripts/marketplace/shapes/modules/laser.js
+++ b/unpublishedScripts/marketplace/shapes/modules/laser.js
@@ -173,8 +173,18 @@ Laser = function (side) {
             // Normal laser operation with trigger.
             intersection = Overlays.findRayIntersection(pickRay, PRECISION_PICKING, NO_INCLUDE_IDS, NO_EXCLUDE_IDS,
                 VISIBLE_ONLY);
+            var tabletIDs = [];
+            if (HMD.tabletID) {
+                tabletIDs.push(HMD.tabletID);
+            }
+            if (HMD.tabletScreenID) {
+                tabletIDs.push(HMD.tabletScreenID);
+            }
+            if (HMD.homeButtonID) {
+                tabletIDs.push(HMD.homeButtonID);
+            }
             if (Reticle.pointingAtSystemOverlay || (intersection.overlayID
-                    && [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID].indexOf(intersection.overlayID) !== -1)) {
+                    && tabletIDs.indexOf(intersection.overlayID) !== -1)) {
                 // No laser if pointing at HUD overlay or tablet; system provides lasers for these cases.
                 if (isLaserOn) {
                     isLaserOn = false;