From 436062381ef66dd56c6e599984cd6933cc844ae5 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Thu, 16 Nov 2017 19:29:45 +0100 Subject: [PATCH] Asset loading and synchronization --- include/openspace/scene/asset.h | 44 +++-- include/openspace/scene/assetloader.h | 40 ++-- include/openspace/scene/assetmanager.h | 30 +-- modules/imgui/src/guiassetcomponent.cpp | 14 +- src/engine/openspaceengine.cpp | 6 +- src/scene/asset.cpp | 239 ++++++++++++++---------- src/scene/assetloader.cpp | 58 +++--- src/scene/assetmanager.cpp | 163 +++++++--------- src/scene/assetmanager_lua.inl | 49 +++-- 9 files changed, 339 insertions(+), 304 deletions(-) diff --git a/include/openspace/scene/asset.h b/include/openspace/scene/asset.h index 2f94650545..550087ba0f 100644 --- a/include/openspace/scene/asset.h +++ b/include/openspace/scene/asset.h @@ -33,7 +33,7 @@ #include #include -#include +#include #include namespace openspace { @@ -76,28 +76,40 @@ public: void setState(State state); void addSynchronization(std::shared_ptr synchronization); std::vector> synchronizations(); - std::vector> allAssets(); + + // Sync bool startSynchronizations(); bool cancelSynchronizations(); bool restartSynchronizations(); float synchronizationProgress(); + // Init bool isInitReady() const; void initialize(); void deinitialize(); - bool hasDependency(const Asset* asset) const; - void addDependency(std::shared_ptr asset); - void removeDependency(Asset* asset); - void removeDependency(const std::string& assetId); - std::vector> dependencies(); + // Dependency graph + bool requires(const Asset* asset) const; + void require(std::shared_ptr asset); - bool hasDependants() const; - bool hasInitializedDependants() const; + bool requests(const Asset* child) const; + void request(std::shared_ptr child); + void unrequest(std::shared_ptr child); + + std::vector> requiredSubTreeAssets(); + std::vector> subTreeAssets(); + std::vector> requestedAssets(); + std::vector> requiredAssets(); + std::vector> childAssets(); + + bool isRequired() const; + bool isRequested() const; std::string resolveLocalResource(std::string resourceName); private: + + void handleRequests(); void startSync(ResourceSynchronization& rs); void cancelSync(ResourceSynchronization& rs); @@ -112,11 +124,17 @@ private: // Absolute path to asset file std::string _assetPath; - // Dependencies - std::vector> _dependencies; + // Required assets + std::vector> _requiredAssets; - // Assets that refers to this asset as an dependency - std::vector> _dependants; + // Assets that refers to this asset as a required asset + std::vector> _requiringAssets; + + // Requested assets + std::vector> _requestedAssets; + + // Assets that refers to this asset as a requested asset + std::vector> _requestingAssets; }; } // namespace openspace diff --git a/include/openspace/scene/assetloader.h b/include/openspace/scene/assetloader.h index 7d3fda4c66..e0dd6676a8 100644 --- a/include/openspace/scene/assetloader.h +++ b/include/openspace/scene/assetloader.h @@ -71,43 +71,34 @@ public: ~AssetLoader(); /** - * Load an asset: - * Add the asset as a dependency on the root asset + * Add the asset as a request for the root asset * The asset is loaded synchronously */ - std::shared_ptr loadAsset(const std::string& identifier); + std::shared_ptr add(const std::string& identifier); /** - * Unload an asset: * Remove the asset as a dependency on the root asset * The asset is unloaded synchronously */ - void unloadAsset(const std::string& identifier); + void remove(const std::string& identifier); /** - * Unload an asset: * Remove the asset as a dependency on the root asset * The asset is unloaded synchronously */ - void unloadAsset(const Asset* asset); + void remove(const Asset* asset); /** - * Return true if the specified asset is loaded - */ - bool hasLoadedAsset(const std::string& identifier); - - - /** - * Returns the asset identified by the identifier, - * if the asset is loaded. Otherwise return nullptr. - */ - std::shared_ptr loadedAsset(const std::string& identifier); + * Returns the asset identified by the identifier, + * if the asset is loaded. Otherwise return nullptr. + */ + std::shared_ptr has(const std::string& identifier); /** * Return all assets loaded using the loadAsset method. * Non-recursive (does not include imports of the loaded assets) */ - std::vector> loadedAssets(); + //std::vector> loadedAssets(); /** * Return the lua state @@ -128,15 +119,18 @@ public: void callOnDeinitialize(Asset* asset); - void callOnDependantInitialize(Asset* asset, Asset* dependant); + void callOnDependencyInitialize(Asset* asset, Asset* dependant); - void callOnDependantDeinitialize(Asset* asset, Asset* dependant); + void callOnDependencyDeinitialize(Asset* asset, Asset* dependant); std::string generateAssetPath(const std::string& baseDirectory, const std::string& path) const; private: - std::shared_ptr importDependency(const std::string& identifier); - std::shared_ptr importAsset(std::string path); + std::shared_ptr require(const std::string& identifier); + std::shared_ptr request(const std::string& path); + void unrequest(const std::string& path); + + std::shared_ptr loadAsset(std::string path); std::shared_ptr getAsset(std::string path); ghoul::filesystem::Directory currentDirectory(); @@ -166,7 +160,7 @@ private: friend int assetloader::exportAsset(lua_State* state); std::shared_ptr _rootAsset; - std::map> _importedAssets; + std::map> _loadedAssets; std::vector> _assetStack; std::string _assetRootDirectory; diff --git a/include/openspace/scene/assetmanager.h b/include/openspace/scene/assetmanager.h index c803fdfafe..66d8218fa5 100644 --- a/include/openspace/scene/assetmanager.h +++ b/include/openspace/scene/assetmanager.h @@ -57,34 +57,34 @@ public: std::unique_ptr loader ); - struct ManagedAsset { - std::string path; - std::shared_ptr asset; - }; + void initialize(); + void deinitialize(); + void add(const std::string& path); + void remove(const std::string& path); + void removeAll(); + std::shared_ptr rootAsset(); bool update(); - void setTargetAssetState(const std::string& path, Asset::State targetState); - void setTargetAssetState(Asset* asset, Asset::State targetState); - Asset::State currentAssetState(Asset* asset); - Asset::State currentAssetState(const std::string& path); - - void clearAllTargetAssets(); - std::vector> loadedAssets(); + //void setTargetAssetState(const std::string& path, Asset::State targetState); + //void setTargetAssetState(Asset* asset, Asset::State targetState); + //Asset::State currentAssetState(Asset* asset); + //Asset::State currentAssetState(const std::string& path); + //void clearAllTargetAssets(); + //std::vector> loadedAssets(); scripting::LuaLibrary luaLibrary(); bool isDone(); private: - std::shared_ptr tryLoadAsset(const std::string& path); + std::shared_ptr tryAddAsset(const std::string& path); + bool tryRemoveAsset(const std::string& path); void unloadAsset(Asset* asset); bool tryInitializeAsset(Asset& asset); bool tryDeinitializeAsset(Asset& asset); void startSynchronization(Asset& asset); void cancelSynchronization(Asset& asset); - std::vector _managedAssets; - - std::unordered_map _pendingStateChangeCommands; + std::unordered_map _pendingStateChangeCommands; //std::unordered_map _stateChangesInProgress; std::unordered_set _pendingInitializations; diff --git a/modules/imgui/src/guiassetcomponent.cpp b/modules/imgui/src/guiassetcomponent.cpp index a40eff1c31..6cea8abdfe 100644 --- a/modules/imgui/src/guiassetcomponent.cpp +++ b/modules/imgui/src/guiassetcomponent.cpp @@ -45,20 +45,14 @@ void GuiAssetComponent::render() { AssetManager& assetManager = OsEng.assetManager(); - std::unordered_set> allAssets; - std::vector> loadedAssets = assetManager.loadedAssets(); - - for (const std::shared_ptr& ancestor : loadedAssets) { - const std::vector> all = ancestor->allAssets(); - std::copy(all.begin(), all.end(), std::inserter(allAssets, allAssets.end())); - } - + + std::vector> allAssets = + assetManager.rootAsset()->subTreeAssets(); + for (const auto& a : allAssets) { ImGui::Text("%s", a->assetFilePath().c_str()); ImGui::NextColumn(); - assetManager.currentAssetState(a.get()); - ImGui::NextColumn(); ImGui::Separator(); /* diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 847de20e7e..f8891064e3 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -555,6 +555,7 @@ void OpenSpaceEngine::initialize() { std::string assetPath = ""; configurationManager().getValue(ConfigurationManager::KeyConfigAsset, assetPath); + _engine->_assetManager->initialize(); scheduleLoadSingleAsset(assetPath); LTRACE("OpenSpaceEngine::initialize(end)"); @@ -599,8 +600,9 @@ void OpenSpaceEngine::loadSingleAsset(const std::string& assetPath) { _navigationHandler->setFocusNode(camera->parent()); _renderEngine->setScene(_scene.get()); - _assetManager->clearAllTargetAssets(); - _assetManager->setTargetAssetState(assetPath, Asset::State::Initialized); + + _assetManager->removeAll(); + _assetManager->add(assetPath); bool showMessage = true; std::string kMessage = diff --git a/src/scene/asset.cpp b/src/scene/asset.cpp index bfdfb98b04..e3dbbae86d 100644 --- a/src/scene/asset.cpp +++ b/src/scene/asset.cpp @@ -57,10 +57,20 @@ std::string Asset::resolveLocalResource(std::string resourceName) { resourceName; } -void Asset::startSync(ResourceSynchronization & rs) { +void Asset::handleRequests() { + State currentState = state(); + + if (currentState == State::Initialized) { + // ... + } } -void Asset::cancelSync(ResourceSynchronization & rs) { +void Asset::startSync(ResourceSynchronization& rs) { + rs.start(); +} + +void Asset::cancelSync(ResourceSynchronization& rs) { + rs.cancel(); } Asset::State Asset::state() const { @@ -80,11 +90,21 @@ std::vector> Asset::synchronizations() return _synchronizations; } -std::vector> Asset::allAssets() { - std::set> assets({ shared_from_this() }); - for (auto& dep : _dependencies) { - std::vector> depAssets = dep->allAssets(); - std::copy(depAssets.begin(), depAssets.end(), std::inserter(assets, assets.end())); +std::vector> Asset::subTreeAssets() { + std::unordered_set> assets({ shared_from_this() }); + for (auto& c : childAssets()) { + std::vector> subTree = c->subTreeAssets(); + std::copy(subTree.begin(), subTree.end(), std::inserter(assets, assets.end())); + } + std::vector> assetVector(assets.begin(), assets.end()); + return assetVector; +} + +std::vector> Asset::requiredSubTreeAssets() { + std::unordered_set> assets({ shared_from_this() }); + for (auto& dep : _requiredAssets) { + std::vector> subTree = dep->requiredSubTreeAssets(); + std::copy(subTree.begin(), subTree.end(), std::inserter(assets, assets.end())); } std::vector> assetVector(assets.begin(), assets.end()); return assetVector; @@ -92,8 +112,8 @@ std::vector> Asset::allAssets() { bool Asset::startSynchronizations() { bool startedAnySync = false; - for (auto& dep : _dependencies) { - bool started = dep->startSynchronizations(); + for (auto& child : childAssets()) { + bool started = child->startSynchronizations(); if (started) { startedAnySync = true; } @@ -112,8 +132,8 @@ bool Asset::startSynchronizations() { bool Asset::cancelSynchronizations() { bool cancelledAnySync = false; - for (auto& dep : _dependencies) { - bool cancelled = dep->cancelSynchronizations(); + for (auto& child : childAssets()) { + bool cancelled = child->cancelSynchronizations(); if (cancelled) { cancelledAnySync = true; } @@ -136,7 +156,7 @@ bool Asset::restartSynchronizations() { } float Asset::synchronizationProgress() { - std::vector> assets = allAssets(); + std::vector> assets = subTreeAssets(); size_t nTotalBytes = 0; size_t nSyncedBytes = 0; @@ -168,7 +188,7 @@ bool Asset::isInitReady() const { return false; } } - for (const auto& dependency : _dependencies) { + for (const auto& dependency : _requiredAssets) { if (!dependency->isInitReady()) { return false; } @@ -187,20 +207,46 @@ void Asset::initialize() { return; } - // Initialize dependencies - for (auto& dependency : _dependencies) { - dependency->initialize(); + // 1. Initialize required children + for (auto& child : _requiredAssets) { + child->initialize(); } - setState(Asset::State::Initialized); - - // Call onInitialize in Lua + // 2. Call onInitialize in Lua loader()->callOnInitialize(this); - // Notify dependencies - for (auto& dependency : _dependencies) { - loader()->callOnDependantInitialize(dependency.get(), this); + // 3. Update the internal state + setState(Asset::State::Initialized); + + // 4. Call dependency initialization functions + // Now that both this and all children are initialized. + for (auto& child : _requiredAssets) { + loader()->callOnDependencyInitialize(child.get(), this); } + + // 5. Call dependency initialization function of the child and this + // if the requested child was initialized before this. + for (auto& child : _requestedAssets) { + if (child->state() == State::Initialized) { + loader()->callOnDependencyInitialize(child.get(), this); + } + } + + // 6. Ask requested children to initialize if they are not already initialized. + // Initialization may not happen immediately. + for (auto& child : _requestedAssets) { + child->handleRequests(); + } + + // 7. Call dependency initialization function of this and the parent + // if the requesting parent was initialized before this. + for (auto& parent : _requestingAssets) { + std::shared_ptr p = parent.lock(); + if (p && p->state() == State::Initialized) { + loader()->callOnDependencyInitialize(this, p.get()); + } + } + } void Asset::deinitialize() { @@ -208,9 +254,14 @@ void Asset::deinitialize() { return; } - // Notify dependencies - for (auto& dependency : _dependencies) { - loader()->callOnDependantDeinitialize(dependency.get(), this); + // Notify children + for (auto& dependency : _requiredAssets) { + loader()->callOnDependencyDeinitialize(dependency.get(), this); + } + for (auto& dependency : _requestedAssets) { + if (dependency->state() == State::Initialized) { + loader()->callOnDependencyDeinitialize(dependency.get(), this); + } } // Call onDeinitialize in Lua @@ -219,8 +270,8 @@ void Asset::deinitialize() { setState(Asset::State::Loaded); // Make sure no dependencies are left dangling - for (auto& dependency : _dependencies) { - if (!dependency->hasInitializedDependants()) { + for (auto& dependency : childAssets()) { + if (!dependency->isRequired() && !dependency->isRequested()) { dependency->deinitialize(); } } @@ -250,101 +301,99 @@ AssetLoader* Asset::loader() const { return _loader; } -bool Asset::hasDependency(const Asset* asset) const { +bool Asset::requires(const Asset* asset) const { const auto it = std::find_if( - _dependencies.begin(), - _dependencies.end(), + _requiredAssets.begin(), + _requiredAssets.end(), [asset](std::shared_ptr dep) { return dep.get() == asset; } ); - - return it != _dependencies.end(); + return it != _requiredAssets.end(); } -void Asset::addDependency(std::shared_ptr dependency) { +void Asset::require(std::shared_ptr child) { if (state() == Asset::State::Unloaded) { - // TODO: Throw: Can only add dependency when in Loaded state + // TODO: Throw: Can only require asset when in unloaded state return; } - // Do nothing if the dependency already exists. - auto it = std::find(_dependencies.begin(), - _dependencies.end(), - dependency); + auto it = std::find(_requiredAssets.begin(), + _requiredAssets.end(), + child); - if (it != _dependencies.end()) { + if (it != _requiredAssets.end()) { + // Do nothing if the requirement already exists. return; } - - _dependencies.push_back(dependency); - dependency->_dependants.push_back(shared_from_this()); - - //addPropertySubOwner(dependency); + _requiredAssets.push_back(child); + child->_requiringAssets.push_back(shared_from_this()); } -void Asset::removeDependency(Asset* dependency) { - _dependencies.erase( - std::remove_if(_dependencies.begin(), - _dependencies.end(), - [dependency](std::shared_ptr asset) { - return asset.get() == dependency; - } - ), - _dependencies.end() - ); - std::vector>& dependants = dependency->_dependants; - dependants.erase( - std::remove_if(dependants.begin(), dependants.end(), [this](std::weak_ptr asset) { - return asset.lock().get() == this; - }), - dependants.end() - ); +void Asset::request(std::shared_ptr child) { + auto it = std::find(_requestedAssets.begin(), + _requestedAssets.end(), + child); - if (!dependency->hasInitializedDependants()) { - dependency->deinitialize(); + if (it != _requestedAssets.end()) { + // Do nothing if the request already exists. + return; } + _requestedAssets.push_back(child); + child->_requestingAssets.push_back(shared_from_this()); + + child->handleRequests(); } -void Asset::removeDependency(const std::string& assetId) { - auto dep = std::find_if( - _dependencies.begin(), - _dependencies.end(), - [&assetId](const std::shared_ptr& d) { - return d->id() == assetId; - }); +void Asset::unrequest(std::shared_ptr child) { + auto it = std::find(_requestedAssets.begin(), + _requestedAssets.end(), + child); - if (dep != _dependencies.end()) { - removeDependency(dep->get()); - } else { - LERROR("No such dependency '" << assetId << "'"); + if (it != _requestedAssets.end()) { + // Do nothing if the request already exists. + return; } + _requestedAssets.push_back(child); + child->_requestingAssets.push_back(shared_from_this()); + + child->handleRequests(); } -std::vector> Asset::dependencies() { - return _dependencies; -} - -bool Asset::hasDependants() const { - for (const auto& dependant : _dependants) { - std::shared_ptr d = dependant.lock(); - if (d && d->hasDependency(this)) { - return true; +bool Asset::requests(const Asset* asset) const { + const auto it = std::find_if( + _requestedAssets.begin(), + _requestedAssets.end(), + [asset](std::shared_ptr dep) { + return dep.get() == asset; } - } - return false; + ); + return it != _requiredAssets.end(); } -bool Asset::hasInitializedDependants() const { - for (const auto& dependant : _dependants) { - std::shared_ptr d = dependant.lock(); - if (d && d->state() == Asset::State::Initialized && - d->hasDependency(this)) - { - return true; - } - } - return false; +std::vector> Asset::requiredAssets() { + return _requiredAssets; } +std::vector> Asset::requestedAssets() { + return _requestedAssets; +} + +std::vector> Asset::childAssets() { + std::vector> children; + children.reserve(_requiredAssets.size() + _requestedAssets.size()); + children.insert(_requiredAssets.begin(), _requiredAssets.end(), children.end()); + children.insert(_requestedAssets.begin(), _requestedAssets.end(), children.end()); + return children; +} + +bool Asset::isRequired() const { + return !_requiringAssets.empty(); +} + +bool Asset::isRequested() const { + return !_requestingAssets.empty(); +} + + } diff --git a/src/scene/assetloader.cpp b/src/scene/assetloader.cpp index 8c87de1901..22a215c399 100644 --- a/src/scene/assetloader.cpp +++ b/src/scene/assetloader.cpp @@ -87,7 +87,7 @@ AssetLoader::AssetLoader( AssetLoader::~AssetLoader() { } -std::shared_ptr AssetLoader::importAsset(std::string path) { +std::shared_ptr AssetLoader::loadAsset(std::string path) { std::shared_ptr asset = std::make_shared(this, path); pushAsset(asset); @@ -100,7 +100,7 @@ std::shared_ptr AssetLoader::importAsset(std::string path) { } ghoul::lua::runScriptFile(*_luaState, path); - _importedAssets.emplace(asset->id(), asset); + _loadedAssets.emplace(asset->id(), asset); asset->setState(Asset::State::Loaded); return asset; @@ -125,10 +125,10 @@ std::shared_ptr AssetLoader::getAsset(std::string name) { std::string path = generateAssetPath(directory, name); // Check if asset is already loaded. - const auto it = _importedAssets.find(path); + const auto it = _loadedAssets.find(path); - return it == _importedAssets.end() ? - importAsset(path) : + return it == _loadedAssets.end() ? + loadAsset(path) : it->second; } @@ -164,13 +164,25 @@ int AssetLoader::onDeinitializeDependencyLua(Asset* dependant, Asset* dependency return 0; } -std::shared_ptr AssetLoader::importDependency(const std::string& name) { +std::shared_ptr AssetLoader::require(const std::string& name) { std::shared_ptr asset = getAsset(name); std::shared_ptr dependant = _assetStack.back(); - dependant->addDependency(asset); + dependant->require(asset); return asset; } +std::shared_ptr AssetLoader::request(const std::string& name) { + try { + std::shared_ptr asset = getAsset(name); + std::shared_ptr parent = _assetStack.back(); + parent->request(asset); + return asset; + } catch (const ghoul::RuntimeError& e) { + LERROR("Failed to load " << name << e.component << " :" << e.message); + } + return nullptr; +} + ghoul::filesystem::Directory AssetLoader::currentDirectory() { if (_assetStack.back()->hasAssetFile()) { return _assetStack.back()->assetDirectory(); @@ -179,44 +191,32 @@ ghoul::filesystem::Directory AssetLoader::currentDirectory() { } } -std::shared_ptr AssetLoader::loadAsset(const std::string & identifier) { +std::shared_ptr AssetLoader::add(const std::string& identifier) { ghoul_assert(_assetStack.size() == 1, "Can only load an asset from the root asset"); - return importDependency(identifier); + return request(identifier); } -void AssetLoader::unloadAsset(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"); // TODO: Implement this //_rootAsset->removeDependency(id); } -void AssetLoader::unloadAsset(const Asset* asset) { +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); } -bool AssetLoader::hasLoadedAsset(const std::string & identifier) { - const auto it = _importedAssets.find(identifier); - if (it == _importedAssets.end()) { +std::shared_ptr AssetLoader::has(const std::string& identifier) { + const auto it = _loadedAssets.find(identifier); + if (it == _loadedAssets.end()) { return false; } - return _rootAsset->hasDependency(it->second.get()); -} - -std::shared_ptr AssetLoader::loadedAsset(const std::string & identifier) { - const auto it = _importedAssets.find(identifier); - if (it == _importedAssets.end()) { - return nullptr; - } return it->second; } -std::vector> AssetLoader::loadedAssets() { - return _rootAsset->dependencies(); -} - ghoul::lua::LuaState* AssetLoader::luaState() { return _luaState; } @@ -253,7 +253,7 @@ void AssetLoader::callOnDeinitialize(Asset * asset) { } } -void AssetLoader::callOnDependantInitialize(Asset* asset, Asset* dependant) { +void AssetLoader::callOnDependencyInitialize(Asset* asset, Asset* dependant) { for (int init : _onDependencyInitializationFunctionRefs[dependant][asset]) { lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, init); if (lua_pcall(*_luaState, 0, 0, 0) != LUA_OK) { @@ -265,7 +265,7 @@ void AssetLoader::callOnDependantInitialize(Asset* asset, Asset* dependant) { } } -void AssetLoader::callOnDependantDeinitialize(Asset* asset, Asset* dependant) { +void AssetLoader::callOnDependencyDeinitialize(Asset* asset, Asset* dependant) { std::vector& funs = _onDependencyDeinitializationFunctionRefs[dependant][asset]; for (auto it = funs.rbegin(); it != funs.rend(); it++) { lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, *it); @@ -432,7 +432,7 @@ int AssetLoader::importDependencyLua(Asset* dependant) { std::string assetName = luaL_checkstring(*_luaState, 1); - std::shared_ptr dependency = importDependency(assetName); + std::shared_ptr dependency = require(assetName); if (!dependency) { return luaL_error(*_luaState, "Asset '%s' not found", assetName.c_str()); diff --git a/src/scene/assetmanager.cpp b/src/scene/assetmanager.cpp index dd22b985b4..e3d1f79c4f 100644 --- a/src/scene/assetmanager.cpp +++ b/src/scene/assetmanager.cpp @@ -41,26 +41,34 @@ AssetManager::AssetManager(std::unique_ptr loader) : _assetLoader(std::move(loader)) {} +void AssetManager::initialize() { + _assetLoader->rootAsset()->initialize(); +} + +void AssetManager::deinitialize() { + _assetLoader->rootAsset()->deinitialize(); +} + bool AssetManager::update() { // 1. Load assets. // 2. Start/cancel synchronizations // 3. Unload assets. - // Load assets + // Add assets for (const auto& c : _pendingStateChangeCommands) { const std::string& path = c.first; - const Asset::State targetState = c.second; - if (targetState != Asset::State::Unloaded && !_assetLoader->loadedAsset(path)) { - std::shared_ptr asset = tryLoadAsset(path); + const bool add = c.second; + if (add && !_assetLoader->has(path)) { + std::shared_ptr asset = tryAddAsset(path); } } // Start/cancel synchronizations and/or deinitialize - for (const auto& c : _pendingStateChangeCommands) { + /*for (const auto& c : _pendingStateChangeCommands) { const std::string& path = c.first; const Asset::State targetState = c.second; - std::shared_ptr asset = _assetLoader->loadedAsset(path); + std::shared_ptr asset = _assetLoader->has(path); if (!asset) { continue; } @@ -90,7 +98,17 @@ bool AssetManager::update() { _pendingInitializations.erase(asset.get()); tryDeinitializeAsset(*asset); } + }*/ + + // Remove assets + for (const auto& c : _pendingStateChangeCommands) { + const std::string& path = c.first; + const bool remove = c.second; + if (remove && _assetLoader->has(path)) { + tryRemoveAsset(path); + } } + // TODO: Handle state changes /*std::vector stateChanges = @@ -221,89 +239,76 @@ void AssetManager::handleSyncStateChange(AssetSynchronizer::StateChange stateCha _syncAncestors.erase(stateChange.asset.get()); }*/ -void AssetManager::setTargetAssetState(const std::string& path, Asset::State targetState) { - _pendingStateChangeCommands[path] = targetState; +void AssetManager::add(const std::string& path) { + _pendingStateChangeCommands[path] = true; } -Asset::State AssetManager::currentAssetState(Asset* asset) { - const auto it = std::find_if( - _managedAssets.begin(), - _managedAssets.end(), - [&asset](const ManagedAsset& ma){ - return ma.asset.get() == asset; - } - ); - if (it == _managedAssets.end()) { - return Asset::State::Unloaded; - } - return it->asset->state(); +void AssetManager::remove(const std::string& path) { + _pendingStateChangeCommands[path] = false; } -Asset::State AssetManager::currentAssetState(const std::string& assetIdentifier) { - const auto it = std::find_if( - _managedAssets.begin(), - _managedAssets.end(), - [&assetIdentifier](const ManagedAsset& ma) { - return ma.path == assetIdentifier; - } - ); - if (it == _managedAssets.end()) { - return Asset::State::Unloaded; - } - return it->asset->state(); -} - - -void AssetManager::clearAllTargetAssets() { +void AssetManager::removeAll() { _pendingStateChangeCommands.clear(); - for (const auto& ma : _managedAssets) { - _pendingStateChangeCommands[ma.path] = Asset::State::Unloaded; + std::vector> allAssets = + _assetLoader->rootAsset()->requestedAssets(); + + for (const auto& a : allAssets) { + _pendingStateChangeCommands[a->assetFilePath()] = false; } } -std::vector> AssetManager::loadedAssets() { - std::vector> assets; - assets.reserve(_managedAssets.size()); - for (auto ma : _managedAssets) { - if (ma.asset != nullptr) { - assets.push_back(ma.asset); - } - } - return assets; +std::shared_ptr AssetManager::rootAsset() { + return _assetLoader->rootAsset(); } scripting::LuaLibrary AssetManager::luaLibrary() { return { - "", + "asset", { + // Functions for adding/removing assets { - "loadAsset", - &luascriptfunctions::loadAsset, + "add", + &luascriptfunctions::asset::add, {this}, "string", "" }, { - "synchronizeAsset", - &luascriptfunctions::synchronizeAsset, + "remove", + &luascriptfunctions::asset::remove, + {this}, + "string", + "" + }, + // Functions for managing assets + { + "reload", + &luascriptfunctions::asset::reload, {this}, "string", "" }, { - "initializeAsset", - &luascriptfunctions::initializeAsset, - { this }, + "synchronize", + &luascriptfunctions::asset::synchronize, + {this}, "string", "" }, { - "unloadAsset", - &luascriptfunctions::unloadAsset, - { this }, + "resynchronize", + &luascriptfunctions::asset::resynchronize, + {this}, "string", "" - } + }, + { + "cancelSynchronization", + &luascriptfunctions::asset::cancelSynchronization, + {this}, + "string", + "" + }, } }; } @@ -316,40 +321,14 @@ void AssetManager::unloadAsset(Asset* asset) { } -std::shared_ptr AssetManager::tryLoadAsset(const std::string& path) { - /* - std::shared_ptr asset; - try { - asset = _assetLoader->loadAsset(path); - } catch (const ghoul::RuntimeError& e) { - LERROR(e.component << ": " << e.message); - } - if (asset == nullptr) { - LERROR("Could not load asset from " << path); - _managedAssets.push_back(ManagedAsset{ - path, - nullptr, - Asset::State::LoadingFailed - }); - return nullptr; - } - const auto it = std::find_if( - _managedAssets.begin(), - _managedAssets.end(), - [&asset](const ManagedAsset& ma){ - return ma.asset == asset; - } - ); - if (it == _managedAssets.end()) { - _managedAssets.push_back(ManagedAsset{ - path, - asset, - AssetState::Loaded - }); - return asset; - } */ +std::shared_ptr AssetManager::tryAddAsset(const std::string& path) { + _assetLoader->add(path); return nullptr; - +} + +bool AssetManager::tryRemoveAsset(const std::string& path) { + _assetLoader->remove(path); + return false; } bool AssetManager::tryInitializeAsset(Asset& asset) { diff --git a/src/scene/assetmanager_lua.inl b/src/scene/assetmanager_lua.inl index 81e16427ef..71eb9c2b79 100644 --- a/src/scene/assetmanager_lua.inl +++ b/src/scene/assetmanager_lua.inl @@ -22,58 +22,57 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -namespace openspace::luascriptfunctions { +namespace openspace::luascriptfunctions::asset { -int loadAsset(lua_State* state) { +int add(lua_State* state) { AssetManager *assetManager = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); int nArguments = lua_gettop(state); - SCRIPT_CHECK_ARGUMENTS("loadAsset", state, 1, nArguments); - + SCRIPT_CHECK_ARGUMENTS("add", state, 1, nArguments); std::string assetName = luaL_checkstring(state, -1); - - assetManager->setTargetAssetState(assetName, Asset::State::Loaded); + assetManager->add(assetName); return 0; } -int synchronizeAsset(lua_State* state) { +int remove(lua_State* state) { AssetManager *assetManager = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); int nArguments = lua_gettop(state); - SCRIPT_CHECK_ARGUMENTS("synchronizeAsset", state, 1, nArguments); - + SCRIPT_CHECK_ARGUMENTS("remove", state, 1, nArguments); std::string assetName = luaL_checkstring(state, -1); - - assetManager->setTargetAssetState(assetName, Asset::State::SyncResolved); + assetManager->remove(assetName); return 0; } - -int initializeAsset(lua_State* state) { +int removeAll(lua_State* state) { AssetManager *assetManager = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); int nArguments = lua_gettop(state); - SCRIPT_CHECK_ARGUMENTS("initializeAsset", state, 1, nArguments); - - std::string assetName = luaL_checkstring(state, -1); - - assetManager->setTargetAssetState(assetName, Asset::State::Initialized); + SCRIPT_CHECK_ARGUMENTS("removeAll", state, 0, nArguments); + assetManager->removeAll(); return 0; } -int unloadAsset(lua_State* state) { - AssetManager *assetManager = - reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int reload(lua_State* state) { + return 0; +} - int nArguments = lua_gettop(state); - SCRIPT_CHECK_ARGUMENTS("unloadAsset", state, 1, nArguments); +int synchronize(lua_State* state) { + return 0; +} - std::string assetName = luaL_checkstring(state, -1); +int resynchronize(lua_State* state) { + return 0; +} - assetManager->setTargetAssetState(assetName, Asset::State::Unloaded); +int initialize(lua_State* state) { + return 0; +} + +int cancelSynchronization(lua_State* state) { return 0; }