From a40a562db21152bd94a393b2226d5586b8606c04 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 11 Feb 2016 09:30:06 -0800 Subject: [PATCH] handle two conner cases where preload would get called twice --- .../src/EntityTreeRenderer.cpp | 3 ++- libraries/entities/src/EntityItem.h | 20 +++++++++++++++++++ libraries/entities/src/EntityTree.cpp | 3 +++ libraries/entities/src/EntityTreeElement.cpp | 8 +++++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 0ea35e6c5a..1967e14d6e 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -690,10 +690,11 @@ void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID, const void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) { if (_tree && !_shuttingDown) { EntityItemPointer entity = getTree()->findEntityByEntityItemID(entityID); - if (entity && !entity->getScript().isEmpty()) { + if (entity && entity->shouldPreloadScript()) { QString scriptUrl = entity->getScript(); scriptUrl = ResourceManager::normalizeURL(scriptUrl); _entitiesScriptEngine->loadEntityScript(entityID, scriptUrl, reload); + entity->scriptHasPreloaded(); } } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 55741823f1..da10886b97 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -404,6 +404,20 @@ public: virtual void loader() {} // called indirectly when urls for geometry are updated + /// Has the entity been added to an entity tree? This is useful in some state decisions + /// for example whether or not to send out a scriptChanging signal. + void markAsAddedToTree() { _isAddedToTree = true; } + bool isAddedToTree() const { return _isAddedToTree; } + + /// Should the external entity script mechanism call a preload for this entity. + /// Due to the asyncronous nature of signals for add entity and script changing + /// it's possible for two similar signals to cross paths. This method allows the + /// entity to definitively state if the preload signal should be sent. + bool shouldPreloadScript() const { return !_script.isEmpty() && + _loadedScript != _script && _loadedScriptTimestamp != _scriptTimestamp; } + + void scriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } + protected: void setSimulated(bool simulated) { _simulated = simulated; } @@ -506,6 +520,12 @@ protected: mutable QHash _previouslyDeletedActions; QUuid _sourceUUID; /// the server node UUID we came from + + bool _isAddedToTree { false }; /// this is false until the entity has been added to an entity tree + + QString _loadedScript; /// the value of _script when the last preload signal was sent + quint64 _loadedScriptTimestamp { 0 }; /// the value of _scriptTimestamp when the last preload signal was sent + }; #endif // hifi_EntityItem_h diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 4c3412edd3..fc463b6f21 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -92,6 +92,9 @@ void EntityTree::postAddEntity(EntityItemPointer entity) { // find and hook up any entities with this entity as a (previously) missing parent fixupMissingParents(); + + // indicate that the entity has been added to the tree + entity->markAsAddedToTree(); } bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) { diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 1e798f2e0c..d58faa81fe 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -921,7 +921,13 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int QString entityScriptAfter = entityItem->getScript(); quint64 entityScriptTimestampAfter = entityItem->getScriptTimestamp(); bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter; - if (entityScriptBefore != entityScriptAfter || reload) { + + // If the script value has changed on us, or it's timestamp has changed to force + // a reload then we want to send out a script changing signal... UNLESS this is the + // first time we've read the entity information, in which case, the entity has + // not yet been added to the tree, and we want to wait for the addEntity. In other + // words it's not a "change" in the script, if it's a first time load. + if (entityItem->isAddedToTree() && (entityScriptBefore != entityScriptAfter || reload)) { _myTree->emitEntityScriptChanging(entityItemID, reload); // the entity script has changed }