diff --git a/include/openspace/scene/asset.h b/include/openspace/scene/asset.h index 503e003afd..e5554bd36a 100644 --- a/include/openspace/scene/asset.h +++ b/include/openspace/scene/asset.h @@ -82,8 +82,7 @@ public: void addSynchronization(std::shared_ptr synchronization); std::vector> ownSynchronizations() const; - void syncStateChanged(std::shared_ptr sync, - ResourceSynchronization::State s); + void syncStateChanged(ResourceSynchronization::State s); bool hasLoadedParent() const; void load(); @@ -136,7 +135,7 @@ public: private: void setState(State state); - void requiredAssetChangedState(std::shared_ptr a, Asset::State state); + void requiredAssetChangedState(Asset::State state); void requestedAssetChangedState(std::shared_ptr a, Asset::State state); bool isSyncResolveReady(); diff --git a/modules/sync/tasks/syncassettask.h b/modules/sync/tasks/syncassettask.h index ca5b27dcb7..974ab296b5 100644 --- a/modules/sync/tasks/syncassettask.h +++ b/modules/sync/tasks/syncassettask.h @@ -41,18 +41,19 @@ class SyncAssetTask : public Task { public: class RequestListener : public AssetListener { public: - + virtual ~RequestListener() = default; void assetStateChanged(std::shared_ptr asset, Asset::State state) override; - void assetRequested(std::shared_ptr parent, - std::shared_ptr child) {}; + void assetRequested(std::shared_ptr, + std::shared_ptr) override {}; - void assetUnrequested(std::shared_ptr parent, - std::shared_ptr child) {}; + void assetUnrequested(std::shared_ptr, + std::shared_ptr) override {}; }; SyncAssetTask(const ghoul::Dictionary& dictionary); + std::string description() override; void perform(const Task::ProgressCallback& progressCallback) override; static documentation::Documentation documentation(); diff --git a/src/scene/asset.cpp b/src/scene/asset.cpp index 439f0c0356..90906e7373 100644 --- a/src/scene/asset.cpp +++ b/src/scene/asset.cpp @@ -109,7 +109,7 @@ void Asset::setState(Asset::State state) { for (auto& requiringAsset : _requiringAssets) { if (std::shared_ptr a = requiringAsset.lock()) { - a->requiredAssetChangedState(thisAsset, state); + a->requiredAssetChangedState(state); } } @@ -120,7 +120,7 @@ void Asset::setState(Asset::State state) { } } -void Asset::requiredAssetChangedState(std::shared_ptr child, Asset::State childState) { +void Asset::requiredAssetChangedState(Asset::State childState) { ghoul_assert(!isInitialized(), "Required asset changing state while parent asset is initialized"); if (childState == State::SyncResolved) { @@ -132,7 +132,9 @@ void Asset::requiredAssetChangedState(std::shared_ptr child, Asset::State } } -void Asset::requestedAssetChangedState(std::shared_ptr child, Asset::State childState) { +void Asset::requestedAssetChangedState(std::shared_ptr child, + Asset::State childState) +{ if (child->hasInitializedParent()) { if (childState == State::Loaded) { child->startSynchronizations(); @@ -147,18 +149,20 @@ void Asset::addSynchronization(std::shared_ptr synchron _synchronizations.push_back(synchronization); // Set up callback for synchronization state change - // The synchronization watcher will make sure that callbacks are invoked in the main thread. - SynchronizationWatcher::WatchHandle watch = _synchronizationWatcher->watchSynchronization( - synchronization, - [this, synchronization](ResourceSynchronization::State state) { - syncStateChanged(synchronization, state); - } - ); + // The synchronization watcher will make sure that callbacks + // are invoked in the main thread. + + SynchronizationWatcher::WatchHandle watch = + _synchronizationWatcher->watchSynchronization( + synchronization, + [this](ResourceSynchronization::State state) { + syncStateChanged(state); + } + ); _syncWatches.push_back(watch); } -void Asset::syncStateChanged(std::shared_ptr synchronization, - ResourceSynchronization::State state) +void Asset::syncStateChanged(ResourceSynchronization::State state) { if (state == ResourceSynchronization::State::Resolved) { if (!isSynchronized() && isSyncResolveReady()) { @@ -429,20 +433,13 @@ void Asset::load() { setState(loaded ? State::Loaded : State::LoadingFailed); } -void Asset::unloadIfUnwanted() { - if (hasLoadedParent()) { - return; - } - unload(); -} - void Asset::unload() { if (!isLoaded()) { return; } - loader()->unloadAsset(shared_from_this()); setState(State::Unloaded); + loader()->unloadAsset(shared_from_this()); for (std::shared_ptr child : requiredAssets()) { unrequire(child); @@ -452,6 +449,13 @@ void Asset::unload() { } } +void Asset::unloadIfUnwanted() { + if (hasLoadedParent()) { + return; + } + unload(); +} + void Asset::initialize() { if (isInitialized()) { return; @@ -462,12 +466,19 @@ void Asset::initialize() { } LDEBUG("Initializing asset " << id()); - // 1. Initialize required children + // 1. Initialize requirements for (auto& child : _requiredAssets) { child->initialize(); } - // 2. Call onInitialize in Lua + // 2. Initialize requests + for (auto& child : _requestedAssets) { + if (child->isSynchronized()) { + child->initialize(); + } + } + + // 3. Call lua onInitialize try { loader()->callOnInitialize(this); } catch (const ghoul::lua::LuaRuntimeException& e) { @@ -477,11 +488,10 @@ void Asset::initialize() { return; } - // 3. Update the internal state + // 4. Update state setState(Asset::State::Initialized); - // 4. Call dependency initialization functions - // Now that both this and all children are initialized. + // 5. Call dependency lua onInitialize of this and requirements for (auto& child : _requiredAssets) { try { loader()->callOnDependencyInitialize(child.get(), this); @@ -493,8 +503,7 @@ void Asset::initialize() { } } - // 5. Call dependency initialization function of the child and this - // if the requested child was initialized before this. + // 6. Call dependency lua onInitialize of this and initialized requests for (auto& child : _requestedAssets) { if (child->isInitialized()) { try { @@ -508,18 +517,10 @@ void Asset::initialize() { } } - // 6. Ask requested children to initialize if they are not already initialized. - for (auto& child : _requestedAssets) { - if (child->isSynchronized()) { - child->initialize(); - } - } - - // 7. Call dependency initialization function of this and the parent - // if the requesting parent was initialized before this. + // 7. Call dependency lua onInitialize of initialized requesting assets and this for (auto& parent : _requestingAssets) { std::shared_ptr p = parent.lock(); - if (p && p->state() == State::Initialized) { + if (p && p->isInitialized()) { try { loader()->callOnDependencyInitialize(this, p.get()); } catch (const ghoul::lua::LuaRuntimeException& e) { @@ -541,53 +542,68 @@ void Asset::deinitializeIfUnwanted() { } void Asset::deinitialize() { - if (state() != Asset::State::Initialized) { + if (!isInitialized()) { return; } - LDEBUG("Denitializing asset " << id()); - // Notify children - for (auto& dependency : _requiredAssets) { - try { - loader()->callOnDependencyDeinitialize(dependency.get(), this); - } - catch (const ghoul::lua::LuaRuntimeException& e) { - LERROR("Failed to deinitialize requested asset " << - dependency->id() << " of " << id() << ". " << - e.component << ": " << e.message); - // TODO: rollback? - } - } - for (auto& dependency : _requestedAssets) { - if (dependency->state() == State::Initialized) { + // Perform inverse actions as in initialize, in reverse order (7 - 1) + + // 7. Call dependency lua onDeinitialize of initialized requesting assets and this + for (auto& parent : _requestingAssets) { + std::shared_ptr p = parent.lock(); + if (p && p->isInitialized()) { try { - loader()->callOnDependencyDeinitialize(dependency.get(), this); + loader()->callOnDependencyDeinitialize(this, p.get()); } catch (const ghoul::lua::LuaRuntimeException& e) { LERROR("Failed to deinitialize requested asset " << - dependency->id() << " of " << id() << ". " << - e.component << ": " << e.message); - // TODO: rollback? + id() << " of " << p->id() << ". " << + e.component << ": " << e.message); } } } + // 6. Call dependency lua onDeinitialize of this and initialized requests + for (auto& child : _requestedAssets) { + if (child->isInitialized()) { + try { + loader()->callOnDependencyDeinitialize(child.get(), this); + } + catch (const ghoul::lua::LuaRuntimeException& e) { + LERROR("Failed to deinitialize requested asset " << + child->id() << " of " << id() << ". " << + e.component << ": " << e.message); + } + } + } + // 5. Call dependency lua onInitialize of this and requirements + for (auto& child : _requiredAssets) { + try { + loader()->callOnDependencyDeinitialize(child.get(), this); + } + catch (const ghoul::lua::LuaRuntimeException& e) { + LERROR("Failed to deinitialize required asset " << + child->id() << " of " << id() << ". " << + e.component << ": " << e.message); + } + } + + // 4. Update state + setState(Asset::State::SyncResolved); + + // 3. Call lua onInitialize try { loader()->callOnDeinitialize(this); } catch (const ghoul::lua::LuaRuntimeException& e) { LERROR("Failed to deinitialize asset " << id() << ". " << e.component << ": " << e.message); - // TODO: rollback? return; } - // Call onDeinitialize in Lua - setState(Asset::State::Loaded); - - // Make sure no dependencies are left dangling + // 2 and 1. Deinitialize unwanted requirements and requests for (auto& dependency : childAssets()) { dependency->deinitializeIfUnwanted(); } @@ -840,7 +856,6 @@ bool Asset::shouldBeInitialized() const { return a->state() == State::Initialized; } ); - return initializedAsset != parents.end(); } diff --git a/src/scene/assetloader.cpp b/src/scene/assetloader.cpp index 568fa8d5df..2422842fff 100644 --- a/src/scene/assetloader.cpp +++ b/src/scene/assetloader.cpp @@ -75,10 +75,10 @@ AssetLoader::AssetLoader( SynchronizationWatcher* syncWatcher, std::string assetRootDirectory ) - : _luaState(&luaState) - , _rootAsset(std::make_shared(this, syncWatcher)) + : _rootAsset(std::make_shared(this, syncWatcher)) , _synchronizationWatcher(syncWatcher) , _assetRootDirectory(assetRootDirectory) + , _luaState(&luaState) { setCurrentAsset(_rootAsset); @@ -219,7 +219,8 @@ bool AssetLoader::loadAsset(std::shared_ptr asset) { }); if (!FileSys.fileExists(asset->assetFilePath())) { - LERROR("Could not load asset '" << asset->assetFilePath() << "': File does not exist."); + LERROR("Could not load asset '" << asset->assetFilePath() << + "': File does not exist."); return false; } @@ -244,14 +245,14 @@ void AssetLoader::unloadAsset(std::shared_ptr asset) { } _onDeinitializationFunctionRefs.clear(); - for (const auto it : _onDependencyInitializationFunctionRefs[asset.get()]) { + for (const auto& it : _onDependencyInitializationFunctionRefs[asset.get()]) { for (int ref : it.second) { luaL_unref(*_luaState, LUA_REGISTRYINDEX, ref); } } _onDependencyInitializationFunctionRefs[asset.get()].clear(); - for (const auto it : _onDependencyDeinitializationFunctionRefs[asset.get()]) { + for (const auto& it : _onDependencyDeinitializationFunctionRefs[asset.get()]) { for (int ref : it.second) { luaL_unref(*_luaState, LUA_REGISTRYINDEX, ref); } @@ -312,7 +313,9 @@ int AssetLoader::onInitializeDependencyLua(Asset* dependant, Asset* dependency) int nArguments = lua_gettop(*_luaState); SCRIPT_CHECK_ARGUMENTS("onInitialize", *_luaState, 1, nArguments); int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX); - _onDependencyInitializationFunctionRefs[dependant][dependency].push_back(referenceIndex); + _onDependencyInitializationFunctionRefs[dependant][dependency] + .push_back(referenceIndex); + return 0; } @@ -320,7 +323,9 @@ int AssetLoader::onDeinitializeDependencyLua(Asset* dependant, Asset* dependency int nArguments = lua_gettop(*_luaState); SCRIPT_CHECK_ARGUMENTS("onDeinitialize", *_luaState, 1, nArguments); int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX); - _onDependencyDeinitializationFunctionRefs[dependant][dependency].push_back(referenceIndex); + _onDependencyDeinitializationFunctionRefs[dependant][dependency] + .push_back(referenceIndex); + return 0; } @@ -421,6 +426,8 @@ void AssetLoader::callOnDependencyInitialize(Asset* asset, Asset* dependant) { ); } } + // Potential Todo: + // Call dependency->onInitialize with The asset table exported by the child asset as argument } void AssetLoader::callOnDependencyDeinitialize(Asset* asset, Asset* dependant) { @@ -555,11 +562,9 @@ void AssetLoader::addLuaDependencyTable(Asset* dependant, Asset* dependency) { const std::string dependantId = dependant->id(); const std::string dependencyId = dependency->id(); + // Extract the imported asset's dependants table lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef); lua_getfield(*_luaState, -1, dependencyId.c_str()); - const int dependencyIndex = lua_gettop(*_luaState); - - // Extract the imported asset's dependants table lua_getfield(*_luaState, -1, DependantsTableName); const int dependantsTableIndex = lua_gettop(*_luaState); @@ -581,7 +586,7 @@ void AssetLoader::addLuaDependencyTable(Asset* dependant, Asset* dependency) { lua_pushcclosure(*_luaState, &assetloader::onDeinitializeDependency, 2); lua_setfield(*_luaState, currentDependantTableIndex, OnDeinitializeFunctionName); - // duplicate the table reference on the stack, so it remains after assignment. + // Duplicate the table reference on the stack, so it remains after assignment. lua_pushvalue(*_luaState, -1); // Register the dependant table on the imported asset's dependants table. diff --git a/src/scene/assetmanager.cpp b/src/scene/assetmanager.cpp index e2b7bb36cc..caa85d77e9 100644 --- a/src/scene/assetmanager.cpp +++ b/src/scene/assetmanager.cpp @@ -33,7 +33,7 @@ #include "assetmanager_lua.inl" namespace { - const char* _loggerCat = "AssetManager"; + // const char* _loggerCat = "AssetManager"; } namespace openspace { @@ -82,15 +82,18 @@ bool AssetManager::update() { return false; } -void AssetManager::assetStateChanged(std::shared_ptr asset, Asset::State state) { +void AssetManager::assetStateChanged(std::shared_ptr, Asset::State) { + // Potential todo: notify user about asset stage change //LINFO(asset->id() << " changed state to " << static_cast(state)); } -void AssetManager::assetRequested(std::shared_ptr parent, std::shared_ptr child) { +void AssetManager::assetRequested(std::shared_ptr, std::shared_ptr) { + // Potential todo: notify user about asset request //LINFO(parent->id() << " requested " << child->id()); } -void AssetManager::assetUnrequested(std::shared_ptr parent, std::shared_ptr child) { +void AssetManager::assetUnrequested(std::shared_ptr, std::shared_ptr) { + // Potential todo: notify user about asset unrequest //LINFO(parent->id() << " unrequested " << child->id()); }