From 6e13203fecc0e94853fd76fcdcf6e2a72a7329d5 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@highfidelity.io>
Date: Mon, 25 Feb 2019 13:52:46 -0800
Subject: [PATCH 01/10] avoid nullptr deref

---
 interface/src/avatar/AvatarProject.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/interface/src/avatar/AvatarProject.cpp b/interface/src/avatar/AvatarProject.cpp
index b020cdb627..260ff33db7 100644
--- a/interface/src/avatar/AvatarProject.cpp
+++ b/interface/src/avatar/AvatarProject.cpp
@@ -254,11 +254,15 @@ void AvatarProject::openInInventory() const {
         DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"));
     tablet->loadQMLSource("hifi/commerce/wallet/Wallet.qml");
     DependencyManager::get<HMDScriptingInterface>()->openTablet();
-    tablet->getTabletRoot()->forceActiveFocus();
-    auto name = getProjectName();
 
     // I'm not a fan of this, but it's the only current option.
+    auto name = getProjectName();
     QTimer::singleShot(TIME_TO_WAIT_FOR_INVENTORY_TO_OPEN_MS, [name, tablet]() {
         tablet->sendToQml(QVariantMap({ { "method", "updatePurchases" }, { "filterText", name } }));
     });
+
+    QQuickItem* root = tablet->getTabletRoot();
+    if (root) {
+        root->forceActiveFocus();
+    }
 }

From a8e6d0127913487fb56322a665f653b37a3ff248 Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Thu, 28 Feb 2019 11:33:09 -0800
Subject: [PATCH 02/10] fix context overlay

---
 .../ui/overlays/ContextOverlayInterface.cpp   | 20 +++++++++----------
 .../src/ui/overlays/ContextOverlayInterface.h |  1 -
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp
index 24c0986d09..e5cec70f64 100644
--- a/interface/src/ui/overlays/ContextOverlayInterface.cpp
+++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp
@@ -50,11 +50,14 @@ ContextOverlayInterface::ContextOverlayInterface() {
     _entityPropertyFlags += PROP_OWNING_AVATAR_ID;
 
     auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
-    connect(entityScriptingInterface, &EntityScriptingInterface::clickDownOnEntity, this, &ContextOverlayInterface::clickDownOnEntity);
-    connect(entityScriptingInterface, &EntityScriptingInterface::holdingClickOnEntity, this, &ContextOverlayInterface::holdingClickOnEntity);
+    connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &ContextOverlayInterface::clickDownOnEntity);
     connect(entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity, this, &ContextOverlayInterface::mouseReleaseOnEntity);
     connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, &ContextOverlayInterface::contextOverlays_hoverEnterEntity);
     connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, &ContextOverlayInterface::contextOverlays_hoverLeaveEntity);
+
+    connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay);
+    connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay);
+
     connect(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"), &TabletProxy::tabletShownChanged, this, [&]() {
         if (_contextOverlayJustClicked && _hmdScriptingInterface->isMounted()) {
             QUuid tabletFrameID = _hmdScriptingInterface->getCurrentTabletFrameID();
@@ -70,8 +73,6 @@ ContextOverlayInterface::ContextOverlayInterface() {
         }
     });
     connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity);
-    connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay);
-    connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay);
 
     {
         _selectionScriptingInterface->enableListHighlight("contextOverlayHighlightList", QVariantMap());
@@ -106,7 +107,7 @@ void ContextOverlayInterface::clickDownOnEntity(const EntityItemID& id, const Po
     if (_enabled && event.getButton() == PointerEvent::SecondaryButton && contextOverlayFilterPassed(id)) {
         _mouseDownEntity = id;
         _mouseDownEntityTimestamp = usecTimestampNow();
-    } else if (id == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) {
+    } else if ((event.shouldFocus() || event.getButton() == PointerEvent::PrimaryButton) && id == _contextOverlayID) {
         qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "ID:" << id;
         emit contextOverlayClicked(_currentEntityWithContextOverlay);
         _contextOverlayJustClicked = true;
@@ -119,13 +120,10 @@ void ContextOverlayInterface::clickDownOnEntity(const EntityItemID& id, const Po
 }
 
 static const float CONTEXT_OVERLAY_CLICK_HOLD_TIME_MSEC = 400.0f;
-void ContextOverlayInterface::holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event) {
+void ContextOverlayInterface::mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event) {
     if (!_mouseDownEntity.isNull() && ((usecTimestampNow() - _mouseDownEntityTimestamp) > (CONTEXT_OVERLAY_CLICK_HOLD_TIME_MSEC * USECS_PER_MSEC))) {
         _mouseDownEntity = EntityItemID();
     }
-}
-
-void ContextOverlayInterface::mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event) {
     if (_enabled && event.getButton() == PointerEvent::SecondaryButton && contextOverlayFilterPassed(entityItemID) && _mouseDownEntity == entityItemID) {
         createOrDestroyContextOverlay(entityItemID, event);
     }
@@ -253,7 +251,7 @@ bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityIt
 }
 
 void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event) {
-    if (_contextOverlayID != UNKNOWN_ENTITY_ID) {
+    if (_contextOverlayID == id) {
         qCDebug(context_overlay) << "Started hovering over Context Overlay. ID:" << id;
         EntityItemProperties properties;
         properties.setColor(CONTEXT_OVERLAY_COLOR);
@@ -265,7 +263,7 @@ void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const QUuid& id,
 }
 
 void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event) {
-    if (_contextOverlayID != UNKNOWN_ENTITY_ID) {
+    if (_contextOverlayID == id) {
         qCDebug(context_overlay) << "Stopped hovering over Context Overlay. ID:" << id;
         EntityItemProperties properties;
         properties.setColor(CONTEXT_OVERLAY_COLOR);
diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h
index 57fc8ebe6e..b1b62aa0c4 100644
--- a/interface/src/ui/overlays/ContextOverlayInterface.h
+++ b/interface/src/ui/overlays/ContextOverlayInterface.h
@@ -59,7 +59,6 @@ signals:
 
 public slots:
     void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
-    void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
     void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
 
     bool createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event);

From f715dbe243ce4ea094b455c327331888aa8eb073 Mon Sep 17 00:00:00 2001
From: danteruiz <danteruiz102@gmail.com>
Date: Thu, 28 Feb 2019 11:53:20 -0800
Subject: [PATCH 03/10] fix tablet scaling

---
 .../src/RenderableWebEntityItem.cpp           |  3 +-
 libraries/entities/src/EntityItem.cpp         | 42 +++++------
 libraries/entities/src/EntityItem.h           |  2 +-
 .../entities/src/EntityItemProperties.cpp     | 46 ++++++------
 libraries/entities/src/EntityItemProperties.h |  4 +-
 libraries/entities/src/EntityPropertyFlags.h  |  4 +-
 libraries/entities/src/ModelEntityItem.cpp    | 35 +++++++--
 libraries/entities/src/ModelEntityItem.h      |  8 +-
 libraries/networking/src/udt/PacketHeaders.h  |  1 +
 .../nearParentGrabOverlay.js                  |  7 +-
 scripts/system/libraries/WebTablet.js         |  2 +-
 scripts/system/libraries/utils.js             | 74 +++++++++++++++++--
 12 files changed, 164 insertions(+), 64 deletions(-)

diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index 0f2c708d17..3b615ba467 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -266,6 +266,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
                     _webSurface->resize(QSize(windowSize.x, windowSize.y));
                     updateModelTransformAndBound();
                     _renderTransform = getModelTransform();
+                    _renderTransform.setScale(1.0f);
                     _renderTransform.postScale(entity->getScaledDimensions());
                 });
             });
@@ -487,4 +488,4 @@ QObject* WebEntityRenderer::getEventHandler() {
 
 void WebEntityRenderer::emitScriptEvent(const QVariant& message) {
     emit scriptEventReceived(message);
-}
\ No newline at end of file
+}
diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index 5dc218bc3b..5da1c05aa2 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -79,6 +79,8 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
 
     // Core
     requestedProperties += PROP_SIMULATION_OWNER;
+    requestedProperties += PROP_PARENT_ID;
+    requestedProperties += PROP_PARENT_JOINT_INDEX;
     requestedProperties += PROP_VISIBLE;
     requestedProperties += PROP_NAME;
     requestedProperties += PROP_LOCKED;
@@ -93,8 +95,6 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
     requestedProperties += PROP_LAST_EDITED_BY;
     requestedProperties += PROP_ENTITY_HOST_TYPE;
     requestedProperties += PROP_OWNING_AVATAR_ID;
-    requestedProperties += PROP_PARENT_ID;
-    requestedProperties += PROP_PARENT_JOINT_INDEX;
     requestedProperties += PROP_QUERY_AA_CUBE;
     requestedProperties += PROP_CAN_CAST_SHADOW;
     requestedProperties += PROP_VISIBLE_IN_SECONDARY_CAMERA;
@@ -260,6 +260,14 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
         //      PROP_CUSTOM_PROPERTIES_INCLUDED,
 
         APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, _simulationOwner.toByteArray());
+        // convert AVATAR_SELF_ID to actual sessionUUID.
+        QUuid actualParentID = getParentID();
+        if (actualParentID == AVATAR_SELF_ID) {
+            auto nodeList = DependencyManager::get<NodeList>();
+            actualParentID = nodeList->getSessionUUID();
+        }
+        APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, actualParentID);
+        APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
         APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible());
         APPEND_ENTITY_PROPERTY(PROP_NAME, getName());
         APPEND_ENTITY_PROPERTY(PROP_LOCKED, getLocked());
@@ -274,14 +282,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
         APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, getLastEditedBy());
         // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, (uint32_t)getEntityHostType());  // not sent over the wire
         // APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, getOwningAvatarID());            // not sent over the wire
-        // convert AVATAR_SELF_ID to actual sessionUUID.
-        QUuid actualParentID = getParentID();
-        if (actualParentID == AVATAR_SELF_ID) {
-            auto nodeList = DependencyManager::get<NodeList>();
-            actualParentID = nodeList->getSessionUUID();
-        }
-        APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, actualParentID);
-        APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
         APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube());
         APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow());
         // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, getIsVisibleInSecondaryCamera()); // not sent over the wire
@@ -792,6 +792,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
 
     // Core
     // PROP_SIMULATION_OWNER handled above
+    {   // parentID and parentJointIndex are protected by simulation ownership
+        bool oldOverwrite = overwriteLocalData;
+        overwriteLocalData = overwriteLocalData && !weOwnSimulation;
+        READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
+        READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
+        overwriteLocalData = oldOverwrite;
+    }
     READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
     READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
     READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
@@ -835,13 +842,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
     READ_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy);
     // READ_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, entity::HostType, setEntityHostType); // not sent over the wire
     // READ_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, QUuuid, setOwningAvatarID);           // not sent over the wire
-    {   // parentID and parentJointIndex are protected by simulation ownership
-        bool oldOverwrite = overwriteLocalData;
-        overwriteLocalData = overwriteLocalData && !weOwnSimulation;
-        READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
-        READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
-        overwriteLocalData = oldOverwrite;
-    }
     {   // See comment above
         auto customUpdateQueryAACubeFromNetwork = [this, shouldUpdate, lastEdited](AACube value) {
             if (shouldUpdate(_lastUpdatedQueryAACubeTimestamp, value != _lastUpdatedQueryAACubeValue)) {
@@ -1309,6 +1309,8 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire
 
     // Core
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(simulationOwner, getSimulationOwner);
+    COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
+    COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(visible, getVisible);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(name, getName);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked);
@@ -1323,8 +1325,6 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(lastEditedBy, getLastEditedBy);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(entityHostType, getEntityHostType);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(owningAvatarID, getOwningAvatarID);
-    COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
-    COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow);
     COPY_ENTITY_PROPERTY_TO_PROPERTIES(isVisibleInSecondaryCamera, isVisibleInSecondaryCamera);
@@ -1456,6 +1456,8 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
 
     // Core
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulationOwner, setSimulationOwner);
+    SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, setParentID);
+    SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
@@ -1470,8 +1472,6 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(entityHostType, setEntityHostType);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(owningAvatarID, setOwningAvatarID);
-    SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, setParentID);
-    SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(isVisibleInSecondaryCamera, setIsVisibleInSecondaryCamera);
diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h
index 0ca851e228..bd1977f053 100644
--- a/libraries/entities/src/EntityItem.h
+++ b/libraries/entities/src/EntityItem.h
@@ -197,7 +197,7 @@ public:
     void setDescription(const QString& value);
 
     /// Dimensions in meters (0.0 - TREE_SCALE)
-    glm::vec3 getScaledDimensions() const;
+    virtual glm::vec3 getScaledDimensions() const;
     virtual void setScaledDimensions(const glm::vec3& value);
     virtual glm::vec3 getRaycastDimensions() const { return getScaledDimensions(); }
 
diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp
index 7575763bf9..5ae9b30869 100644
--- a/libraries/entities/src/EntityItemProperties.cpp
+++ b/libraries/entities/src/EntityItemProperties.cpp
@@ -462,6 +462,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
 
     // Core
     CHECK_PROPERTY_CHANGE(PROP_SIMULATION_OWNER, simulationOwner);
+    CHECK_PROPERTY_CHANGE(PROP_PARENT_ID, parentID);
+    CHECK_PROPERTY_CHANGE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
     CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible);
     CHECK_PROPERTY_CHANGE(PROP_NAME, name);
     CHECK_PROPERTY_CHANGE(PROP_LOCKED, locked);
@@ -476,8 +478,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
     CHECK_PROPERTY_CHANGE(PROP_LAST_EDITED_BY, lastEditedBy);
     CHECK_PROPERTY_CHANGE(PROP_ENTITY_HOST_TYPE, entityHostType);
     CHECK_PROPERTY_CHANGE(PROP_OWNING_AVATAR_ID, owningAvatarID);
-    CHECK_PROPERTY_CHANGE(PROP_PARENT_ID, parentID);
-    CHECK_PROPERTY_CHANGE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
     CHECK_PROPERTY_CHANGE(PROP_QUERY_AA_CUBE, queryAACube);
     CHECK_PROPERTY_CHANGE(PROP_CAN_CAST_SHADOW, canCastShadow);
     CHECK_PROPERTY_CHANGE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera);
@@ -1551,6 +1551,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
 
     // Core properties
     //COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SIMULATION_OWNER, simulationOwner); // not exposed yet
+    COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_ID, parentID);
+    COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE, visible);
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NAME, name);
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
@@ -1565,8 +1567,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LAST_EDITED_BY, lastEditedBy);
     COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ENTITY_HOST_TYPE, entityHostType, getEntityHostTypeAsString());
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID);
-    COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_ID, parentID);
-    COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_JOINT_INDEX, parentJointIndex);
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_QUERY_AA_CUBE, queryAACube);
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow);
     COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera);
@@ -1956,6 +1956,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
         // not handled yet
         // COPY_PROPERTY_FROM_QSCRIPTVALUE(simulationOwner, SimulationOwner, setSimulationOwner);
     }
+    COPY_PROPERTY_FROM_QSCRIPTVALUE(parentID, QUuid, setParentID);
+    COPY_PROPERTY_FROM_QSCRIPTVALUE(parentJointIndex, quint16, setParentJointIndex);
     COPY_PROPERTY_FROM_QSCRIPTVALUE(visible, bool, setVisible);
     COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName);
     COPY_PROPERTY_FROM_QSCRIPTVALUE(locked, bool, setLocked);
@@ -1972,8 +1974,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
         COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(entityHostType, EntityHostType);
         COPY_PROPERTY_FROM_QSCRIPTVALUE(owningAvatarID, QUuid, setOwningAvatarID);
     }
-    COPY_PROPERTY_FROM_QSCRIPTVALUE(parentID, QUuid, setParentID);
-    COPY_PROPERTY_FROM_QSCRIPTVALUE(parentJointIndex, quint16, setParentJointIndex);
     COPY_PROPERTY_FROM_QSCRIPTVALUE(queryAACube, AACube, setQueryAACube); // TODO: should scripts be able to set this?
     COPY_PROPERTY_FROM_QSCRIPTVALUE(canCastShadow, bool, setCanCastShadow);
     COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera);
@@ -2243,6 +2243,8 @@ void EntityItemProperties::copyFromJSONString(QScriptEngine& scriptEngine, const
 void EntityItemProperties::merge(const EntityItemProperties& other) {
     // Core
     COPY_PROPERTY_IF_CHANGED(simulationOwner);
+    COPY_PROPERTY_IF_CHANGED(parentID);
+    COPY_PROPERTY_IF_CHANGED(parentJointIndex);
     COPY_PROPERTY_IF_CHANGED(visible);
     COPY_PROPERTY_IF_CHANGED(name);
     COPY_PROPERTY_IF_CHANGED(locked);
@@ -2257,8 +2259,6 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
     COPY_PROPERTY_IF_CHANGED(lastEditedBy);
     COPY_PROPERTY_IF_CHANGED(entityHostType);
     COPY_PROPERTY_IF_CHANGED(owningAvatarID);
-    COPY_PROPERTY_IF_CHANGED(parentID);
-    COPY_PROPERTY_IF_CHANGED(parentJointIndex);
     COPY_PROPERTY_IF_CHANGED(queryAACube);
     COPY_PROPERTY_IF_CHANGED(canCastShadow);
     COPY_PROPERTY_IF_CHANGED(isVisibleInSecondaryCamera);
@@ -2526,6 +2526,8 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
     std::call_once(initMap, []() {
         // Core
         ADD_PROPERTY_TO_MAP(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner);
+        ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid);
+        ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t);
         ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool);
         ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString);
         ADD_PROPERTY_TO_MAP(PROP_LOCKED, Locked, locked, bool);
@@ -2541,8 +2543,6 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
         ADD_PROPERTY_TO_MAP(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid);
         ADD_PROPERTY_TO_MAP(PROP_ENTITY_HOST_TYPE, EntityHostType, entityHostType, entity::HostType);
         ADD_PROPERTY_TO_MAP(PROP_OWNING_AVATAR_ID, OwningAvatarID, owningAvatarID, QUuid);
-        ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid);
-        ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t);
         ADD_PROPERTY_TO_MAP(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube);
         ADD_PROPERTY_TO_MAP(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool);
         ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool);
@@ -2998,6 +2998,8 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
 
 
             APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, properties._simulationOwner.toByteArray());
+            APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, properties.getParentID());
+            APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, properties.getParentJointIndex());
             APPEND_ENTITY_PROPERTY(PROP_VISIBLE, properties.getVisible());
             APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
             APPEND_ENTITY_PROPERTY(PROP_LOCKED, properties.getLocked());
@@ -3012,8 +3014,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
             APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, properties.getLastEditedBy());
             // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, (uint32_t)properties.getEntityHostType());              // not sent over the wire
             // APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, properties.getOwningAvatarID());                        // not sent over the wire
-            APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, properties.getParentID());
-            APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, properties.getParentJointIndex());
             APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, properties.getQueryAACube());
             APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow());
             // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, properties.getIsVisibleInSecondaryCamera()); // not sent over the wire
@@ -3124,6 +3124,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
                 APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
 
                 APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, properties.getModelURL());
+                APPEND_ENTITY_PROPERTY(PROP_MODEL_SCALE, properties.getModelScale());
                 APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, properties.getJointRotationsSet());
                 APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, properties.getJointRotations());
                 APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, properties.getJointTranslationsSet());
@@ -3477,6 +3478,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
     processedBytes += propertyFlags.getEncodedLength();
 
     READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SIMULATION_OWNER, QByteArray, setSimulationOwner);
+    READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_ID, QUuid, setParentID);
+    READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
     READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible);
     READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
     READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked);
@@ -3491,8 +3494,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
     READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy);
     // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ENTITY_HOST_TYPE, entity::HostType, setEntityHostType);            // not sent over the wire
     // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_OWNING_AVATAR_ID, QUuid, setOwningAvatarID);                       // not sent over the wire
-    READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_ID, QUuid, setParentID);
-    READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
     READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUERY_AA_CUBE, AACube, setQueryAACube);
     READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow);
     // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over the wire
@@ -3599,6 +3600,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
         READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
 
         READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MODEL_URL, QString, setModelURL);
+        READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MODEL_SCALE, vec3, setModelScale);
         READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_ROTATIONS_SET, QVector<bool>, setJointRotationsSet);
         READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_ROTATIONS, QVector<quat>, setJointRotations);
         READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS_SET, QVector<bool>, setJointTranslationsSet);
@@ -3884,6 +3886,8 @@ bool EntityItemProperties::decodeCloneEntityMessage(const QByteArray& buffer, in
 void EntityItemProperties::markAllChanged() {
     // Core
     _simulationOwnerChanged = true;
+    _parentIDChanged = true;
+    _parentJointIndexChanged = true;
     _visibleChanged = true;
     _nameChanged = true;
     _lockedChanged = true;
@@ -3898,8 +3902,6 @@ void EntityItemProperties::markAllChanged() {
     _lastEditedByChanged = true;
     _entityHostTypeChanged = true;
     _owningAvatarIDChanged = true;
-    _parentIDChanged = true;
-    _parentJointIndexChanged = true;
     _queryAACubeChanged = true;
     _canCastShadowChanged = true;
     _isVisibleInSecondaryCameraChanged = true;
@@ -4232,6 +4234,12 @@ QList<QString> EntityItemProperties::listChangedProperties() {
     if (simulationOwnerChanged()) {
         out += "simulationOwner";
     }
+    if (parentIDChanged()) {
+        out += "parentID";
+    }
+    if (parentJointIndexChanged()) {
+        out += "parentJointIndex";
+    }
     if (visibleChanged()) {
         out += "visible";
     }
@@ -4274,12 +4282,6 @@ QList<QString> EntityItemProperties::listChangedProperties() {
     if (owningAvatarIDChanged()) {
         out += "owningAvatarID";
     }
-    if (parentIDChanged()) {
-        out += "parentID";
-    }
-    if (parentJointIndexChanged()) {
-        out += "parentJointIndex";
-    }
     if (queryAACubeChanged()) {
         out += "queryAACube";
     }
diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h
index afc3537559..00a93dd129 100644
--- a/libraries/entities/src/EntityItemProperties.h
+++ b/libraries/entities/src/EntityItemProperties.h
@@ -161,6 +161,8 @@ public:
 
     // Core Properties
     DEFINE_PROPERTY_REF(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner, SimulationOwner());
+    DEFINE_PROPERTY_REF(PROP_PARENT_ID, ParentID, parentID, QUuid, UNKNOWN_ENTITY_ID);
+    DEFINE_PROPERTY_REF(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, quint16, -1);
     DEFINE_PROPERTY(PROP_VISIBLE, Visible, visible, bool, ENTITY_ITEM_DEFAULT_VISIBLE);
     DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString, ENTITY_ITEM_DEFAULT_NAME);
     DEFINE_PROPERTY(PROP_LOCKED, Locked, locked, bool, ENTITY_ITEM_DEFAULT_LOCKED);
@@ -175,8 +177,6 @@ public:
     DEFINE_PROPERTY_REF(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid, ENTITY_ITEM_DEFAULT_LAST_EDITED_BY);
     DEFINE_PROPERTY_REF_ENUM(PROP_ENTITY_HOST_TYPE, EntityHostType, entityHostType, entity::HostType, entity::HostType::DOMAIN);
     DEFINE_PROPERTY_REF_WITH_SETTER(PROP_OWNING_AVATAR_ID, OwningAvatarID, owningAvatarID, QUuid, UNKNOWN_ENTITY_ID);
-    DEFINE_PROPERTY_REF(PROP_PARENT_ID, ParentID, parentID, QUuid, UNKNOWN_ENTITY_ID);
-    DEFINE_PROPERTY_REF(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, quint16, -1);
     DEFINE_PROPERTY_REF(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube, AACube());
     DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW);
     DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA);
diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h
index cce30c9614..0326268f55 100644
--- a/libraries/entities/src/EntityPropertyFlags.h
+++ b/libraries/entities/src/EntityPropertyFlags.h
@@ -20,6 +20,8 @@ enum EntityPropertyList {
 
     // Core properties
     PROP_SIMULATION_OWNER,
+    PROP_PARENT_ID,
+    PROP_PARENT_JOINT_INDEX,
     PROP_VISIBLE,
     PROP_NAME,
     PROP_LOCKED,
@@ -34,8 +36,6 @@ enum EntityPropertyList {
     PROP_LAST_EDITED_BY,
     PROP_ENTITY_HOST_TYPE,            // not sent over the wire
     PROP_OWNING_AVATAR_ID,            // not sent over the wire
-    PROP_PARENT_ID,
-    PROP_PARENT_JOINT_INDEX,
     PROP_QUERY_AA_CUBE,
     PROP_CAN_CAST_SHADOW,
     PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over the wire
diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp
index bb8f375302..505ee26c0f 100644
--- a/libraries/entities/src/ModelEntityItem.cpp
+++ b/libraries/entities/src/ModelEntityItem.cpp
@@ -301,6 +301,31 @@ void ModelEntityItem::setModelURL(const QString& url) {
     });
 }
 
+glm::vec3 ModelEntityItem::getScaledDimensions() const {
+    glm::vec3 parentScale =  getTransform().getScale();
+    return _unscaledDimensions * parentScale;
+}
+
+void ModelEntityItem::setScaledDimensions(const glm::vec3& value) {
+    glm::vec3 parentScale = getTransform().getScale();
+    setUnscaledDimensions(value / parentScale);
+}
+
+const Transform ModelEntityItem::getTransform() const {
+    bool success;
+    return getTransform(success);
+}
+
+const Transform ModelEntityItem::getTransform(bool& success, int depth) const {
+    const Transform parentTransform = getParentTransform(success, depth);
+    Transform localTransform = getLocalTransform();
+    localTransform.postScale(getModelScale());
+
+    Transform worldTransform;
+    Transform::mult(worldTransform, parentTransform, localTransform);
+
+    return worldTransform;
+}
 void ModelEntityItem::setCompoundShapeURL(const QString& url) {
     withWriteLock([&] {
         if (_compoundShapeURL.get() != url) {
@@ -715,13 +740,13 @@ bool ModelEntityItem::applyNewAnimationProperties(AnimationPropertyGroup newProp
 }
 
 glm::vec3 ModelEntityItem::getModelScale() const {
-    return _modelScaleLock.resultWithReadLock<glm::vec3>([&] {
-        return getSNScale();
+    return resultWithReadLock<glm::vec3>([&] {
+        return _modelScale;
     });
 }
 
 void ModelEntityItem::setModelScale(const glm::vec3& modelScale) {
-    _modelScaleLock.withWriteLock([&] {
-        setSNScale(modelScale);
+    withWriteLock([&] {
+        _modelScale = modelScale;
     });
-}
\ No newline at end of file
+}
diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h
index 234cfa435e..0efbbbb16c 100644
--- a/libraries/entities/src/ModelEntityItem.h
+++ b/libraries/entities/src/ModelEntityItem.h
@@ -66,6 +66,12 @@ public:
     static const QString DEFAULT_MODEL_URL;
     QString getModelURL() const;
 
+    virtual glm::vec3 getScaledDimensions() const override;
+    virtual void setScaledDimensions(const glm::vec3& value) override;
+
+    virtual const Transform getTransform(bool& success, int depth = 0) const override;
+    virtual const Transform getTransform() const override;
+
     static const QString DEFAULT_COMPOUND_SHAPE_URL;
     QString getCompoundShapeURL() const;
 
@@ -144,7 +150,6 @@ protected:
     // they aren't currently updated from data in the model/rig, and they don't have a direct effect
     // on what's rendered.
     ReadWriteLockable _jointDataLock;
-    ReadWriteLockable _modelScaleLock;
 
     bool _jointRotationsExplicitlySet { false }; // were the joints set as a property or just side effect of animations
     bool _jointTranslationsExplicitlySet{ false }; // were the joints set as a property or just side effect of animations
@@ -159,6 +164,7 @@ protected:
     int _lastKnownCurrentFrame{-1};
 
     glm::u8vec3 _color;
+    glm::vec3 _modelScale;
     QString _modelURL;
     bool _relayParentJoints;
     bool _groupCulled { false };
diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h
index b6fcd2f2ce..4229a4a152 100644
--- a/libraries/networking/src/udt/PacketHeaders.h
+++ b/libraries/networking/src/udt/PacketHeaders.h
@@ -263,6 +263,7 @@ enum class EntityVersion : PacketVersion {
     ShowKeyboardFocusHighlight,
     WebBillboardMode,
     ModelScale,
+    ReOrderParentIDProperties,
 
     // Add new versions above here
     NUM_PACKET_TYPE,
diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js
index e59b2e35ad..5dcfee23cb 100644
--- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js
+++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js
@@ -117,11 +117,12 @@ Script.include("/~/system/libraries/utils.js");
                 this.previousParentID[this.grabbedThingID] = grabbedProperties.parentID;
                 this.previousParentJointIndex[this.grabbedThingID] = grabbedProperties.parentJointIndex;
             }
-            Overlays.editOverlay(this.grabbedThingID, reparentProps);
 
             // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix
             if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) {
-                resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex);
+                reparentAndScaleTablet(getTabletWidthFromSettings(), reparentProps);
+            } else {
+                Entities.editEntity(this.grabbedThingID, reparentProps);
             }
 
             Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
@@ -140,7 +141,7 @@ Script.include("/~/system/libraries/utils.js");
                 });
             } else if (!this.robbed){
                 // before we grabbed it, overlay was a child of something; put it back.
-                Overlays.editOverlay(this.grabbedThingID, {
+                Entities.editEntity(this.grabbedThingID, {
                     parentID: this.previousParentID[this.grabbedThingID],
                     parentJointIndex: this.previousParentJointIndex[this.grabbedThingID]
                 });
diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js
index c0e3178521..c5ae9730f2 100644
--- a/scripts/system/libraries/WebTablet.js
+++ b/scripts/system/libraries/WebTablet.js
@@ -159,7 +159,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) {
         url: url,
         localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
         localRotation: Quat.angleAxis(180, Y_AXIS),
-        dimensions: {x: screenWidth, y: screenHeight, z: 0.1},
+        dimensions: {x: screenWidth, y: screenHeight, z: 1.0},
         dpi: tabletDpi,
         color: { red: 255, green: 255, blue: 255 },
         alpha: 1.0,
diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js
index 931c346299..6f74b43a8e 100644
--- a/scripts/system/libraries/utils.js
+++ b/scripts/system/libraries/utils.js
@@ -395,7 +395,7 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
     var tabletDpi = DEFAULT_DPI * (DEFAULT_WIDTH / tabletWidth);
 
     // update tablet model dimensions
-    Overlays.editOverlay(HMD.tabletID, {
+    Entities.editEntity(HMD.tabletID, {
         dimensions: { x: tabletWidth, y: tabletHeight, z: tabletDepth }
     });
 
@@ -405,9 +405,9 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
     var screenWidth = 0.9367 * tabletWidth;
     var screenHeight = 0.9000 * tabletHeight;
     var landscape = Tablet.getTablet("com.highfidelity.interface.tablet.system").landscape;
-    Overlays.editOverlay(HMD.tabletScreenID, {
+    Entities.editEntity(HMD.tabletScreenID, {
         localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET},
-        dimensions: {x: landscape ? screenHeight : screenWidth, y: landscape ? screenWidth : screenHeight, z: 0.1},
+        dimensions: {x: landscape ? screenHeight : screenWidth, y: landscape ? screenWidth : screenHeight, z: 1.0},
         dpi: tabletDpi
     });
 
@@ -416,19 +416,83 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
     var HOME_BUTTON_X_OFFSET = 0.00079 * sensorScaleOffsetOverride * sensorScaleFactor;
     var HOME_BUTTON_Y_OFFSET = -1 * ((tabletHeight / 2) - (4.0 * tabletScaleFactor / 2)) * sensorScaleOffsetOverride;
     var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride;
-    Overlays.editOverlay(HMD.homeButtonID, {
+    Entities.editEntity(HMD.homeButtonID, {
         localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
         localRotation: { x: 0, y: 1, z: 0, w: 0 },
         dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
     });
 
-    Overlays.editOverlay(HMD.homeButtonHighlightID, {
+    Entities.editEntity(HMD.homeButtonHighlightID, {
         localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
         localRotation: { x: 0, y: 1, z: 0, w: 0 },
         dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
     });
 };
 
+
+reparentAndScaleTablet = function(width, reparentProps) {
+
+    if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID || !HMD.homeButtonHighlightID) {
+        return;
+    }
+    var sensorScaleFactor = MyAvatar.sensorToWorldScale;
+    var sensorScaleOffsetOverride = 1;
+    var SENSOR_TO_ROOM_MATRIX = 65534;
+    var parentJointIndex = reparentProps.parentJointIndex;
+    if (parentJointIndex === SENSOR_TO_ROOM_MATRIX) {
+        sensorScaleOffsetOverride = 1 / sensorScaleFactor;
+    }
+
+
+    // will need to be recaclulated if dimensions of fbx model change.
+    var TABLET_NATURAL_DIMENSIONS = {x: 32.083, y: 48.553, z: 2.269};
+    var DEFAULT_DPI = 31;
+    var DEFAULT_WIDTH = 0.4375;
+
+    // scale factor of natural tablet dimensions.
+    var tabletWidth = (width || DEFAULT_WIDTH) * sensorScaleFactor;
+    var tabletScaleFactor = tabletWidth / TABLET_NATURAL_DIMENSIONS.x;
+    var tabletHeight = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor;
+    var tabletDepth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor;
+    var tabletDpi = DEFAULT_DPI * (DEFAULT_WIDTH / tabletWidth);
+
+    // update tablet model dimensions
+
+    Entities.editEntity(HMD.tabletID, {
+        parentID: reparentProps.parentID,
+        parentJointIndex: reparentProps.parentJointIndex,
+        dimensions: { x: tabletWidth, y: tabletHeight, z: tabletDepth}
+    });
+    // update webOverlay
+    var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.5) * sensorScaleOffsetOverride;
+    var WEB_ENTITY_Y_OFFSET = 1.25 * tabletScaleFactor * sensorScaleOffsetOverride;
+    var screenWidth = 0.9367 * tabletWidth;
+    var screenHeight = 0.9000 * tabletHeight;
+    var landscape = Tablet.getTablet("com.highfidelity.interface.tablet.system").landscape;
+    Entities.editEntity(HMD.tabletScreenID, {
+        localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET},
+        dimensions: {x: landscape ? screenHeight : screenWidth, y: landscape ? screenWidth : screenHeight, z: 1.0},
+        dpi: tabletDpi
+    });
+
+    // update homeButton
+    var homeButtonDim = 4.0 * tabletScaleFactor / 1.5;
+    var HOME_BUTTON_X_OFFSET = 0.00079 * sensorScaleOffsetOverride * sensorScaleFactor;
+    var HOME_BUTTON_Y_OFFSET = -1 * ((tabletHeight / 2) - (4.0 * tabletScaleFactor / 2)) * sensorScaleOffsetOverride;
+    var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride;
+    Entities.editEntity(HMD.homeButtonID, {
+        localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
+        localRotation: { x: 0, y: 1, z: 0, w: 0 },
+        dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
+    });
+
+    Entities.editEntity(HMD.homeButtonHighlightID, {
+        localPosition: { x: -HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
+        localRotation: { x: 0, y: 1, z: 0, w: 0 },
+        dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
+    });
+}
+
 getMainTabletIDs = function () {
     var tabletIDs = [];
     if (HMD.tabletID) {

From 15064f0097d49126271e9187800360120b75dce2 Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Thu, 28 Feb 2019 14:04:22 -0800
Subject: [PATCH 04/10] fix lasers and keyboard on reload

---
 interface/src/Application.cpp | 5 +++++
 interface/src/ui/Keyboard.cpp | 8 ++++++++
 interface/src/ui/Keyboard.h   | 2 ++
 3 files changed, 15 insertions(+)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index ebc1176ee1..bfae3e7303 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5770,6 +5770,11 @@ void Application::reloadResourceCaches() {
 
     DependencyManager::get<NodeList>()->reset();  // Force redownload of .fst models
 
+    DependencyManager::get<ScriptEngines>()->reloadAllScripts();
+    getOffscreenUI()->clearCache();
+
+    DependencyManager::get<Keyboard>()->createKeyboard();
+
     getMyAvatar()->resetFullAvatarURL();
 }
 
diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp
index 1ff1c0248b..d344e27d54 100644
--- a/interface/src/ui/Keyboard.cpp
+++ b/interface/src/ui/Keyboard.cpp
@@ -259,6 +259,12 @@ void Keyboard::setUse3DKeyboard(bool use) {
 void Keyboard::createKeyboard() {
     auto pointerManager = DependencyManager::get<PointerManager>();
 
+    if (_created) {
+        pointerManager->removePointer(_leftHandStylus);
+        pointerManager->removePointer(_rightHandStylus);
+        clearKeyboardKeys();
+    }
+
     QVariantMap modelProperties {
         { "url", MALLET_MODEL_URL }
     };
@@ -289,6 +295,8 @@ void Keyboard::createKeyboard() {
     loadKeyboardFile(keyboardSvg);
 
     _keySound = DependencyManager::get<SoundCache>()->getSound(SOUND_FILE);
+
+    _created = true;
 }
 
 bool Keyboard::isRaised() const {
diff --git a/interface/src/ui/Keyboard.h b/interface/src/ui/Keyboard.h
index 627eb68dfd..b3358e486d 100644
--- a/interface/src/ui/Keyboard.h
+++ b/interface/src/ui/Keyboard.h
@@ -193,6 +193,8 @@ private:
 
     QSet<QUuid> _itemsToIgnore;
     std::vector<QHash<QUuid, Key>> _keyboardLayers;
+
+    bool _created { false };
 };
 
 #endif

From 7d9efe4c091521e8c3a0362a8cd673410a072263 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@highfidelity.io>
Date: Thu, 28 Feb 2019 14:20:11 -0800
Subject: [PATCH 05/10] avoid mem-leak for serverless domains

---
 interface/src/Application.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 83b287b7ae..9913e0d128 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -3773,9 +3773,12 @@ std::map<QString, QString> Application::prepareServerlessDomainContents(QUrl dom
         tmpTree->reaverageOctreeElements();
         tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0);
     }
+    std::map<QString, QString> namedPaths = tmpTree->getNamedPaths();
 
-    return tmpTree->getNamedPaths();
+    // we must manually eraseAllOctreeElements(false) else the tmpTree will mem-leak
+    tmpTree->eraseAllOctreeElements(false);
 
+    return namedPaths;
 }
 
 void Application::loadServerlessDomain(QUrl domainURL) {

From ed9ebf84c971ed040612d6cc7075ae6d9cd521bd Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@highfidelity.io>
Date: Thu, 28 Feb 2019 14:21:14 -0800
Subject: [PATCH 06/10] remove unuseful log entry

---
 libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index efd1399f30..e54258fc3e 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -232,8 +232,6 @@ void EntityTreeRenderer::clearNonLocalEntities() {
             }
         }
         scene->enqueueTransaction(transaction);
-    } else {
-        qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown";
     }
 
     _renderablesToUpdate = savedEntities;

From 33d6e2ce3b2e562bdac33368d7a7750113e3bd3b Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@highfidelity.io>
Date: Thu, 28 Feb 2019 14:21:35 -0800
Subject: [PATCH 07/10] avoid mem-leaked entities when clearing tree

---
 libraries/entities/src/EntityTree.cpp | 40 +++++++++++++++++++--------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp
index 53b4fb4fe4..8855bc28a7 100644
--- a/libraries/entities/src/EntityTree.cpp
+++ b/libraries/entities/src/EntityTree.cpp
@@ -52,7 +52,15 @@ EntityTree::EntityTree(bool shouldReaverage) :
 }
 
 EntityTree::~EntityTree() {
-    eraseAllOctreeElements(false);
+    // NOTE: to eraseAllOctreeElements() in this context is useless because
+    // any OctreeElements in the tree still have shared backpointers to this Tree
+    // which means the dtor never would have been called in the first place!
+    //
+    // I'm keeping this useless commented-out line to remind us:
+    // we don't need shared pointer overhead for EntityTrees.
+    // TODO: EntityTreeElement::_tree should be raw back pointer.
+    // AND: EntityItem::_element should be a raw back pointer.
+    //eraseAllOctreeElements(false); // KEEP THIS
 }
 
 void EntityTree::setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist) { 
@@ -74,16 +82,15 @@ void EntityTree::eraseNonLocalEntities() {
     emit clearingEntities();
 
     if (_simulation) {
-        // This will clear all entities host types including local entities, because local entities
-        // are not in the physics simulation
+        // local entities are not in the simulation, so we clear ALL
         _simulation->clearEntities();
     }
-    _staleProxies.clear();
-    QHash<EntityItemID, EntityItemPointer> localMap;
-    localMap.swap(_entityMap);
-    QHash<EntityItemID, EntityItemPointer> savedEntities;
     this->withWriteLock([&] {
-        foreach(EntityItemPointer entity, localMap) {
+        QHash<EntityItemID, EntityItemPointer> savedEntities;
+        // NOTE: lock the Tree first, then lock the _entityMap.
+        // It should never be done the other way around.
+        QReadLocker locker(&_entityMapLock);
+        foreach(EntityItemPointer entity, _entityMap) {
             EntityTreeElementPointer element = entity->getElement();
             if (element) {
                 element->cleanupNonLocalEntities();
@@ -91,11 +98,16 @@ void EntityTree::eraseNonLocalEntities() {
 
             if (entity->isLocalEntity()) {
                 savedEntities[entity->getEntityItemID()] = entity;
+            } else {
+                int32_t spaceIndex = entity->getSpaceIndex();
+                if (spaceIndex != -1) {
+                    // stale spaceIndices will be freed later
+                    _staleProxies.push_back(spaceIndex);
+                }
             }
         }
+        _entityMap.swap(savedEntities);
     });
-    localMap.clear();
-    _entityMap = savedEntities;
 
     resetClientEditStats();
     clearDeletedEntities();
@@ -113,13 +125,13 @@ void EntityTree::eraseNonLocalEntities() {
         _needsParentFixup = localEntitiesNeedsParentFixup;
     }
 }
+
 void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
     emit clearingEntities();
 
     if (_simulation) {
         _simulation->clearEntities();
     }
-    _staleProxies.clear();
     QHash<EntityItemID, EntityItemPointer> localMap;
     localMap.swap(_entityMap);
     this->withWriteLock([&] {
@@ -128,6 +140,11 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
             if (element) {
                 element->cleanupEntities();
             }
+            int32_t spaceIndex = entity->getSpaceIndex();
+            if (spaceIndex != -1) {
+                // assume stale spaceIndices will be freed later
+                _staleProxies.push_back(spaceIndex);
+            }
         }
     });
     localMap.clear();
@@ -767,6 +784,7 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
         // keep a record of valid stale spaceIndices so they can be removed from the Space
         int32_t spaceIndex = theEntity->getSpaceIndex();
         if (spaceIndex != -1) {
+            // stale spaceIndices will be freed later
             _staleProxies.push_back(spaceIndex);
         }
     }

From 8a7853a701a2b4790f77b05d49e94b7e7fbd48d6 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@highfidelity.io>
Date: Thu, 28 Feb 2019 14:38:13 -0800
Subject: [PATCH 08/10] remove crufty comment

---
 libraries/entities/src/EntityTree.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp
index 8855bc28a7..6e404ce690 100644
--- a/libraries/entities/src/EntityTree.cpp
+++ b/libraries/entities/src/EntityTree.cpp
@@ -781,7 +781,6 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
             _simulation->prepareEntityForDelete(theEntity);
         }
 
-        // keep a record of valid stale spaceIndices so they can be removed from the Space
         int32_t spaceIndex = theEntity->getSpaceIndex();
         if (spaceIndex != -1) {
             // stale spaceIndices will be freed later

From d33400f6ad114e85086d2b738e0f8f85fd94cc4b Mon Sep 17 00:00:00 2001
From: Dante Ruiz <danteruiz102@gmail.com>
Date: Thu, 28 Feb 2019 15:25:15 -0800
Subject: [PATCH 09/10] fix GCC compiler warning

---
 libraries/physics/src/ObjectActionTractor.cpp |  2 +-
 libraries/shared/src/NestableTransformNode.h  |  2 +-
 libraries/shared/src/SpatiallyNestable.cpp    | 22 +++++++++----------
 libraries/shared/src/SpatiallyNestable.h      |  6 ++---
 4 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/libraries/physics/src/ObjectActionTractor.cpp b/libraries/physics/src/ObjectActionTractor.cpp
index a46aac3f29..c7681e217c 100644
--- a/libraries/physics/src/ObjectActionTractor.cpp
+++ b/libraries/physics/src/ObjectActionTractor.cpp
@@ -60,7 +60,7 @@ bool ObjectActionTractor::getTarget(float deltaTimeStep, glm::quat& rotation, gl
             }
             if (other && otherIsReady) {
                 bool success;
-                glm::vec3 otherWorldPosition = other->getWorldPosition(_otherJointIndex, success);
+                glm::vec3 otherWorldPosition = other->getJointWorldPosition(_otherJointIndex, success);
                 if (!success) {
                     linearTimeScale = FLT_MAX;
                     angularTimeScale = FLT_MAX;
diff --git a/libraries/shared/src/NestableTransformNode.h b/libraries/shared/src/NestableTransformNode.h
index be017a696d..a584bcd308 100644
--- a/libraries/shared/src/NestableTransformNode.h
+++ b/libraries/shared/src/NestableTransformNode.h
@@ -32,7 +32,7 @@ public:
         }
 
         bool success;
-        Transform jointWorldTransform = nestable->getTransform(_jointIndex, success);
+        Transform jointWorldTransform = nestable->getJointTransform(_jointIndex, success);
 
         if (!success) {
             return Transform();
diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp
index e7bdc87bf3..d202afc59f 100644
--- a/libraries/shared/src/SpatiallyNestable.cpp
+++ b/libraries/shared/src/SpatiallyNestable.cpp
@@ -92,7 +92,7 @@ Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const
         return result;
     }
     if (parent) {
-        result = parent->getTransform(_parentJointIndex, success, depth + 1);
+        result = parent->getJointTransform(_parentJointIndex, success, depth + 1);
         if (getScalesWithParent()) {
             result.setScale(parent->scaleForChildren());
         }
@@ -203,7 +203,7 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position,
     }
 
     if (parent) {
-        parentTransform = parent->getTransform(parentJointIndex, success);
+        parentTransform = parent->getJointTransform(parentJointIndex, success);
         if (!success) {
             return glm::vec3(0.0f);
         }
@@ -240,7 +240,7 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation,
     }
 
     if (parent) {
-        parentTransform = parent->getTransform(parentJointIndex, success);
+        parentTransform = parent->getJointTransform(parentJointIndex, success);
         if (!success) {
             return glm::quat();
         }
@@ -350,7 +350,7 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position,
     }
 
     if (parent) {
-        parentTransform = parent->getTransform(parentJointIndex, success);
+        parentTransform = parent->getJointTransform(parentJointIndex, success);
         if (!success) {
             return glm::vec3(0.0f);
         }
@@ -390,7 +390,7 @@ glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation,
     }
 
     if (parent) {
-        parentTransform = parent->getTransform(parentJointIndex, success);
+        parentTransform = parent->getJointTransform(parentJointIndex, success);
         if (!success) {
             return glm::quat();
         }
@@ -525,8 +525,8 @@ glm::vec3 SpatiallyNestable::getWorldPosition() const {
     return result;
 }
 
-glm::vec3 SpatiallyNestable::getWorldPosition(int jointIndex, bool& success) const {
-    return getTransform(jointIndex, success).getTranslation();
+glm::vec3 SpatiallyNestable::getJointWorldPosition(int jointIndex, bool& success) const {
+    return getJointTransform(jointIndex, success).getTranslation();
 }
 
 void SpatiallyNestable::setWorldPosition(const glm::vec3& position, bool& success, bool tellPhysics) {
@@ -579,7 +579,7 @@ glm::quat SpatiallyNestable::getWorldOrientation() const {
 }
 
 glm::quat SpatiallyNestable::getWorldOrientation(int jointIndex, bool& success) const {
-    return getTransform(jointIndex, success).getRotation();
+    return getJointTransform(jointIndex, success).getRotation();
 }
 
 void SpatiallyNestable::setWorldOrientation(const glm::quat& orientation, bool& success, bool tellPhysics) {
@@ -765,7 +765,7 @@ void SpatiallyNestable::breakParentingLoop() const {
     }
 }
 
-const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success, int depth) const {
+const Transform SpatiallyNestable::getJointTransform(int jointIndex, bool& success, int depth) const {
     // this returns the world-space transform for this object.  It finds its parent's transform (which may
     // cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it.
     Transform jointInWorldFrame;
@@ -832,8 +832,8 @@ glm::vec3 SpatiallyNestable::getSNScale(bool& success) const {
     return getTransform(success).getScale();
 }
 
-glm::vec3 SpatiallyNestable::getSNScale(int jointIndex, bool& success) const {
-    return getTransform(jointIndex, success).getScale();
+glm::vec3 SpatiallyNestable::getJointSNScale(int jointIndex, bool& success) const {
+    return getJointTransform(jointIndex, success).getScale();
 }
 
 void SpatiallyNestable::setSNScale(const glm::vec3& scale) {
diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h
index a802a25e89..6b709f0352 100644
--- a/libraries/shared/src/SpatiallyNestable.h
+++ b/libraries/shared/src/SpatiallyNestable.h
@@ -129,9 +129,9 @@ public:
     virtual void setSNScale(const glm::vec3& scale, bool& success);
 
     // get world-frame values for a specific joint
-    virtual const Transform getTransform(int jointIndex, bool& success, int depth = 0) const;
-    virtual glm::vec3 getWorldPosition(int jointIndex, bool& success) const;
-    virtual glm::vec3 getSNScale(int jointIndex, bool& success) const;
+    virtual const Transform getJointTransform(int jointIndex, bool& success, int depth = 0) const;
+    virtual glm::vec3 getJointWorldPosition(int jointIndex, bool& success) const;
+    virtual glm::vec3 getJointSNScale(int jointIndex, bool& success) const;
 
     // object's parent's frame
     virtual Transform getLocalTransform() const;

From 8d5a3debfa98acce922cb41f53c0752006552471 Mon Sep 17 00:00:00 2001
From: SamGondelman <samuel_gondelman@alumni.brown.edu>
Date: Thu, 28 Feb 2019 15:24:32 -0800
Subject: [PATCH 10/10] fix chat.js textSize

---
 scripts/system/chat.js | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/scripts/system/chat.js b/scripts/system/chat.js
index b0a2e114a3..749665f3d8 100644
--- a/scripts/system/chat.js
+++ b/scripts/system/chat.js
@@ -45,6 +45,17 @@
     var speechBubbleLineHeight = 0.05; // The height of a line of text in the speech bubble.
     var SPEECH_BUBBLE_MAX_WIDTH = 1; // meters
 
+    var textSizeOverlay = Overlays.addOverlay("text3d", {
+        position: MyAvatar.position,
+        lineHeight: speechBubbleLineHeight,
+        leftMargin: 0,
+        topMargin: 0,
+        rightMargin: 0,
+        bottomMargin: 0,
+        ignoreRayIntersection: true,
+        visible: false
+    });
+
     // Load the persistent variables from the Settings, with defaults.
     function loadSettings() {
         chatName = Settings.getValue('Chat_chatName', MyAvatar.displayName);
@@ -63,6 +74,9 @@
         speechBubbleOffset = Settings.getValue('Chat_speechBubbleOffset', {x: 0.0, y: 0.3, z:0.0});
         speechBubbleJointName = Settings.getValue('Chat_speechBubbleJointName', 'Head');
         speechBubbleLineHeight = Settings.getValue('Chat_speechBubbleLineHeight', 0.05);
+        Overlays.editOverlay(textSizeOverlay, {
+            lineHeight: speechBubbleLineHeight
+        });
 
         saveSettings();
     }
@@ -637,7 +651,7 @@
         // Only overlay text3d has a way to measure the text, not entities.
         // So we make a temporary one just for measuring text, then delete it.
         var speechBubbleTextOverlayID = Overlays.addOverlay("text3d", speechBubbleParams);
-        var textSize = Overlays.textSize(speechBubbleTextOverlayID, speechBubbleMessage);
+        var textSize = Overlays.textSize(textSizeOverlay, speechBubbleMessage);
         try {
             Overlays.deleteOverlay(speechBubbleTextOverlayID);
         } catch (e) {}
@@ -971,6 +985,8 @@
         unidentifyAvatars();
         disconnectWebHandler();
 
+        Overlays.deleteOverlay(textSizeOverlay);
+
         if (onChatPage) {
             tablet.gotoHomeScreen();
             onChatPage = false;