From eb26d9b4e38de4dcced40cf18a051577d84bd64a Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Fri, 3 Apr 2020 14:28:33 -0700
Subject: [PATCH 1/6] working on parenting fixes

---
 .../qml/+android_interface/Stats.qml          |  4 +++
 interface/resources/qml/Stats.qml             |  4 +++
 interface/src/ui/Stats.cpp                    |  2 ++
 interface/src/ui/Stats.h                      | 18 ++++++++++++
 .../src/EntityTreeRenderer.cpp                |  7 +++--
 .../src/EntityTreeRenderer.h                  |  5 ++++
 .../src/RenderableEntityItem.cpp              | 20 ++++---------
 .../src/RenderableEntityItem.h                |  7 +----
 .../src/RenderableGizmoEntityItem.cpp         | 19 +++++++------
 .../src/RenderableGizmoEntityItem.h           |  1 +
 .../src/RenderableGridEntityItem.cpp          |  3 +-
 .../src/RenderableImageEntityItem.cpp         | 16 +++++------
 .../RenderableParticleEffectEntityItem.cpp    | 28 ++++++++++++++++---
 .../src/RenderableParticleEffectEntityItem.h  |  2 ++
 .../src/RenderablePolyLineEntityItem.cpp      |  3 +-
 .../src/RenderableShapeEntityItem.cpp         |  7 ++---
 .../src/RenderableTextEntityItem.cpp          |  3 +-
 .../src/RenderableWebEntityItem.cpp           |  3 +-
 .../src/RenderableZoneEntityItem.cpp          | 10 -------
 .../src/RenderableZoneEntityItem.h            |  1 -
 libraries/entities/src/EntityItem.cpp         | 20 ++++++++-----
 libraries/entities/src/EntityItem.h           |  4 +--
 libraries/entities/src/GizmoEntityItem.cpp    |  1 +
 libraries/entities/src/GridEntityItem.cpp     |  1 +
 libraries/entities/src/ImageEntityItem.cpp    |  1 +
 libraries/entities/src/LightEntityItem.cpp    | 16 +----------
 libraries/entities/src/LightEntityItem.h      |  3 --
 libraries/entities/src/LineEntityItem.cpp     |  1 +
 libraries/entities/src/MaterialEntityItem.cpp |  1 +
 libraries/entities/src/ModelEntityItem.cpp    |  1 +
 .../entities/src/ParticleEffectEntityItem.cpp |  1 +
 libraries/entities/src/PolyLineEntityItem.cpp |  1 +
 libraries/entities/src/PolyVoxEntityItem.cpp  |  1 +
 libraries/entities/src/ShapeEntityItem.cpp    |  1 +
 libraries/entities/src/TextEntityItem.cpp     |  1 +
 libraries/entities/src/WebEntityItem.cpp      |  1 +
 libraries/entities/src/ZoneEntityItem.cpp     |  1 +
 libraries/render-utils/src/Model.cpp          | 12 ++++----
 libraries/render-utils/src/Model.h            |  6 ++--
 39 files changed, 134 insertions(+), 103 deletions(-)

diff --git a/interface/resources/qml/+android_interface/Stats.qml b/interface/resources/qml/+android_interface/Stats.qml
index 1f07af786f..b44b95c5ca 100644
--- a/interface/resources/qml/+android_interface/Stats.qml
+++ b/interface/resources/qml/+android_interface/Stats.qml
@@ -386,6 +386,10 @@ Item {
                         visible: root.expanded
                         text: "LOD: " + root.lodStatus;
                     }
+                    StatText {
+                        visible: root.expanded
+                        text: "Entity Updates: " + root.numEntityUpdates + " / " + root.numNeededEntityUpdates;
+                    }
                 }
             }
         }
diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml
index 23aa256cdc..9e4fdffaee 100644
--- a/interface/resources/qml/Stats.qml
+++ b/interface/resources/qml/Stats.qml
@@ -437,6 +437,10 @@ Item {
                         visible: root.expanded
                         text: "LOD: " + root.lodStatus;
                     }
+                    StatText {
+                        visible: root.expanded
+                        text: "Entity Updates: " + root.numEntityUpdates + " / " + root.numNeededEntityUpdates;
+                    }
                 }
             }
         }
diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp
index 8b9b9743f0..a9e2e4d8e3 100644
--- a/interface/src/ui/Stats.cpp
+++ b/interface/src/ui/Stats.cpp
@@ -456,6 +456,8 @@ void Stats::updateStats(bool force) {
         STAT_UPDATE(localLeaves, (int)OctreeElement::getLeafNodeCount());
         // LOD Details
         STAT_UPDATE(lodStatus, "You can see " + DependencyManager::get<LODManager>()->getLODFeedbackText());
+        STAT_UPDATE(numEntityUpdates, DependencyManager::get<EntityTreeRenderer>()->getPrevNumEntityUpdates());
+        STAT_UPDATE(numNeededEntityUpdates, DependencyManager::get<EntityTreeRenderer>()->getPrevTotalNeededEntityUpdates());
     }
 
 
diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h
index b87e3a3dbc..96f0ea725a 100644
--- a/interface/src/ui/Stats.h
+++ b/interface/src/ui/Stats.h
@@ -112,6 +112,8 @@ private: \
  * @property {number} lodAngle - <em>Read-only.</em>
  * @property {number} lodTargetFramerate - <em>Read-only.</em>
  * @property {string} lodStatus - <em>Read-only.</em>
+ * @property {string} numEntityUpdates - <em>Read-only.</em>
+ * @property {string} numNeededEntityUpdates - <em>Read-only.</em>
  * @property {string} timingStats - <em>Read-only.</em>
  * @property {string} gameUpdateStats - <em>Read-only.</em>
  * @property {number} serverElements - <em>Read-only.</em>
@@ -277,6 +279,8 @@ class Stats : public QQuickItem {
     STATS_PROPERTY(int, lodAngle, 0)
     STATS_PROPERTY(int, lodTargetFramerate, 0)
     STATS_PROPERTY(QString, lodStatus, QString())
+    STATS_PROPERTY(int, numEntityUpdates, 0)
+    STATS_PROPERTY(int, numNeededEntityUpdates, 0)
     STATS_PROPERTY(QString, timingStats, QString())
     STATS_PROPERTY(QString, gameUpdateStats, QString())
     STATS_PROPERTY(int, serverElements, 0)
@@ -883,6 +887,20 @@ signals:
      */
     void lodStatusChanged();
 
+    /**jsdoc
+     * Triggered when the value of the <code>numEntityUpdates</code> property changes.
+     * @function Stats.numEntityUpdatesChanged
+     * @returns {Signal}
+     */
+    void numEntityUpdatesChanged();
+
+    /**jsdoc
+     * Triggered when the value of the <code>numNeededEntityUpdates</code> property changes.
+     * @function Stats.numNeededEntityUpdatesChanged
+     * @returns {Signal}
+     */
+    void numNeededEntityUpdatesChanged();
+
     /**jsdoc
      * Triggered when the value of the <code>serverElements</code> property changes.
      * @function Stats.serverElementsChanged
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index ab3f4c5243..5e05ebf5c9 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -426,6 +426,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
     }
 
     float expectedUpdateCost = _avgRenderableUpdateCost * _renderablesToUpdate.size();
+    _prevTotalNeededEntityUpdates = _renderablesToUpdate.size();
     if (expectedUpdateCost < MAX_UPDATE_RENDERABLES_TIME_BUDGET) {
         // we expect to update all renderables within available time budget
         PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
@@ -434,7 +435,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
             assert(renderable); // only valid renderables are added to _renderablesToUpdate
             renderable->updateInScene(scene, transaction);
         }
-        size_t numRenderables = _renderablesToUpdate.size() + 1; // add one to avoid divide by zero
+        _prevNumEntityUpdates = _renderablesToUpdate.size();
+        size_t numRenderables = _prevNumEntityUpdates + 1; // add one to avoid divide by zero
         _renderablesToUpdate.clear();
 
         // compute average per-renderable update cost
@@ -495,7 +497,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
             }
 
             // compute average per-renderable update cost
-            size_t numUpdated = sortedRenderables.size() - _renderablesToUpdate.size() + 1; // add one to avoid divide by zero
+           _prevNumEntityUpdates = sortedRenderables.size() - _renderablesToUpdate.size();
+            size_t numUpdated = _prevNumEntityUpdates + 1; // add one to avoid divide by zero
             float cost = (float)(usecTimestampNow() - updateStart) / (float)(numUpdated);
             const float BLEND = 0.1f;
             _avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost;
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h
index 6dbaedc123..36ec94c464 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.h
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.h
@@ -135,6 +135,9 @@ public:
     static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName);
     static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName);
 
+    int getPrevNumEntityUpdates() const { return _prevNumEntityUpdates; }
+    int getPrevTotalNeededEntityUpdates() const { return _prevTotalNeededEntityUpdates; }
+
 signals:
     void enterEntity(const EntityItemID& entityItemID);
     void leaveEntity(const EntityItemID& entityItemID);
@@ -248,6 +251,8 @@ private:
 
     ReadWriteLockable _changedEntitiesGuard;
     std::unordered_set<EntityItemID> _changedEntities;
+    int _prevNumEntityUpdates { 0 };
+    int _prevTotalNeededEntityUpdates { 0 };
 
     std::unordered_set<EntityRendererPointer> _renderablesToUpdate;
     std::unordered_map<EntityItemID, EntityRendererPointer> _entitiesInScene;
diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp
index ae56a8fc47..79ee861c95 100644
--- a/libraries/entities-renderer/src/RenderableEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp
@@ -201,13 +201,6 @@ void EntityRenderer::render(RenderArgs* args) {
         return;
     }
 
-    if (!_renderUpdateQueued && needsRenderUpdate()) {
-        // FIXME find a way to spread out the calls to needsRenderUpdate so that only a given subset of the 
-        // items checks every frame, like 1/N of the tree ever N frames
-        _renderUpdateQueued = true;
-        emit requestRenderUpdate();
-    }
-
     if (_visible && (args->_renderMode != RenderArgs::RenderMode::DEFAULT_RENDER_MODE || !_cauterized)) {
         doRender(args);
     }
@@ -326,11 +319,6 @@ void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& trans
     }
     _updateTime = usecTimestampNow();
 
-    // FIXME is this excessive?
-    if (!needsRenderUpdate()) {
-        return;
-    }
-
     doRenderUpdateSynchronous(scene, transaction, _entity);
     transaction.updateItem<PayloadProxyInterface>(_renderItemID, [this](PayloadProxyInterface& self) {
         if (!isValidRenderItem()) {
@@ -338,7 +326,6 @@ void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& trans
         }
         // Happens on the render thread.  Classes should use
         doRenderUpdateAsynchronous(_entity);
-        _renderUpdateQueued = false;
     });
 }
 
@@ -431,7 +418,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
 }
 
 void EntityRenderer::onAddToScene(const EntityItemPointer& entity) {
-    QObject::connect(this, &EntityRenderer::requestRenderUpdate, this, [this] { 
+    QObject::connect(this, &EntityRenderer::requestRenderUpdate, this, [this] {
         auto renderer = DependencyManager::get<EntityTreeRenderer>();
         if (renderer) {
             renderer->onEntityChanged(_entity->getID());
@@ -440,7 +427,10 @@ void EntityRenderer::onAddToScene(const EntityItemPointer& entity) {
     _changeHandlerId = entity->registerChangeHandler([](const EntityItemID& changedEntity) {
         auto renderer = DependencyManager::get<EntityTreeRenderer>();
         if (renderer) {
-            renderer->onEntityChanged(changedEntity);
+            auto renderable = renderer->renderableForEntityId(changedEntity);
+            if (renderable && renderable->needsRenderUpdate()) {
+                renderer->onEntityChanged(changedEntity);
+            }
         }
     });
 }
diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h
index 227eb6a018..d52ccf4a99 100644
--- a/libraries/entities-renderer/src/RenderableEntityItem.h
+++ b/libraries/entities-renderer/src/RenderableEntityItem.h
@@ -145,8 +145,6 @@ protected:
     PrimitiveMode _primitiveMode { PrimitiveMode::SOLID };
     bool _cauterized { false };
     bool _moving { false };
-    // Only touched on the rendering thread
-    bool _renderUpdateQueued{ false };
     Transform _renderTransform;
 
     std::unordered_map<std::string, graphics::MultiMaterial> _materials;
@@ -187,10 +185,7 @@ protected:
     using Parent::needsRenderUpdateFromEntity;
     // Returns true if the item in question needs to have updateInScene called because of changes in the entity
     virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const override final {
-        if (Parent::needsRenderUpdateFromEntity(entity)) {
-            return true;
-        }
-        return needsRenderUpdateFromTypedEntity(_typedEntity);
+        return Parent::needsRenderUpdateFromEntity(entity) || needsRenderUpdateFromTypedEntity(_typedEntity);
     }
 
     virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) override final {
diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp
index 9081d0727f..7a36ae2707 100644
--- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp
@@ -39,6 +39,16 @@ bool GizmoEntityRenderer::isTransparent() const {
     return Parent::isTransparent() || ringTransparent;
 }
 
+void GizmoEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
+    void* key = (void*)this;
+    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
+        withWriteLock([&] {
+            _renderTransform = getModelTransform();
+            _renderTransform.postScale(entity->getScaledDimensions());
+        });
+    });
+}
+
 void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
     bool dirty = false;
     RingGizmoPropertyGroup ringProperties = entity->getRingProperties();
@@ -186,15 +196,6 @@ void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
             }
         }
     }
-
-    void* key = (void*)this;
-    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
-        withWriteLock([&] {
-            updateModelTransformAndBound();
-            _renderTransform = getModelTransform();
-            _renderTransform.postScale(entity->getScaledDimensions());
-        });
-    });
 }
 
 Item::Bound GizmoEntityRenderer::getBound() {
diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h
index c072f482cd..e3d84a0201 100644
--- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h
+++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h
@@ -29,6 +29,7 @@ protected:
     bool isTransparent() const override;
 
 private:
+    virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity);
     virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
     virtual void doRender(RenderArgs* args) override;
 
diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp
index 0b074f7a81..52900d0798 100644
--- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp
@@ -41,10 +41,9 @@ void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
     });
 
     void* key = (void*)this;
-    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
+    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
         withWriteLock([&] {
             _dimensions = entity->getScaledDimensions();
-            updateModelTransformAndBound();
             _renderTransform = getModelTransform();
         });
     });
diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp
index acdf5a35de..4d19a83ae6 100644
--- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp
@@ -30,11 +30,9 @@ bool ImageEntityRenderer::isTransparent() const {
 }
 
 bool ImageEntityRenderer::needsRenderUpdate() const {
-    bool textureLoadedChanged = resultWithReadLock<bool>([&] {
-        return (!_textureIsLoaded && _texture && _texture->isLoaded());
-    });
-
-    if (textureLoadedChanged) {
+    if (resultWithReadLock<bool>([&] {
+        return !_textureIsLoaded;
+    })) {
         return true;
     }
 
@@ -63,15 +61,15 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
         _pulseProperties = entity->getPulseProperties();
         _billboardMode = entity->getBillboardMode();
 
-        if (!_textureIsLoaded && _texture && _texture->isLoaded()) {
-            _textureIsLoaded = true;
+        if (!_textureIsLoaded) {
+            emit requestRenderUpdate();
         }
+        _textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed());
     });
 
     void* key = (void*)this;
-    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
+    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
         withWriteLock([&] {
-            updateModelTransformAndBound();
             _renderTransform = getModelTransform();
             _renderTransform.postScale(entity->getScaledDimensions());
         });
diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
index f34eb85230..5ffb395302 100644
--- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp
@@ -64,6 +64,16 @@ ParticleEffectEntityRenderer::ParticleEffectEntityRenderer(const EntityItemPoint
     });
 }
 
+bool ParticleEffectEntityRenderer::needsRenderUpdate() const {
+    if (resultWithReadLock<bool>([&] {
+        return !_textureLoaded;
+    })) {
+        return true;
+    }
+
+    return Parent::needsRenderUpdate();
+}
+
 void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
     auto newParticleProperties = entity->getParticleProperties();
     if (!newParticleProperties.valid()) {
@@ -102,6 +112,7 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
         }
 
         withWriteLock([&] {
+            _textureLoaded = true;
             entity->setVisuallyReady(true);
         });
     } else {
@@ -111,20 +122,29 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
         if (textureNeedsUpdate) {
             withWriteLock([&] {
                 _networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
+                _textureLoaded = false;
+                entity->setVisuallyReady(false);
             });
         }
 
-        if (_networkTexture) {
+        if (!_textureLoaded) {
+            emit requestRenderUpdate();
+        }
+
+        bool textureLoaded = resultWithReadLock<bool>([&] {
+            return _networkTexture && (_networkTexture->isLoaded() || _networkTexture->isFailed());
+        });
+        if (textureLoaded) {
             withWriteLock([&] {
-                entity->setVisuallyReady(_networkTexture->isFailed() || _networkTexture->isLoaded());
+                entity->setVisuallyReady(true);
+                _textureLoaded = true;
             });
         }
     }
 
     void* key = (void*)this;
-    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
+    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] {
         withWriteLock([&] {
-            updateModelTransformAndBound();
             _renderTransform = getModelTransform();
         });
     });
diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h
index cc907f2b1d..a89ab804fc 100644
--- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h
+++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h
@@ -25,6 +25,7 @@ public:
     ParticleEffectEntityRenderer(const EntityItemPointer& entity);
 
 protected:
+    virtual bool needsRenderUpdate() const override;
     virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
     virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
 
@@ -111,6 +112,7 @@ private:
     GeometryResource::Pointer _geometryResource;
 
     NetworkTexturePointer _networkTexture;
+    bool _textureLoaded { false };
     ScenePointer _scene;
 };
 
diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
index e75f8593d6..a843083831 100644
--- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
@@ -204,9 +204,8 @@ void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
     bool geometryChanged = uvModeStretchChanged || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged || faceCameraChanged;
 
     void* key = (void*)this;
-    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, geometryChanged] () {
+    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, geometryChanged] {
         withWriteLock([&] {
-            updateModelTransformAndBound();
             _renderTransform = getModelTransform();
 
             if (geometryChanged) {
diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
index d5a0e22199..222b833be2 100644
--- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
@@ -70,20 +70,18 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
     });
 
     void* key = (void*)this;
-    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
+    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
         withWriteLock([&] {
-            auto entity = getEntity();
             _position = entity->getWorldPosition();
             _dimensions = entity->getUnscaledDimensions(); // get unscaled to avoid scaling twice
             _orientation = entity->getWorldOrientation();
-            updateModelTransformAndBound();
             _renderTransform = getModelTransform(); // contains parent scale, if this entity scales with its parent
             if (_shape == entity::Sphere) {
                 _renderTransform.postScale(SPHERE_ENTITY_SCALE);
             }
 
             _renderTransform.postScale(_dimensions);
-        });;
+        });
     });
 }
 
@@ -125,6 +123,7 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
             auto materials = _materials.find("0");
             if (materials != _materials.end()) {
                 materials->second.setNeedsUpdate(true);
+                emit requestRenderUpdate();
             }
         }
     });
diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
index fbd10e2f5b..a5baad4841 100644
--- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp
@@ -102,10 +102,9 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
 
 void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
     void* key = (void*)this;
-    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
+    AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
         withWriteLock([&] {
             _dimensions = entity->getScaledDimensions();
-            updateModelTransformAndBound();
             _renderTransform = getModelTransform();
             _renderTransform.postScale(_dimensions);
         });
diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index 1da4999bad..c818eaf237 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -236,11 +236,10 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
             }
 
             void* key = (void*)this;
-            AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
+            AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
                 withWriteLock([&] {
                     glm::vec2 windowSize = getWindowSize(entity);
                     _webSurface->resize(QSize(windowSize.x, windowSize.y));
-                    updateModelTransformAndBound();
                     _renderTransform = getModelTransform();
                     _renderTransform.setScale(1.0f);
                     _renderTransform.postScale(entity->getScaledDimensions());
diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
index bbb8c67ad1..d6c675e88c 100644
--- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
@@ -255,14 +255,6 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
     entity->setVisuallyReady(visuallyReady);
 }
 
-void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
-    if (entity->getShapeType() == SHAPE_TYPE_SPHERE) {
-        _renderTransform = getModelTransform();
-        _renderTransform.postScale(SPHERE_ENTITY_SCALE);
-    }
-}
-
-
 ItemKey ZoneEntityRenderer::getKey() {
     return ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).build();
 }
@@ -299,8 +291,6 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
         return true;
     }
 
-    // FIXME: do we need to trigger an update when shapeType changes?  see doRenderUpdateAsynchronousTyped
-
     return false;
 }
 
diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h
index 5fd9b87408..d4e3d16408 100644
--- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h
+++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h
@@ -39,7 +39,6 @@ protected:
     virtual void doRender(RenderArgs* args) override;
     virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
     virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
-    virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
 
 private:
     void updateKeyZoneItemFromEntity(const TypedEntityPointer& entity);
diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index 856468f2ec..a48b7377df 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -615,10 +615,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
         _lastEdited = lastEditedFromBufferAdjusted;
         _lastEditedFromRemote = now;
         _lastEditedFromRemoteInRemoteTime = lastEditedFromBuffer;
-
-        // TODO: only send this notification if something ACTUALLY changed (hint, we haven't yet parsed
-        // the properties out of the bitstream (see below))
-        somethingChangedNotification(); // notify derived classes that something has changed
     }
 
     // last updated is stored as ByteCountCoded delta from lastEdited
@@ -1569,7 +1565,6 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         #endif
         setLastEdited(now);
-        somethingChangedNotification(); // notify derived classes that something has changed
         if (getDirtyFlags() & (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES)) {
             // anything that sets the transform or velocity must update _lastSimulated which is used
             // for kinematic extrapolation (e.g. we want to extrapolate forward from this moment
@@ -1827,6 +1822,7 @@ void EntityItem::setPosition(const glm::vec3& value) {
 void EntityItem::setParentID(const QUuid& value) {
     QUuid oldParentID = getParentID();
     if (oldParentID != value) {
+        _needsRenderUpdate = true;
         EntityTreePointer tree = getTree();
         if (tree && !oldParentID.isNull()) {
             tree->removeFromChildrenOfAvatars(getThisPointer());
@@ -2993,10 +2989,15 @@ bool EntityItem::getCauterized() const {
 }
 
 void EntityItem::setCauterized(bool value) {
+    bool needsRenderUpdate = false;
     withWriteLock([&] {
-        _needsRenderUpdate |= _cauterized != value;
+        needsRenderUpdate = _cauterized != value;
+        _needsRenderUpdate |= needsRenderUpdate;
         _cauterized = value;
     });
+    if (needsRenderUpdate) {
+        somethingChangedNotification();
+    }
 }
 
 bool EntityItem::getIgnorePickIntersection() const {
@@ -3031,10 +3032,15 @@ bool EntityItem::getCullWithParent() const {
 }
 
 void EntityItem::setCullWithParent(bool value) {
+    bool needsRenderUpdate = false;
     withWriteLock([&] {
-        _needsRenderUpdate |= _cullWithParent != value;
+        needsRenderUpdate = _cullWithParent != value;
+        _needsRenderUpdate |= needsRenderUpdate;
         _cullWithParent = value;
     });
+    if (needsRenderUpdate) {
+        somethingChangedNotification();
+    }
 }
 
 bool EntityItem::isChildOfMyAvatar() const {
diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h
index 14b8b259cc..5b0f1ad44c 100644
--- a/libraries/entities/src/EntityItem.h
+++ b/libraries/entities/src/EntityItem.h
@@ -574,8 +574,8 @@ public:
 
     bool stillHasMyGrab() const;
 
-    bool needsRenderUpdate() const { return resultWithReadLock<bool>([&] { return _needsRenderUpdate; }); }
-    void setNeedsRenderUpdate(bool needsRenderUpdate) { withWriteLock([&] { _needsRenderUpdate = needsRenderUpdate; }); }
+    bool needsRenderUpdate() const { return _needsRenderUpdate; }
+    void setNeedsRenderUpdate(bool needsRenderUpdate) { _needsRenderUpdate = needsRenderUpdate; }
 
 signals:
     void spaceUpdate(std::pair<int32_t, glm::vec4> data);
diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp
index a2fc691387..9d79e06534 100644
--- a/libraries/entities/src/GizmoEntityItem.cpp
+++ b/libraries/entities/src/GizmoEntityItem.cpp
@@ -58,6 +58,7 @@ bool GizmoEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties.getLastEdited());
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp
index e45ab89b69..a1147b21df 100644
--- a/libraries/entities/src/GridEntityItem.cpp
+++ b/libraries/entities/src/GridEntityItem.cpp
@@ -70,6 +70,7 @@ bool GridEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties.getLastEdited());
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp
index 2d942cc25d..c538ce619d 100644
--- a/libraries/entities/src/ImageEntityItem.cpp
+++ b/libraries/entities/src/ImageEntityItem.cpp
@@ -71,6 +71,7 @@ bool ImageEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties.getLastEdited());
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp
index 2df2136639..11864f59da 100644
--- a/libraries/entities/src/LightEntityItem.cpp
+++ b/libraries/entities/src/LightEntityItem.cpp
@@ -55,21 +55,6 @@ void LightEntityItem::setUnscaledDimensions(const glm::vec3& value) {
     }
 }
 
-void LightEntityItem::locationChanged(bool tellPhysics, bool tellChildren) {
-    EntityItem::locationChanged(tellPhysics, tellChildren);
-    withWriteLock([&] {
-        _needsRenderUpdate = true;
-    });
-}
-
-void LightEntityItem::dimensionsChanged() {
-    EntityItem::dimensionsChanged();
-    withWriteLock([&] {
-        _needsRenderUpdate = true;
-    });
-}
-
-
 EntityItemProperties LightEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
     EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
 
@@ -145,6 +130,7 @@ bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
                 "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties.getLastEdited());
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h
index 8194ff8308..533d2994d6 100644
--- a/libraries/entities/src/LightEntityItem.h
+++ b/libraries/entities/src/LightEntityItem.h
@@ -73,9 +73,6 @@ public:
     
     static bool getLightsArePickable() { return _lightsArePickable; }
     static void setLightsArePickable(bool value) { _lightsArePickable = value; }
-    
-    virtual void locationChanged(bool tellPhysics, bool tellChildren) override;
-    virtual void dimensionsChanged() override;
 
     virtual bool supportsDetailedIntersection() const override { return true; }
     virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp
index 1cd09c1a0c..45cdf980a1 100644
--- a/libraries/entities/src/LineEntityItem.cpp
+++ b/libraries/entities/src/LineEntityItem.cpp
@@ -61,6 +61,7 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) {
                 "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties._lastEdited);
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp
index 73bebfc403..11745c29ce 100644
--- a/libraries/entities/src/MaterialEntityItem.cpp
+++ b/libraries/entities/src/MaterialEntityItem.cpp
@@ -60,6 +60,7 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties.getLastEdited());
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp
index 0b6e62e89e..aa0c7304a7 100644
--- a/libraries/entities/src/ModelEntityItem.cpp
+++ b/libraries/entities/src/ModelEntityItem.cpp
@@ -111,6 +111,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties._lastEdited);
+        somethingChangedNotification();
     }
 
     return somethingChanged;
diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp
index c20ae87276..082c4efb17 100644
--- a/libraries/entities/src/ParticleEffectEntityItem.cpp
+++ b/libraries/entities/src/ParticleEffectEntityItem.cpp
@@ -759,6 +759,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
                 "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties.getLastEdited());
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp
index fe14ba6925..fcd4b6d89d 100644
--- a/libraries/entities/src/PolyLineEntityItem.cpp
+++ b/libraries/entities/src/PolyLineEntityItem.cpp
@@ -77,6 +77,7 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
                 "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties._lastEdited);
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp
index b424ba137f..c31d0b81b3 100644
--- a/libraries/entities/src/PolyVoxEntityItem.cpp
+++ b/libraries/entities/src/PolyVoxEntityItem.cpp
@@ -130,6 +130,7 @@ bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) {
                 "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties._lastEdited);
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp
index 882ab26901..5b9c3e6881 100644
--- a/libraries/entities/src/ShapeEntityItem.cpp
+++ b/libraries/entities/src/ShapeEntityItem.cpp
@@ -186,6 +186,7 @@ bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties.getLastEdited());
+        somethingChangedNotification();
     }
     return somethingChanged;
 }
diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp
index bcc2c0efed..9c53196247 100644
--- a/libraries/entities/src/TextEntityItem.cpp
+++ b/libraries/entities/src/TextEntityItem.cpp
@@ -109,6 +109,7 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties._lastEdited);
+        somethingChangedNotification();
     }
     
     return somethingChanged;
diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp
index a62f599e4c..d8b2c8fc3d 100644
--- a/libraries/entities/src/WebEntityItem.cpp
+++ b/libraries/entities/src/WebEntityItem.cpp
@@ -92,6 +92,7 @@ bool WebEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties._lastEdited);
+        somethingChangedNotification();
     }
 
     return somethingChanged;
diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp
index 0771d9ad54..dc18c05ef3 100644
--- a/libraries/entities/src/ZoneEntityItem.cpp
+++ b/libraries/entities/src/ZoneEntityItem.cpp
@@ -88,6 +88,7 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         }
         setLastEdited(properties._lastEdited);
+        somethingChangedNotification();
     }
 
     return somethingChanged;
diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index d8172112ff..d3f2a04d24 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -282,11 +282,6 @@ void Model::setRenderItemsNeedUpdate() {
     emit requestRenderUpdate();
 }
 
-void Model::setPrimitiveMode(PrimitiveMode primitiveMode) {
-    _primitiveMode = primitiveMode;
-    setRenderItemsNeedUpdate();
-}
-
 void Model::reset() {
     if (isLoaded()) {
         const HFMModel& hfmModel = getHFMModel();
@@ -888,6 +883,13 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) {
     scene->enqueueTransaction(transaction);
 }
 
+void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene) {
+    if (_primitiveMode != primitiveMode) {
+        _primitiveMode = primitiveMode;
+        updateRenderItemsKey(scene);
+    }
+}
+
 void Model::setVisibleInScene(bool visible, const render::ScenePointer& scene) {
     if (Model::isVisible() != visible) {
         auto keyBuilder = render::ItemKey::Builder(_renderItemKeyGlobalFlags);
diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h
index b677861e9f..85aaa33bcb 100644
--- a/libraries/render-utils/src/Model.h
+++ b/libraries/render-utils/src/Model.h
@@ -129,6 +129,9 @@ public:
     bool isCauterized() const { return _cauterized; }
     void setCauterized(bool value, const render::ScenePointer& scene);
 
+    void setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene = nullptr);
+    PrimitiveMode getPrimitiveMode() const { return _primitiveMode; }
+
     void setCullWithParent(bool value);
 
     // Access the current RenderItemKey Global Flags used by the model and applied to the render items  representing the parts of the model.
@@ -168,9 +171,6 @@ public:
     bool isLoaded() const { return (bool)_renderGeometry && _renderGeometry->isHFMModelLoaded(); }
     bool isAddedToScene() const { return _addedToScene; }
 
-    void setPrimitiveMode(PrimitiveMode primitiveMode);
-    PrimitiveMode getPrimitiveMode() const { return _primitiveMode; }
-
     void reset();
 
     void setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint);

From a7861855a7428455cca39b5e783bad0b9ee41cea Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Thu, 16 Jul 2020 14:34:02 -0700
Subject: [PATCH 2/6] properties update over wire

---
 libraries/entities/src/EntityItem.cpp         |  4 ++++
 libraries/entities/src/GizmoEntityItem.cpp    | 15 ++----------
 libraries/entities/src/GizmoEntityItem.h      |  2 +-
 libraries/entities/src/GridEntityItem.cpp     | 15 ++----------
 libraries/entities/src/GridEntityItem.h       |  2 +-
 libraries/entities/src/ImageEntityItem.cpp    | 15 ++----------
 libraries/entities/src/ImageEntityItem.h      |  2 +-
 libraries/entities/src/LightEntityItem.cpp    | 19 +--------------
 libraries/entities/src/LightEntityItem.h      |  4 +---
 libraries/entities/src/LineEntityItem.cpp     | 14 +----------
 libraries/entities/src/LineEntityItem.h       |  2 +-
 libraries/entities/src/MaterialEntityItem.cpp | 15 ++----------
 libraries/entities/src/MaterialEntityItem.h   |  2 +-
 libraries/entities/src/ModelEntityItem.cpp    | 15 +-----------
 libraries/entities/src/ModelEntityItem.h      |  2 +-
 .../entities/src/ParticleEffectEntityItem.cpp | 15 ++----------
 .../entities/src/ParticleEffectEntityItem.h   |  2 +-
 libraries/entities/src/PolyLineEntityItem.cpp | 14 +----------
 libraries/entities/src/PolyLineEntityItem.h   |  2 +-
 libraries/entities/src/PolyVoxEntityItem.cpp  | 16 +++----------
 libraries/entities/src/PolyVoxEntityItem.h    |  2 +-
 libraries/entities/src/ShapeEntityItem.cpp    | 15 ++----------
 libraries/entities/src/ShapeEntityItem.h      |  2 +-
 libraries/entities/src/TextEntityItem.cpp     | 15 +-----------
 libraries/entities/src/TextEntityItem.h       |  2 +-
 libraries/entities/src/WebEntityItem.cpp      | 15 +-----------
 libraries/entities/src/WebEntityItem.h        |  2 +-
 libraries/entities/src/ZoneEntityItem.cpp     | 23 ++-----------------
 libraries/entities/src/ZoneEntityItem.h       |  1 -
 29 files changed, 40 insertions(+), 214 deletions(-)

diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index 69f1ed2aee..faf29ec20b 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -1001,6 +1001,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
         element->getTree()->trackIncomingEntityLastEdited(lastEditedFromBufferAdjusted, bytesRead);
     }
 
+    if (somethingChanged) {
+        somethingChangedNotification();
+    }
 
     return bytesRead;
 }
@@ -1576,6 +1579,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
             // when position and/or velocity was changed).
             _lastSimulated = now;
         }
+        somethingChangedNotification();
     }
 
     // timestamps
diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp
index 9d79e06534..47c9afd168 100644
--- a/libraries/entities/src/GizmoEntityItem.cpp
+++ b/libraries/entities/src/GizmoEntityItem.cpp
@@ -39,8 +39,8 @@ EntityItemProperties GizmoEntityItem::getProperties(const EntityPropertyFlags& d
     return properties;
 }
 
-bool GizmoEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
+bool GizmoEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(gizmoType, setGizmoType);
     withWriteLock([&] {
@@ -49,17 +49,6 @@ bool GizmoEntityItem::setProperties(const EntityItemProperties& properties) {
         _needsRenderUpdate |= ringPropertiesChanged;
     });
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "GizmoEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties.getLastEdited());
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/GizmoEntityItem.h b/libraries/entities/src/GizmoEntityItem.h
index aa338355b8..37a802387d 100644
--- a/libraries/entities/src/GizmoEntityItem.h
+++ b/libraries/entities/src/GizmoEntityItem.h
@@ -26,7 +26,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    bool setProperties(const EntityItemProperties& properties) override;
+    bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp
index a1147b21df..e635511bfc 100644
--- a/libraries/entities/src/GridEntityItem.cpp
+++ b/libraries/entities/src/GridEntityItem.cpp
@@ -46,8 +46,8 @@ EntityItemProperties GridEntityItem::getProperties(const EntityPropertyFlags& de
     return properties;
 }
 
-bool GridEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
+bool GridEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
@@ -61,17 +61,6 @@ bool GridEntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(majorGridEvery, setMajorGridEvery);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(minorGridEvery, setMinorGridEvery);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "GridEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties.getLastEdited());
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/GridEntityItem.h b/libraries/entities/src/GridEntityItem.h
index 165d9b50f5..7dc7a475b2 100644
--- a/libraries/entities/src/GridEntityItem.h
+++ b/libraries/entities/src/GridEntityItem.h
@@ -26,7 +26,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    bool setProperties(const EntityItemProperties& properties) override;
+    bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp
index c538ce619d..6a8c457b0a 100644
--- a/libraries/entities/src/ImageEntityItem.cpp
+++ b/libraries/entities/src/ImageEntityItem.cpp
@@ -45,8 +45,8 @@ EntityItemProperties ImageEntityItem::getProperties(const EntityPropertyFlags& d
     return properties;
 }
 
-bool ImageEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
+bool ImageEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
@@ -62,17 +62,6 @@ bool ImageEntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(keepAspectRatio, setKeepAspectRatio);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(subImage, setSubImage);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "ImageEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties.getLastEdited());
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h
index a1be5a0554..bca67dc738 100644
--- a/libraries/entities/src/ImageEntityItem.h
+++ b/libraries/entities/src/ImageEntityItem.h
@@ -26,7 +26,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    bool setProperties(const EntityItemProperties& properties) override;
+    bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp
index 11864f59da..715b457bde 100644
--- a/libraries/entities/src/LightEntityItem.cpp
+++ b/libraries/entities/src/LightEntityItem.cpp
@@ -119,24 +119,8 @@ void LightEntityItem::setCutoff(float value) {
     }
 }
 
-bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "LightEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties.getLastEdited());
-        somethingChangedNotification();
-    }
-    return somethingChanged;
-}
-
 bool LightEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setSubClassProperties(properties); // set the properties in our base class
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight);
@@ -148,7 +132,6 @@ bool LightEntityItem::setSubClassProperties(const EntityItemProperties& properti
     return somethingChanged;
 }
 
-
 int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, 
                                                 ReadBitstreamToTreeParams& args,
                                                 EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h
index 533d2994d6..5245770ec8 100644
--- a/libraries/entities/src/LightEntityItem.h
+++ b/libraries/entities/src/LightEntityItem.h
@@ -33,11 +33,9 @@ public:
     /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
     virtual void setUnscaledDimensions(const glm::vec3& value) override;
 
-    virtual bool setProperties(const EntityItemProperties& properties) override;
-    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
-
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp
index 45cdf980a1..f3304e716f 100644
--- a/libraries/entities/src/LineEntityItem.cpp
+++ b/libraries/entities/src/LineEntityItem.cpp
@@ -45,24 +45,12 @@ EntityItemProperties LineEntityItem::getProperties(const EntityPropertyFlags& de
     return properties;
 }
 
-bool LineEntityItem::setProperties(const EntityItemProperties& properties) {
+bool LineEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
     bool somethingChanged = false;
-    somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "LineEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties._lastEdited);
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h
index ee473225fe..38e526204e 100644
--- a/libraries/entities/src/LineEntityItem.h
+++ b/libraries/entities/src/LineEntityItem.h
@@ -24,7 +24,7 @@ class LineEntityItem : public EntityItem {
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp
index 11745c29ce..dcdd80cb48 100644
--- a/libraries/entities/src/MaterialEntityItem.cpp
+++ b/libraries/entities/src/MaterialEntityItem.cpp
@@ -38,8 +38,8 @@ EntityItemProperties MaterialEntityItem::getProperties(const EntityPropertyFlags
     return properties;
 }
 
-bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
+bool MaterialEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialURL, setMaterialURL);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingMode, setMaterialMappingMode);
@@ -51,17 +51,6 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialData, setMaterialData);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialRepeat, setMaterialRepeat);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "MaterialEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties.getLastEdited());
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h
index d8de8c3bc6..76cfbfa9dc 100644
--- a/libraries/entities/src/MaterialEntityItem.h
+++ b/libraries/entities/src/MaterialEntityItem.h
@@ -24,7 +24,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp
index 6818c5cb6a..38e7ad9c3a 100644
--- a/libraries/entities/src/ModelEntityItem.cpp
+++ b/libraries/entities/src/ModelEntityItem.cpp
@@ -79,9 +79,8 @@ EntityItemProperties ModelEntityItem::getProperties(const EntityPropertyFlags& d
     return properties;
 }
 
-bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
+bool ModelEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
     bool somethingChanged = false;
-    somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
@@ -105,18 +104,6 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
         somethingChanged = somethingChanged || somethingChangedInAnimations;
     });
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "ModelEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties._lastEdited);
-        somethingChangedNotification();
-    }
-
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h
index c331a94adf..795630a72a 100644
--- a/libraries/entities/src/ModelEntityItem.h
+++ b/libraries/entities/src/ModelEntityItem.h
@@ -29,7 +29,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp
index 082c4efb17..5ccc209a54 100644
--- a/libraries/entities/src/ParticleEffectEntityItem.cpp
+++ b/libraries/entities/src/ParticleEffectEntityItem.cpp
@@ -696,8 +696,8 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(const EntityPropert
     return properties;
 }
 
-bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
+bool ParticleEffectEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
@@ -750,17 +750,6 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinFinish, setSpinFinish);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotateWithEntity, setRotateWithEntity);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "ParticleEffectEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties.getLastEdited());
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h
index 358e5a6b6d..c96323fc9a 100644
--- a/libraries/entities/src/ParticleEffectEntityItem.h
+++ b/libraries/entities/src/ParticleEffectEntityItem.h
@@ -214,7 +214,7 @@ public:
 
     // methods for getting/setting all properties of this entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp
index fcd4b6d89d..909bc132fb 100644
--- a/libraries/entities/src/PolyLineEntityItem.cpp
+++ b/libraries/entities/src/PolyLineEntityItem.cpp
@@ -53,9 +53,8 @@ EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags
     return properties;
 }
 
-bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
+bool PolyLineEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
     bool somethingChanged = false;
-    somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
@@ -68,17 +67,6 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(glow, setGlow);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(faceCamera, setFaceCamera);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "PolyLineEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties._lastEdited);
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h
index e68666d75e..8fb7831c6a 100644
--- a/libraries/entities/src/PolyLineEntityItem.h
+++ b/libraries/entities/src/PolyLineEntityItem.h
@@ -24,7 +24,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp
index c31d0b81b3..dd55ca898b 100644
--- a/libraries/entities/src/PolyVoxEntityItem.cpp
+++ b/libraries/entities/src/PolyVoxEntityItem.cpp
@@ -106,8 +106,9 @@ EntityItemProperties PolyVoxEntityItem::getProperties(const EntityPropertyFlags&
     return properties;
 }
 
-bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
+bool PolyVoxEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
+    bool somethingChanged = false;
+
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(voxelVolumeSize, setVoxelVolumeSize);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(voxelData, setVoxelData);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(voxelSurfaceStyle, setVoxelSurfaceStyle);
@@ -121,17 +122,6 @@ bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(yPNeighborID, setYPNeighborID);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(zPNeighborID, setZPNeighborID);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "PolyVoxEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties._lastEdited);
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h
index 9d02cbcdad..f994fcd37c 100644
--- a/libraries/entities/src/PolyVoxEntityItem.h
+++ b/libraries/entities/src/PolyVoxEntityItem.h
@@ -24,7 +24,7 @@ class PolyVoxEntityItem : public EntityItem {
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp
index 5b9c3e6881..5e140665b3 100644
--- a/libraries/entities/src/ShapeEntityItem.cpp
+++ b/libraries/entities/src/ShapeEntityItem.cpp
@@ -165,8 +165,8 @@ entity::Shape ShapeEntityItem::getShape() const {
     });
 }
 
-bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
+bool ShapeEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
@@ -177,17 +177,6 @@ bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) {
     });
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "ShapeEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties.getLastEdited());
-        somethingChangedNotification();
-    }
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h
index 43c2ce2a1f..7320867430 100644
--- a/libraries/entities/src/ShapeEntityItem.h
+++ b/libraries/entities/src/ShapeEntityItem.h
@@ -55,7 +55,7 @@ public:
     
     // methods for getting/setting all properties of an entity
     EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    bool setProperties(const EntityItemProperties& properties) override;
+    bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp
index 9c53196247..a996319463 100644
--- a/libraries/entities/src/TextEntityItem.cpp
+++ b/libraries/entities/src/TextEntityItem.cpp
@@ -73,9 +73,8 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de
     return properties;
 }
 
-bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
+bool TextEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
     bool somethingChanged = false;
-    somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
 
     withWriteLock([&] {
         bool pulsePropertiesChanged = _pulseProperties.setProperties(properties);
@@ -99,18 +98,6 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffect, setTextEffect);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffectColor, setTextEffectColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffectThickness, setTextEffectThickness);
-
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "TextEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties._lastEdited);
-        somethingChangedNotification();
-    }
     
     return somethingChanged;
 }
diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h
index 5e3f6d7c02..91496708f6 100644
--- a/libraries/entities/src/TextEntityItem.h
+++ b/libraries/entities/src/TextEntityItem.h
@@ -31,7 +31,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp
index d8b2c8fc3d..73e0096e76 100644
--- a/libraries/entities/src/WebEntityItem.cpp
+++ b/libraries/entities/src/WebEntityItem.cpp
@@ -63,9 +63,8 @@ EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& des
     return properties;
 }
 
-bool WebEntityItem::setProperties(const EntityItemProperties& properties) {
+bool WebEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
     bool somethingChanged = false;
-    somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
@@ -83,18 +82,6 @@ bool WebEntityItem::setProperties(const EntityItemProperties& properties) {
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(inputMode, setInputMode);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(showKeyboardFocusHighlight, setShowKeyboardFocusHighlight);
 
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "WebEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties._lastEdited);
-        somethingChangedNotification();
-    }
-
     return somethingChanged;
 }
 
diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h
index b61e2b124f..5ab53d6ef8 100644
--- a/libraries/entities/src/WebEntityItem.h
+++ b/libraries/entities/src/WebEntityItem.h
@@ -27,7 +27,7 @@ public:
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
+    virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
 
diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp
index 842651fcac..88466caff0 100644
--- a/libraries/entities/src/ZoneEntityItem.cpp
+++ b/libraries/entities/src/ZoneEntityItem.cpp
@@ -76,27 +76,8 @@ EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& de
     return properties;
 }
 
-bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = false;
-    somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
-
-    if (somethingChanged) {
-        bool wantDebug = false;
-        if (wantDebug) {
-            uint64_t now = usecTimestampNow();
-            int elapsed = now - getLastEdited();
-            qCDebug(entities) << "ZoneEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
-                    "now=" << now << " getLastEdited()=" << getLastEdited();
-        }
-        setLastEdited(properties._lastEdited);
-        somethingChangedNotification();
-    }
-
-    return somethingChanged;
-}
-
 bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
-    bool somethingChanged = EntityItem::setSubClassProperties(properties); // set the properties in our base class
+    bool somethingChanged = false;
 
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
@@ -122,7 +103,7 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(avatarPriority, setAvatarPriority);
     SET_ENTITY_PROPERTY_FROM_PROPERTIES(screenshare, setScreenshare);
 
-    somethingChanged = somethingChanged || _keyLightPropertiesChanged || _ambientLightPropertiesChanged ||
+    somethingChanged |= _keyLightPropertiesChanged || _ambientLightPropertiesChanged ||
         _skyboxPropertiesChanged || _hazePropertiesChanged || _bloomPropertiesChanged;
 
     return somethingChanged;
diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h
index 8ec3ea12b4..dda03f9115 100644
--- a/libraries/entities/src/ZoneEntityItem.h
+++ b/libraries/entities/src/ZoneEntityItem.h
@@ -33,7 +33,6 @@ public:
 
     // methods for getting/setting all properties of an entity
     virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
-    virtual bool setProperties(const EntityItemProperties& properties) override;
     virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
 
     virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

From 8274ee3ca90c457aa82b83ac7004b171e611d770 Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Mon, 20 Jul 2020 15:10:48 -0700
Subject: [PATCH 3/6] put back old last edited logic

---
 libraries/entities/src/EntityItem.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index faf29ec20b..ddedf0db18 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -1572,7 +1572,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
             qCDebug(entities) << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
                     "now=" << now << " getLastEdited()=" << getLastEdited();
         #endif
-        setLastEdited(now);
+        setLastEdited(properties._lastEdited);
         if (getDirtyFlags() & (Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES)) {
             // anything that sets the transform or velocity must update _lastSimulated which is used
             // for kinematic extrapolation (e.g. we want to extrapolate forward from this moment

From 87fd039f99632328d4029178e320a4c1eca646f6 Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Tue, 4 Aug 2020 08:54:44 -0700
Subject: [PATCH 4/6] fix merge issue

---
 libraries/render-utils/src/Model.cpp | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index 0956392944..92c9b4fafb 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -886,13 +886,6 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) {
     scene->enqueueTransaction(transaction);
 }
 
-void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene) {
-    if (_primitiveMode != primitiveMode) {
-        _primitiveMode = primitiveMode;
-        updateRenderItemsKey(scene);
-    }
-}
-
 void Model::setVisibleInScene(bool visible, const render::ScenePointer& scene) {
     if (Model::isVisible() != visible) {
         auto keyBuilder = render::ItemKey::Builder(_renderItemKeyGlobalFlags);
@@ -965,10 +958,10 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
     }
 }
 
-void Model::setPrimitiveMode(PrimitiveMode primitiveMode) {
+void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene) {
     if (_primitiveMode != primitiveMode) {
         _primitiveMode = primitiveMode;
-        setRenderItemsNeedUpdate();
+        updateRenderItemsKey(scene);
     }
 }
 

From e78ece7fc5e64ec225807924d39ebe070d72e3c6 Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Mon, 17 Aug 2020 14:16:41 -0700
Subject: [PATCH 5/6] CR

---
 libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +-
 libraries/render-utils/src/Model.cpp                   | 4 ++--
 libraries/render-utils/src/Model.h                     | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index 51178fea1b..b5ed4b767d 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -496,7 +496,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
             }
 
             // compute average per-renderable update cost
-           _prevNumEntityUpdates = sortedRenderables.size() - _renderablesToUpdate.size();
+            _prevNumEntityUpdates = sortedRenderables.size() - _renderablesToUpdate.size();
             size_t numUpdated = _prevNumEntityUpdates + 1; // add one to avoid divide by zero
             float cost = (float)(usecTimestampNow() - updateStart) / (float)(numUpdated);
             const float BLEND = 0.1f;
diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index 92c9b4fafb..182b83762c 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -958,10 +958,10 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
     }
 }
 
-void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene) {
+void Model::setPrimitiveMode(PrimitiveMode primitiveMode) {
     if (_primitiveMode != primitiveMode) {
         _primitiveMode = primitiveMode;
-        updateRenderItemsKey(scene);
+        updateRenderItemsKey(nullptr);
     }
 }
 
diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h
index 0f65b62194..4585ad0009 100644
--- a/libraries/render-utils/src/Model.h
+++ b/libraries/render-utils/src/Model.h
@@ -118,7 +118,7 @@ public:
     bool isCauterized() const { return _cauterized; }
     void setCauterized(bool value, const render::ScenePointer& scene);
 
-    void setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene = nullptr);
+    void setPrimitiveMode(PrimitiveMode primitiveMode);
     PrimitiveMode getPrimitiveMode() const { return _primitiveMode; }
 
     void setCullWithParent(bool value);

From af828607517c0f145aefee104e2b1ccf6676bdb1 Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Wed, 19 Aug 2020 19:51:16 -0700
Subject: [PATCH 6/6] fix shape issue that alezia found

---
 .../src/RenderableShapeEntityItem.cpp                  | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
index 222b833be2..683cc1359a 100644
--- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
@@ -119,10 +119,14 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
             materialChanged = true;
         }
 
-        if (materialChanged) {
-            auto materials = _materials.find("0");
-            if (materials != _materials.end()) {
+        auto materials = _materials.find("0");
+        if (materials != _materials.end()) {
+            if (materialChanged) {
                 materials->second.setNeedsUpdate(true);
+            }
+
+            if (materials->second.shouldUpdate()) {
+                RenderPipelines::updateMultiMaterial(materials->second);
                 emit requestRenderUpdate();
             }
         }