From e0504980ad945f154a77c1ec862d4223e2019f46 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Mon, 11 Dec 2017 11:12:39 +0100 Subject: [PATCH] Initialize requested assets when they are ready --- assets/newhorizons.asset | 2 +- include/openspace/scene/asset.h | 9 ----- include/openspace/scene/assetloader.h | 21 +++++++----- include/openspace/scene/assetmanager.h | 5 +-- src/scene/asset.cpp | 47 +++++++------------------- src/scene/assetloader.cpp | 36 +++++++++++++++----- src/scene/assetmanager.cpp | 19 ++++------- 7 files changed, 64 insertions(+), 75 deletions(-) diff --git a/assets/newhorizons.asset b/assets/newhorizons.asset index 52d0f3235b..f499985568 100644 --- a/assets/newhorizons.asset +++ b/assets/newhorizons.asset @@ -1,3 +1,3 @@ asset.request('keybindings') asset.request('solarsystem') -asset.request('missions/newhorizons/spice/spice') \ No newline at end of file +asset.require('missions/newhorizons/spice/spice') \ No newline at end of file diff --git a/include/openspace/scene/asset.h b/include/openspace/scene/asset.h index be43a23491..56fd02b6df 100644 --- a/include/openspace/scene/asset.h +++ b/include/openspace/scene/asset.h @@ -75,9 +75,6 @@ public: std::string assetName() const; AssetLoader* loader() const; State state() const; - - CallbackHandle addStateChangeCallback(StateChangeCallback cb); - void removeStateChangeCallback(CallbackHandle handle); void setState(State state); void addSynchronization(std::shared_ptr synchronization); @@ -121,7 +118,6 @@ public: std::string resolveLocalResource(std::string resourceName); private: void requiredAssetChangedState(std::shared_ptr a); - void requestedAssetChangedState(std::shared_ptr a); void addRequestingAsset(std::shared_ptr a); void removeRequestingAsset(std::shared_ptr a); @@ -157,11 +153,6 @@ private: // Synchronization callback handles std::unordered_map _syncCallbackHandles; - - CallbackHandle _nextCallbackHandle; - std::unordered_map _stateChangeCallbacks; - std::mutex _stateChangeCallbackMutex; - }; } // namespace openspace diff --git a/include/openspace/scene/assetloader.h b/include/openspace/scene/assetloader.h index a4b475b430..2f1bf73515 100644 --- a/include/openspace/scene/assetloader.h +++ b/include/openspace/scene/assetloader.h @@ -25,7 +25,7 @@ #ifndef __OPENSPACE_CORE___ASSETLOADER___H__ #define __OPENSPACE_CORE___ASSETLOADER___H__ -#include +#include #include #include @@ -42,7 +42,6 @@ namespace openspace { -class Asset; namespace assetloader { int onInitialize(lua_State* state); @@ -57,6 +56,11 @@ int noOperation(lua_State* state); int exportAsset(lua_State* state); } // namespace assetloader +class AssetStateChangeListener { +public: + virtual void assetStateChanged(std::shared_ptr asset, Asset::State state) = 0; +}; + class AssetLoader { public: /** @@ -84,12 +88,6 @@ public: */ void remove(const std::string& identifier); - /** - * Remove the asset as a dependency on the root asset - * The asset is unloaded synchronously - */ - void remove(const Asset* asset); - /** * Returns the asset identified by the identifier, * if the asset is loaded. Otherwise return nullptr. @@ -127,6 +125,11 @@ public: std::string generateAssetPath(const std::string& baseDirectory, const std::string& path) const; + + + void addAssetStateChangeListener(AssetStateChangeListener* listener); + void removeAssetStateChangeListener(AssetStateChangeListener* listener); + void assetStateChanged(std::shared_ptr asset, Asset::State state); private: std::shared_ptr require(const std::string& identifier); @@ -179,6 +182,8 @@ private: std::unordered_map>> _onDependencyDeinitializationFunctionRefs; + std::vector _assetStateChangeListeners; + int _assetsTableRef; }; diff --git a/include/openspace/scene/assetmanager.h b/include/openspace/scene/assetmanager.h index b7dc01c047..4f537a6dc5 100644 --- a/include/openspace/scene/assetmanager.h +++ b/include/openspace/scene/assetmanager.h @@ -51,7 +51,7 @@ class Asset; * from the system if it is not a dependency of a loaded asset. */ -class AssetManager { +class AssetManager : AssetStateChangeListener { public: AssetManager( std::unique_ptr loader @@ -64,12 +64,13 @@ public: void removeAll(); std::shared_ptr rootAsset(); + void assetStateChanged(std::shared_ptr asset, Asset::State state) override; + bool update(); scripting::LuaLibrary luaLibrary(); private: std::shared_ptr tryAddAsset(const std::string& path); bool tryRemoveAsset(const std::string& path); - void assetStateChanged(std::shared_ptr asset, Asset::State state); std::unordered_map _pendingStateChangeCommands; std::mutex _pendingInitializationsMutex; diff --git a/src/scene/asset.cpp b/src/scene/asset.cpp index 924dbfac70..c766ebac79 100644 --- a/src/scene/asset.cpp +++ b/src/scene/asset.cpp @@ -69,57 +69,34 @@ Asset::State Asset::state() const { return _state; } -Asset::CallbackHandle Asset::addStateChangeCallback(StateChangeCallback cb) { - std::lock_guard guard(_stateChangeCallbackMutex); - CallbackHandle h = _nextCallbackHandle++; - _stateChangeCallbacks.emplace(h, cb); - return h; -} - -void Asset::removeStateChangeCallback(Asset::CallbackHandle handle) { - std::lock_guard guard(_stateChangeCallbackMutex); - _stateChangeCallbacks.erase(handle); -} - void Asset::setState(Asset::State state) { if (_state == state) { return; } _state = state; + std::shared_ptr thisAsset = shared_from_this(); + for (auto& requiringAsset : _requiringAssets) { if (std::shared_ptr a = requiringAsset.lock()) { - a->requiredAssetChangedState(shared_from_this()); + a->requiredAssetChangedState(thisAsset); } } - for (auto& requestingAsset : _requestingAssets) { - if (std::shared_ptr a = requestingAsset.lock()) { - a->requestedAssetChangedState(shared_from_this()); - } - } - std::lock_guard guard(_stateChangeCallbackMutex); - for (auto& cb : _stateChangeCallbacks) { - cb.second(state); - } + + _loader->assetStateChanged(thisAsset, state); } void Asset::requiredAssetChangedState(std::shared_ptr child) { State childState = child->state(); - if (childState == State::SyncResolved) { if (isSyncResolveReady()) { setState(State::SyncResolved); } - } - else if (childState == State::SyncRejected) { + } else if (childState == State::SyncRejected) { setState(State::SyncRejected); } } -void Asset::requestedAssetChangedState(std::shared_ptr child) { - // TODO: implement this -} - void Asset::addSynchronization(std::shared_ptr synchronization) { { std::lock_guard guard(_synchronizationsMutex); @@ -274,7 +251,7 @@ bool Asset::restartSynchronizations() { } float Asset::synchronizationProgress() { - std::vector> assets = subTreeAssets(); + std::vector> assets = requiredSubTreeAssets(); size_t nTotalBytes = 0; size_t nSyncedBytes = 0; @@ -502,11 +479,13 @@ void Asset::addRequestingAsset(std::shared_ptr parent) { if (parentState == State::Synchronizing || parentState == State::SyncResolved || - parentState == State::Initialized) + parentState == State::Initialized || + parentState == State::InitializationFailed) { - if (childState != State::Synchronizing || - childState != State::SyncResolved || - childState != State::Initialized) + if (childState != State::Synchronizing && + childState != State::SyncResolved && + childState != State::Initialized && + childState != State::InitializationFailed) { startSynchronizations(); } diff --git a/src/scene/assetloader.cpp b/src/scene/assetloader.cpp index ef36b109bd..4c96f5b02a 100644 --- a/src/scene/assetloader.cpp +++ b/src/scene/assetloader.cpp @@ -121,7 +121,33 @@ std::string AssetLoader::generateAssetPath(const std::string& baseDirectory, "." + AssetFileSuffix); } - + +void AssetLoader::addAssetStateChangeListener(AssetStateChangeListener* listener) { + const auto it = std::find( + _assetStateChangeListeners.begin(), + _assetStateChangeListeners.end(), + listener + ); + + if (it == _assetStateChangeListeners.end()) { + _assetStateChangeListeners.push_back(listener); + } +} + +void AssetLoader::removeAssetStateChangeListener(AssetStateChangeListener* listener) { + _assetStateChangeListeners.erase(std::remove( + _assetStateChangeListeners.begin(), + _assetStateChangeListeners.end(), + listener + )); +} + +void AssetLoader::assetStateChanged(std::shared_ptr asset, Asset::State state) { + for (auto& listener : _assetStateChangeListeners) { + listener->assetStateChanged(asset, state); + } +} + std::shared_ptr AssetLoader::getAsset(std::string name) { ghoul::filesystem::Directory directory = currentDirectory(); std::string path = generateAssetPath(directory, name); @@ -217,14 +243,6 @@ std::shared_ptr AssetLoader::add(const std::string& identifier) { void AssetLoader::remove(const std::string& identifier) { ghoul_assert(_assetStack.size() == 1, "Can only unload an asset from the root asset"); unrequest(identifier); - // TODO: Implement this - //_rootAsset->removeDependency(id); -} - -void AssetLoader::remove(const Asset* asset) { - ghoul_assert(_assetStack.size() == 1, "Can only unload an asset from the root asset"); - // TODO: Implement this - //_rootAsset->removeDependency(id); } std::shared_ptr AssetLoader::has(const std::string& name) const { diff --git a/src/scene/assetmanager.cpp b/src/scene/assetmanager.cpp index 483d9b52d4..e3704484a7 100644 --- a/src/scene/assetmanager.cpp +++ b/src/scene/assetmanager.cpp @@ -42,23 +42,14 @@ AssetManager::AssetManager(std::unique_ptr loader) {} void AssetManager::initialize() { - /*_addAssetCallbackHandle = _assetLoader->addAssetLoadCallback( - [this] (std::shared_ptr a) { - a->addStateChangeCallback([a, this] (Asset::State state) { - assetStateChanged(a, state); - }); - } - );*/ + _assetLoader->addAssetStateChangeListener(this); std::shared_ptr rootAsset = _assetLoader->rootAsset(); - rootAsset->addStateChangeCallback([&rootAsset, this] (Asset::State state) { - assetStateChanged(rootAsset, state); - }); rootAsset->initialize(); } void AssetManager::deinitialize() { _assetLoader->rootAsset()->deinitialize(); - //_assetLoader->removeAssetLoadCallback(_addAssetCallbackHandle); + _assetLoader->removeAssetStateChangeListener(this); } bool AssetManager::update() { @@ -94,6 +85,10 @@ bool AssetManager::update() { } void AssetManager::assetStateChanged(std::shared_ptr asset, Asset::State state) { + if (asset->requestingAssets().empty()) { + return; + } + if (rootAsset()->state() == Asset::State::Initialized) { if (state == Asset::State::Loaded) { asset->startSynchronizations(); @@ -156,7 +151,7 @@ scripting::LuaLibrary AssetManager::luaLibrary() { std::shared_ptr AssetManager::tryAddAsset(const std::string& path) { try { - _assetLoader->add(path); + return _assetLoader->add(path); } catch (const ghoul::RuntimeError& e) { LERROR("Error adding asset: " << e.component << ": " << e.message); }