From d0cddd01d73f78d1ee60e7bcd950008012584be0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 13 Feb 2017 13:33:29 -0800 Subject: [PATCH] Fix entity scripts not loading in certain cases This fixes a bug where an entity script would be loaded but immediately unloaded. This happens when the script property of the entity is changed shortly after it is added. Flow of events: Entity added => Entity added event emitted Entity edited => Script changing event emitted <= Entity added event received Script loaded <= Script changing event received Script stopped Tries to load script again, but because the script hasn't changed since it was last loaded, it is not loaded again. The change here is to modify the behavior when receiving a script changing event. Instead of always unloading and then conditionally loading the script, it will either do both (unload + load) or neither. --- .../entities-renderer/src/EntityTreeRenderer.cpp | 16 +++++++++------- .../entities-renderer/src/EntityTreeRenderer.h | 2 +- libraries/entities/src/EntityItem.h | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 1265aabbf2..4f4f3bf67f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -938,17 +938,19 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { void EntityTreeRenderer::entityScriptChanging(const EntityItemID& entityID, const bool reload) { - if (_tree && !_shuttingDown) { - _entitiesScriptEngine->unloadEntityScript(entityID); - checkAndCallPreload(entityID, reload); - } + checkAndCallPreload(entityID, reload, true); } -void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, const bool reload) { +void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, const bool reload, const bool unloadFirst) { if (_tree && !_shuttingDown) { EntityItemPointer entity = getTree()->findEntityByEntityItemID(entityID); - if (entity && entity->shouldPreloadScript() && _entitiesScriptEngine) { - QString scriptUrl = entity->getScript(); + bool shouldLoad = entity && entity->shouldPreloadScript() && _entitiesScriptEngine; + QString scriptUrl = entity->getScript(); + if ((unloadFirst && shouldLoad) || scriptUrl.isEmpty()) { + _entitiesScriptEngine->unloadEntityScript(entityID); + entity->scriptHasUnloaded(); + } + if (shouldLoad && !scriptUrl.isEmpty()) { scriptUrl = ResourceManager::normalizeURL(scriptUrl); ScriptEngine::loadEntityScript(_entitiesScriptEngine, entityID, scriptUrl, reload); entity->scriptHasPreloaded(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 8669a1c4d3..c11738c459 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -148,7 +148,7 @@ private: bool layerZoneAndHasSkybox(const std::shared_ptr& zone); bool applySkyboxAndHasAmbient(); - void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false); + void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false, const bool unloadFirst = false); QList _releasedModels; RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e69195d53d..163b4d9e45 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -446,6 +446,7 @@ public: bool shouldPreloadScript() const { return !_script.isEmpty() && ((_loadedScript != _script) || (_loadedScriptTimestamp != _scriptTimestamp)); } void scriptHasPreloaded() { _loadedScript = _script; _loadedScriptTimestamp = _scriptTimestamp; } + void scriptHasUnloaded() { _loadedScript = ""; _loadedScriptTimestamp = 0; } bool getClientOnly() const { return _clientOnly; } void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; }