mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-06 19:39:56 -05:00
Work on asset management
This commit is contained in:
@@ -78,21 +78,15 @@ public:
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
|
||||
bool hasRequiredDependency(const Asset* asset) const;
|
||||
void addRequiredDependency(std::shared_ptr<Asset> asset);
|
||||
void removeRequiredDependency(Asset* asset);
|
||||
void removeRequiredDependency(const std::string& assetId);
|
||||
bool hasDependency(const Asset* asset) const;
|
||||
void addDependency(std::shared_ptr<Asset> asset);
|
||||
void removeDependency(Asset* asset);
|
||||
void removeDependency(const std::string& assetId);
|
||||
std::vector<std::shared_ptr<Asset>> dependencies();
|
||||
|
||||
bool hasDependants() const;
|
||||
bool hasInitializedDependants() const;
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> optionalAssets() const;
|
||||
bool hasOptionalDependency(const Asset* asset) const;
|
||||
bool hasEnabledOptionalDependency(const Asset* asset) const;
|
||||
void setOptionalDependencyEnabled(Asset* asset, bool enabled);
|
||||
void addOptionalDependency(std::shared_ptr<Asset> asset, bool enabled);
|
||||
void removeOptionalDependency(Asset* asset);
|
||||
|
||||
std::string resolveLocalResource(std::string resourceName);
|
||||
std::string resolveSyncedResource(std::string resourceName);
|
||||
private:
|
||||
@@ -107,17 +101,11 @@ private:
|
||||
// Absolute path to asset file
|
||||
std::string _assetPath;
|
||||
|
||||
// Required dependencies
|
||||
std::vector<std::shared_ptr<Asset>> _requiredDependencies;
|
||||
// Dependencies
|
||||
std::vector<std::shared_ptr<Asset>> _dependencies;
|
||||
|
||||
// Assets that refers to this asset as an required dependency
|
||||
std::vector<std::weak_ptr<Asset>> _requiredDependants;
|
||||
|
||||
// Optional dependencies
|
||||
std::vector<Optional> _optionalDependencies;
|
||||
|
||||
// Assets that refers to this asset as an optional dependency
|
||||
std::vector<std::weak_ptr<Asset>> _optionalDependants;
|
||||
// Assets that refers to this asset as an dependency
|
||||
std::vector<std::weak_ptr<Asset>> _dependants;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -49,8 +49,7 @@ int onDeinitialize(lua_State* state);
|
||||
int onInitializeDependency(lua_State* state);
|
||||
int onDeinitializeDependency(lua_State* state);
|
||||
int addSynchronization(lua_State* state);
|
||||
int importRequiredDependency(lua_State* state);
|
||||
int importOptionalDependency(lua_State* state);
|
||||
int importDependency(lua_State* state);
|
||||
int resolveLocalResource(lua_State* state);
|
||||
int resolveSyncedResource(lua_State* state);
|
||||
int noOperation(lua_State* state);
|
||||
@@ -74,26 +73,30 @@ public:
|
||||
~AssetLoader();
|
||||
|
||||
/**
|
||||
* Load single asset.
|
||||
* - Import one asset
|
||||
* - Unimport all other assets
|
||||
*/
|
||||
std::shared_ptr<Asset> loadSingleAsset(const std::string& identifier);
|
||||
|
||||
/**
|
||||
* Import an asset:
|
||||
* Add the asset as an optional on the root asset
|
||||
* The asset is imported synchronously
|
||||
* Load an asset:
|
||||
* Add the asset as a dependency on the root asset
|
||||
* The asset is loaded synchronously
|
||||
*/
|
||||
std::shared_ptr<Asset> loadAsset(const std::string& identifier);
|
||||
|
||||
/**
|
||||
* Unimport an asset:
|
||||
* Remove the asset as an optional on the root asset
|
||||
* The asset is unimported synchronously
|
||||
* Unload an asset:
|
||||
* Remove the asset as a dependency on the root asset
|
||||
* The asset is unloaded synchronously
|
||||
*/
|
||||
void unloadAsset(const std::string& identifier);
|
||||
|
||||
/**
|
||||
* Return true if the specified asset is loaded
|
||||
*/
|
||||
bool hasLoadedAsset(const std::string& identifier);
|
||||
|
||||
/**
|
||||
* Return all assets loaded using the loadAsset method.
|
||||
* Non-recursive (does not include imports of the loaded assets)
|
||||
*/
|
||||
std::vector<std::shared_ptr<Asset>> loadedAssets();
|
||||
|
||||
/**
|
||||
* Return the lua state
|
||||
*/
|
||||
@@ -125,8 +128,7 @@ public:
|
||||
std::string generateAssetPath(const std::string& baseDirectory, const std::string& path) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Asset> importRequiredDependency(const std::string& identifier);
|
||||
std::shared_ptr<Asset> importOptionalDependency(const std::string& identifier, bool enabled = true);
|
||||
std::shared_ptr<Asset> importDependency(const std::string& identifier);
|
||||
std::shared_ptr<Asset> importAsset(std::string path);
|
||||
std::shared_ptr<Asset> getAsset(std::string path);
|
||||
ghoul::filesystem::Directory currentDirectory();
|
||||
@@ -142,8 +144,7 @@ private:
|
||||
int onInitializeDependencyLua(Asset* dependant, Asset* dependency);
|
||||
int onDeinitializeDependencyLua(Asset* dependant, Asset* dependency);
|
||||
int addSynchronizationLua(Asset* asset);
|
||||
int importRequiredDependencyLua(Asset* asset);
|
||||
int importOptionalDependencyLua(Asset* asset);
|
||||
int importDependencyLua(Asset* asset);
|
||||
int resolveLocalResourceLua(Asset* asset);
|
||||
int resolveSyncedResourceLua(Asset* asset);
|
||||
int exportAssetLua(Asset* asset);
|
||||
@@ -154,8 +155,7 @@ private:
|
||||
friend int assetloader::onInitializeDependency(lua_State* state);
|
||||
friend int assetloader::onDeinitializeDependency(lua_State* state);
|
||||
friend int assetloader::addSynchronization(lua_State* state);
|
||||
friend int assetloader::importRequiredDependency(lua_State* state);
|
||||
friend int assetloader::importOptionalDependency(lua_State* state);
|
||||
friend int assetloader::importDependency(lua_State* state);
|
||||
friend int assetloader::resolveLocalResource(lua_State* state);
|
||||
friend int assetloader::resolveSyncedResource(lua_State* state);
|
||||
friend int assetloader::exportAsset(lua_State* state);
|
||||
|
||||
@@ -64,8 +64,8 @@ public:
|
||||
private:
|
||||
|
||||
std::unordered_map<std::string, AssetState> _pendingStateChangeCommands;
|
||||
std::unordered_set<std::string> _synchronizingAssets;
|
||||
bool _shouldClearAssets;
|
||||
std::unordered_map<std::shared_ptr<Asset>, AssetState> _stateChangesInProgress;
|
||||
std::unordered_map<std::shared_ptr<Asset>, std::unordered_set<std::shared_ptr<Asset>>> _syncAncestors;
|
||||
std::unique_ptr<AssetLoader> _assetLoader;
|
||||
std::unique_ptr<AssetSynchronizer> _assetSynchronizer;
|
||||
};
|
||||
|
||||
@@ -48,8 +48,10 @@ public:
|
||||
void addAsset(std::shared_ptr<Asset> asset);
|
||||
void removeAsset(Asset* asset);
|
||||
void syncAsset(Asset* asset);
|
||||
void syncUnsynced();
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> getSynchronizedAssets();
|
||||
|
||||
std::vector<Asset*> getRecentlySynchronizedAssets();
|
||||
private:
|
||||
enum class SynchronizationState : int {
|
||||
Added,
|
||||
|
||||
+37
-127
@@ -36,7 +36,6 @@ namespace {
|
||||
namespace openspace {
|
||||
|
||||
Asset::Asset(AssetLoader* loader)
|
||||
//: PropertyOwner({ "RootAsset", "Root asset" })
|
||||
: _readyState(Asset::ReadyState::Loaded)
|
||||
, _loader(loader)
|
||||
, _hasAssetPath(false)
|
||||
@@ -45,7 +44,6 @@ Asset::Asset(AssetLoader* loader)
|
||||
{}
|
||||
|
||||
Asset::Asset(AssetLoader* loader, ghoul::filesystem::File assetPath)
|
||||
//: PropertyOwner({ assetPath, assetPath })
|
||||
: _readyState(Asset::ReadyState::Loaded)
|
||||
, _loader(loader)
|
||||
, _hasAssetPath(true)
|
||||
@@ -87,43 +85,33 @@ std::vector<std::shared_ptr<ResourceSynchronization>> Asset::synchronizations()
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> Asset::allAssets() {
|
||||
std::set<std::shared_ptr<Asset>> assets({ shared_from_this() });
|
||||
for (auto& dep : _requiredDependencies) {
|
||||
for (auto& dep : _dependencies) {
|
||||
std::vector<std::shared_ptr<Asset>> depAssets = dep->allActiveAssets();
|
||||
std::copy(depAssets.begin(), depAssets.end(), std::inserter(assets, assets.end()));
|
||||
}
|
||||
for (auto& dep : _optionalDependencies) {
|
||||
std::vector<std::shared_ptr<Asset>> depAssets = dep.first->allActiveAssets();
|
||||
std::copy(depAssets.begin(), depAssets.end(), std::inserter(assets, assets.end()));
|
||||
}
|
||||
std::vector<std::shared_ptr<Asset>> assetVector(assets.begin(), assets.end());
|
||||
return assetVector;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Asset >> Asset::allActiveAssets() {
|
||||
std::set<std::shared_ptr<Asset>> assets({ shared_from_this() });
|
||||
for (auto& dep : _requiredDependencies) {
|
||||
for (auto& dep : _dependencies) {
|
||||
std::vector<std::shared_ptr<Asset>> depAssets = dep->allActiveAssets();
|
||||
std::copy(depAssets.begin(), depAssets.end(), std::inserter(assets, assets.end()));
|
||||
}
|
||||
for (auto& dep : _optionalDependencies) {
|
||||
if (dep.second) {
|
||||
std::vector<std::shared_ptr<Asset>> depAssets = dep.first->allActiveAssets();
|
||||
std::copy(depAssets.begin(), depAssets.end(), std::inserter(assets, assets.end()));
|
||||
}
|
||||
}
|
||||
std::vector<std::shared_ptr<Asset>> assetVector(assets.begin(), assets.end());
|
||||
return assetVector;
|
||||
}
|
||||
|
||||
bool Asset::isInitReady() const {
|
||||
// An asset is ready for initialization if all synchronizations are resolved
|
||||
// and all its required dependencies are ready for initialization.
|
||||
// and all its dependencies are ready for initialization.
|
||||
for (const std::shared_ptr<ResourceSynchronization>& sync : _synchronizations) {
|
||||
if (!sync->isResolved()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const auto& dependency : _requiredDependencies) {
|
||||
for (const auto& dependency : _dependencies) {
|
||||
if (!dependency->isInitReady()) {
|
||||
return false;
|
||||
}
|
||||
@@ -143,7 +131,7 @@ void Asset::initialize() {
|
||||
}
|
||||
|
||||
// Initialize dependencies
|
||||
for (auto& dependency : _requiredDependencies) {
|
||||
for (auto& dependency : _dependencies) {
|
||||
dependency->initialize();
|
||||
}
|
||||
|
||||
@@ -153,7 +141,7 @@ void Asset::initialize() {
|
||||
loader()->callOnInitialize(this);
|
||||
|
||||
// Notify dependencies
|
||||
for (auto& dependency : _requiredDependencies) {
|
||||
for (auto& dependency : _dependencies) {
|
||||
loader()->callOnDependantInitialize(dependency.get(), this);
|
||||
}
|
||||
}
|
||||
@@ -164,7 +152,7 @@ void Asset::deinitialize() {
|
||||
}
|
||||
|
||||
// Notify dependencies
|
||||
for (auto& dependency : _requiredDependencies) {
|
||||
for (auto& dependency : _dependencies) {
|
||||
loader()->callOnDependantDeinitialize(dependency.get(), this);
|
||||
}
|
||||
|
||||
@@ -174,7 +162,7 @@ void Asset::deinitialize() {
|
||||
_readyState = Asset::ReadyState::Loaded;
|
||||
|
||||
// Make sure no dependencies are left dangling
|
||||
for (auto& dependency : _requiredDependencies) {
|
||||
for (auto& dependency : _dependencies) {
|
||||
if (!dependency->hasInitializedDependants()) {
|
||||
dependency->deinitialize();
|
||||
}
|
||||
@@ -211,50 +199,50 @@ AssetLoader* Asset::loader() const {
|
||||
return _loader;
|
||||
}
|
||||
|
||||
bool Asset::hasRequiredDependency(const Asset* asset) const {
|
||||
bool Asset::hasDependency(const Asset* asset) const {
|
||||
const auto it = std::find_if(
|
||||
_requiredDependencies.begin(),
|
||||
_requiredDependencies.end(),
|
||||
_dependencies.begin(),
|
||||
_dependencies.end(),
|
||||
[asset](std::shared_ptr<Asset> dep) {
|
||||
return dep.get() == asset;
|
||||
}
|
||||
);
|
||||
|
||||
return it != _requiredDependencies.end();
|
||||
return it != _dependencies.end();
|
||||
}
|
||||
|
||||
void Asset::addRequiredDependency(std::shared_ptr<Asset> dependency) {
|
||||
void Asset::addDependency(std::shared_ptr<Asset> dependency) {
|
||||
if (_readyState == Asset::ReadyState::Initialized) {
|
||||
// TODO: Throw: cannot add dep while asset is initialized.
|
||||
return;
|
||||
}
|
||||
|
||||
// Do nothing if the dependency already exists.
|
||||
auto it = std::find(_requiredDependencies.begin(),
|
||||
_requiredDependencies.end(),
|
||||
auto it = std::find(_dependencies.begin(),
|
||||
_dependencies.end(),
|
||||
dependency);
|
||||
|
||||
if (it != _requiredDependencies.end()) {
|
||||
if (it != _dependencies.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_requiredDependencies.push_back(dependency);
|
||||
dependency->_requiredDependants.push_back(shared_from_this());
|
||||
_dependencies.push_back(dependency);
|
||||
dependency->_dependants.push_back(shared_from_this());
|
||||
|
||||
//addPropertySubOwner(dependency);
|
||||
}
|
||||
|
||||
void Asset::removeRequiredDependency(Asset* dependency) {
|
||||
_requiredDependencies.erase(
|
||||
std::remove_if(_requiredDependencies.begin(),
|
||||
_requiredDependencies.end(),
|
||||
void Asset::removeDependency(Asset* dependency) {
|
||||
_dependencies.erase(
|
||||
std::remove_if(_dependencies.begin(),
|
||||
_dependencies.end(),
|
||||
[dependency](std::shared_ptr<Asset> asset) {
|
||||
return asset.get() == dependency;
|
||||
}
|
||||
),
|
||||
_requiredDependencies.end()
|
||||
_dependencies.end()
|
||||
);
|
||||
std::vector<std::weak_ptr<Asset>>& dependants = dependency->_requiredDependants;
|
||||
std::vector<std::weak_ptr<Asset>>& dependants = dependency->_dependants;
|
||||
dependants.erase(
|
||||
std::remove_if(dependants.begin(), dependants.end(), [this](std::weak_ptr<Asset> asset) {
|
||||
return asset.lock().get() == this;
|
||||
@@ -267,31 +255,29 @@ void Asset::removeRequiredDependency(Asset* dependency) {
|
||||
}
|
||||
}
|
||||
|
||||
void Asset::removeRequiredDependency(const std::string& assetId) {
|
||||
void Asset::removeDependency(const std::string& assetId) {
|
||||
auto dep = std::find_if(
|
||||
_requiredDependencies.begin(),
|
||||
_requiredDependencies.end(),
|
||||
_dependencies.begin(),
|
||||
_dependencies.end(),
|
||||
[&assetId](const std::shared_ptr<Asset>& d) {
|
||||
return d->id() == assetId;
|
||||
});
|
||||
|
||||
if (dep != _requiredDependencies.end()) {
|
||||
removeRequiredDependency(dep->get());
|
||||
if (dep != _dependencies.end()) {
|
||||
removeDependency(dep->get());
|
||||
} else {
|
||||
LERROR("No such dependency '" << assetId << "'");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> Asset::dependencies() {
|
||||
return _dependencies;
|
||||
}
|
||||
|
||||
bool Asset::hasDependants() const {
|
||||
for (const auto& dependant : _requiredDependants) {
|
||||
for (const auto& dependant : _dependants) {
|
||||
std::shared_ptr<Asset> d = dependant.lock();
|
||||
if (d && d->hasRequiredDependency(this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const auto& dependant : _optionalDependants) {
|
||||
std::shared_ptr<Asset> d = dependant.lock();
|
||||
if (d && d->hasEnabledOptionalDependency(this)) {
|
||||
if (d && d->hasDependency(this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -299,18 +285,10 @@ bool Asset::hasDependants() const {
|
||||
}
|
||||
|
||||
bool Asset::hasInitializedDependants() const {
|
||||
for (const auto& dependant : _requiredDependants) {
|
||||
for (const auto& dependant : _dependants) {
|
||||
std::shared_ptr<Asset> d = dependant.lock();
|
||||
if (d && d->readyState() == Asset::ReadyState::Initialized &&
|
||||
d->hasRequiredDependency(this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const auto& dependant : _optionalDependants) {
|
||||
std::shared_ptr<Asset> d = dependant.lock();
|
||||
if (d && d->readyState() == Asset::ReadyState::Initialized &&
|
||||
d->hasEnabledOptionalDependency(this))
|
||||
d->hasDependency(this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -318,72 +296,4 @@ bool Asset::hasInitializedDependants() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> Asset::optionalAssets() const {
|
||||
std::vector<std::shared_ptr<Asset>> assets(_optionalDependencies.size());
|
||||
std::transform(
|
||||
_optionalDependencies.begin(),
|
||||
_optionalDependencies.end(),
|
||||
assets.begin(),
|
||||
[](const Optional& o) {
|
||||
return o.first;
|
||||
}
|
||||
);
|
||||
return assets;
|
||||
}
|
||||
|
||||
bool Asset::hasOptionalDependency(const Asset* asset) const {
|
||||
auto it = std::find_if(
|
||||
_optionalDependencies.begin(),
|
||||
_optionalDependencies.end(),
|
||||
[&asset](const Optional& o) {
|
||||
return o.first.get() == asset;
|
||||
}
|
||||
);
|
||||
return it != _optionalDependencies.end();
|
||||
}
|
||||
|
||||
bool Asset::hasEnabledOptionalDependency(const Asset* asset) const {
|
||||
auto it = std::find_if(
|
||||
_optionalDependencies.begin(),
|
||||
_optionalDependencies.end(),
|
||||
[&asset](const Optional& o) {
|
||||
return o.first.get() == asset && o.second;
|
||||
}
|
||||
);
|
||||
return it != _optionalDependencies.end();
|
||||
}
|
||||
|
||||
void Asset::setOptionalDependencyEnabled(Asset* asset, bool enabled) {
|
||||
auto it = std::find_if(
|
||||
_optionalDependencies.begin(),
|
||||
_optionalDependencies.end(),
|
||||
[&asset](const Optional& o) {
|
||||
return o.first.get() == asset;
|
||||
}
|
||||
);
|
||||
|
||||
if (it != _optionalDependencies.end()) {
|
||||
it->second = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void Asset::removeOptionalDependency(Asset* asset) {
|
||||
_optionalDependencies.erase(
|
||||
std::remove_if(
|
||||
_optionalDependencies.begin(),
|
||||
_optionalDependencies.end(),
|
||||
[&asset](Optional& o) {
|
||||
return o.first.get() == asset;
|
||||
}
|
||||
),
|
||||
_optionalDependencies.end()
|
||||
);
|
||||
// TODO: Update and validate
|
||||
}
|
||||
|
||||
void Asset::addOptionalDependency(std::shared_ptr<Asset> asset, bool enabled) {
|
||||
_optionalDependencies.push_back(std::make_pair(asset, enabled));
|
||||
// TODO: Update and validate
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-70
@@ -39,8 +39,7 @@
|
||||
namespace {
|
||||
const char* AssetGlobalVariableName = "asset";
|
||||
|
||||
const char* ImportRequiredDependencyFunctionName = "import";
|
||||
const char* ImportOptionalDependencyFunctionName = "importOptional";
|
||||
const char* ImportDependencyFunctionName = "import";
|
||||
const char* ExportFunctionName = "export";
|
||||
|
||||
const char* SyncedResourceFunctionName = "syncedResource";
|
||||
@@ -178,17 +177,10 @@ int AssetLoader::addSynchronizationLua(Asset* asset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<Asset> AssetLoader::importRequiredDependency(const std::string& name) {
|
||||
std::shared_ptr<Asset> AssetLoader::importDependency(const std::string& name) {
|
||||
std::shared_ptr<Asset> asset = getAsset(name);
|
||||
std::shared_ptr<Asset> dependant = _assetStack.back();
|
||||
dependant->addRequiredDependency(asset);
|
||||
return asset;
|
||||
}
|
||||
|
||||
std::shared_ptr<Asset> AssetLoader::importOptionalDependency(const std::string& name, bool enabled) {
|
||||
std::shared_ptr<Asset> asset = getAsset(name);
|
||||
std::shared_ptr<Asset> owner = _assetStack.back();
|
||||
owner->addOptionalDependency(asset, enabled);
|
||||
dependant->addDependency(asset);
|
||||
return asset;
|
||||
}
|
||||
|
||||
@@ -200,31 +192,29 @@ ghoul::filesystem::Directory AssetLoader::currentDirectory() {
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Asset> AssetLoader::loadSingleAsset(const std::string& identifier) {
|
||||
std::shared_ptr<Asset> imported = importOptionalDependency(identifier, true);
|
||||
std::vector<std::shared_ptr<Asset>> optionals = _rootAsset->optionalAssets();
|
||||
|
||||
// Remove all other optionals
|
||||
for (auto& optional : optionals) {
|
||||
if (optional != imported) {
|
||||
_rootAsset->removeOptionalDependency(optional.get());
|
||||
}
|
||||
}
|
||||
return imported;
|
||||
}
|
||||
|
||||
std::shared_ptr<Asset> AssetLoader::loadAsset(const std::string & identifier) {
|
||||
ghoul_assert(_assetStack.size() == 1, "Can only load an asset from the root asset");
|
||||
return importOptionalDependency(identifier);
|
||||
return importDependency(identifier);
|
||||
}
|
||||
|
||||
|
||||
void AssetLoader::unloadAsset(const std::string & identifier) {
|
||||
ghoul_assert(_assetStack.size() == 1, "Can only unload an asset from the root asset");
|
||||
// TODO: Implement this
|
||||
//_rootAsset->removeOptional(id);
|
||||
//_rootAsset->removeDependency(id);
|
||||
}
|
||||
|
||||
bool AssetLoader::hasLoadedAsset(const std::string & identifier) {
|
||||
const auto it = _importedAssets.find(identifier);
|
||||
if (it == _importedAsset.end()) {
|
||||
return false;
|
||||
}
|
||||
return _rootAsset->hasDependency(it->second.get());
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> AssetLoader::loadedAssets() {
|
||||
return _rootAsset->dependencies();
|
||||
}
|
||||
|
||||
ghoul::lua::LuaState* AssetLoader::luaState() {
|
||||
return _luaState;
|
||||
@@ -340,7 +330,6 @@ void AssetLoader::pushAsset(std::shared_ptr<Asset> asset) {
|
||||
| |- localResource
|
||||
| |- syncedResource
|
||||
| |- import
|
||||
| |- importOptional
|
||||
| |- export
|
||||
| |- onInitialize
|
||||
| |- onDeinitialize
|
||||
@@ -383,14 +372,8 @@ void AssetLoader::pushAsset(std::shared_ptr<Asset> asset) {
|
||||
// Register import-dependency function
|
||||
// Asset, Dependency import(string path)
|
||||
lua_pushlightuserdata(*_luaState, asset.get());
|
||||
lua_pushcclosure(*_luaState, &assetloader::importRequiredDependency, 1);
|
||||
lua_setfield(*_luaState, assetTableIndex, ImportRequiredDependencyFunctionName);
|
||||
|
||||
// Register import-optional function
|
||||
// Asset, Dependency importOptional(string path)
|
||||
lua_pushlightuserdata(*_luaState, asset.get());
|
||||
lua_pushcclosure(*_luaState, &assetloader::importOptionalDependency, 1);
|
||||
lua_setfield(*_luaState, assetTableIndex, ImportOptionalDependencyFunctionName);
|
||||
lua_pushcclosure(*_luaState, &assetloader::importDependency, 1);
|
||||
lua_setfield(*_luaState, assetTableIndex, ImportDependencyFunctionName);
|
||||
|
||||
// Register export-dependency function
|
||||
// export(string key, any value)
|
||||
@@ -452,46 +435,13 @@ void AssetLoader::updateLuaGlobals() {
|
||||
lua_setglobal(*_luaState, AssetGlobalVariableName);
|
||||
}
|
||||
|
||||
int AssetLoader::importRequiredDependencyLua(Asset* dependant) {
|
||||
int AssetLoader::importDependencyLua(Asset* dependant) {
|
||||
int nArguments = lua_gettop(*_luaState);
|
||||
SCRIPT_CHECK_ARGUMENTS("import", *_luaState, 1, nArguments);
|
||||
|
||||
std::string assetName = luaL_checkstring(*_luaState, 1);
|
||||
|
||||
std::shared_ptr<Asset> dependency = importRequiredDependency(assetName);
|
||||
|
||||
if (!dependency) {
|
||||
return luaL_error(*_luaState, "Asset '%s' not found", assetName.c_str());
|
||||
}
|
||||
|
||||
addLuaDependencyTable(dependant, dependency.get());
|
||||
|
||||
// Get the exports table
|
||||
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef);
|
||||
lua_getfield(*_luaState, -1, dependency->id().c_str());
|
||||
lua_getfield(*_luaState, -1, ExportsTableName);
|
||||
int exportsTableIndex = lua_gettop(*_luaState);
|
||||
|
||||
// Get the dependency table
|
||||
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef);
|
||||
lua_getfield(*_luaState, -1, dependency->id().c_str());
|
||||
lua_getfield(*_luaState, -1, DependantsTableName);
|
||||
lua_getfield(*_luaState, -1, dependant->id().c_str());
|
||||
int dependencyTableIndex = lua_gettop(*_luaState);
|
||||
|
||||
lua_pushvalue(*_luaState, exportsTableIndex);
|
||||
lua_pushvalue(*_luaState, dependencyTableIndex);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int AssetLoader::importOptionalDependencyLua(Asset* dependant) {
|
||||
int nArguments = lua_gettop(*_luaState);
|
||||
SCRIPT_CHECK_ARGUMENTS("importOptional", *_luaState, 2, nArguments);
|
||||
|
||||
std::string assetName = luaL_checkstring(*_luaState, 1);
|
||||
bool enabled = lua_toboolean(*_luaState, 2);
|
||||
|
||||
std::shared_ptr<Asset> dependency = importOptionalDependency(assetName, enabled);
|
||||
std::shared_ptr<Asset> dependency = importDependency(assetName);
|
||||
|
||||
if (!dependency) {
|
||||
return luaL_error(*_luaState, "Asset '%s' not found", assetName.c_str());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*****************************************************************************************
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
@@ -70,22 +70,16 @@ int onDeinitializeDependency(lua_State* state) {
|
||||
|
||||
|
||||
/**
|
||||
* Imports required dependencies
|
||||
* Imports dependencies
|
||||
* Gives access to
|
||||
* AssetTable: Exported lua values
|
||||
* Dependency: ...
|
||||
* Usage: {AssetTable, Dependency} = asset.import(string assetIdentifier)
|
||||
*/
|
||||
int importRequiredDependency(lua_State* state) {
|
||||
int importDependency(lua_State* state) {
|
||||
Asset *asset =
|
||||
reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
return asset->loader()->importRequiredDependencyLua(asset);
|
||||
}
|
||||
|
||||
int importOptionalDependency(lua_State* state) {
|
||||
Asset *asset =
|
||||
reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
return asset->loader()->importOptionalDependencyLua(asset);
|
||||
return asset->loader()->importDependencyLua(asset);
|
||||
}
|
||||
|
||||
int resolveLocalResource(lua_State* state) {
|
||||
|
||||
+62
-25
@@ -43,48 +43,85 @@ AssetManager::AssetManager(std::unique_ptr<AssetLoader> loader,
|
||||
}
|
||||
|
||||
void AssetManager::update() {
|
||||
// 1. Check clear flag.
|
||||
std::unordered_map<std::string, std::shared_ptr<Asset>> loadedAssets;
|
||||
|
||||
// Load and unload assets
|
||||
for (const auto& c : _pendingStateChangeCommands) {
|
||||
const std::string& path = c.first;
|
||||
const AssetState targetState = c.second;
|
||||
|
||||
AssetState currentState = AssetState::Unloaded;
|
||||
|
||||
const bool shouldBeLoaded = targetState != AssetState::Unloaded;
|
||||
const bool isLoaded = _assetLoader->hasLoadedAsset(path);
|
||||
|
||||
|
||||
switch (currentState) {
|
||||
case AssetState::Unloaded:
|
||||
if (_assetLoader->rootAsset)
|
||||
if (isLoaded && !shouldBeLoaded) {
|
||||
_assetLoader->unloadAsset(path);
|
||||
break;
|
||||
case AssetState::Loaded:
|
||||
_assetLoader->loadAsset(path);
|
||||
break;
|
||||
case AssetState::Synchronized:
|
||||
//_assetSynchronizer->addAsset();
|
||||
break;
|
||||
case AssetState::Initialized:
|
||||
|
||||
break;
|
||||
} else if (!isLoaded && shouldBeLoaded) {
|
||||
std::shared_ptr<Asset> loadedAsset = _assetLoader->loadAsset(path);
|
||||
loadedAssets.emplace(path, loadedAsset);
|
||||
}
|
||||
}
|
||||
|
||||
// startSynchronizations();
|
||||
// handleFinishedSynchronizations();
|
||||
// handleLoading();
|
||||
// handleInitialization();
|
||||
// Collect all assets for synchronization
|
||||
for (const auto& loadedAsset : loadedAssets) {
|
||||
const AssetState targetState = _pendingStateChangeCommands[loadedAsset.first];
|
||||
bool shouldSync = targetState == AssetState::Synchronized || targetState == AssetState::Initialized;
|
||||
|
||||
if (!shouldSync) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> importedAssets = loadedAsset.second->allAssets();
|
||||
for (const auto& a : importedAssets) {
|
||||
_assetSynchronizer->addAsset(a);
|
||||
_syncAncestors[a].insert(loadedAsset.second);
|
||||
}
|
||||
_stateChangesInProgress.emplace(
|
||||
std::make_pair(loadedAsset.second, _pendingStateChangeCommands[loadedAsset.first])
|
||||
);
|
||||
}
|
||||
|
||||
// Start asset synchronization. (Async operation)
|
||||
_assetSynchronizer->syncUnsynced();
|
||||
|
||||
// Collect finished synchronizations and initialize assets
|
||||
std::vector<std::shared_ptr<Asset>> syncedAssets = _assetSynchronizer->getSynchronizedAssets();
|
||||
for (const auto& syncedAsset : syncedAssets) {
|
||||
// Retrieve ancestors that were waiting for this asset to sync
|
||||
const auto& it = _syncAncestors.find(syncedAsset);
|
||||
if (it == _syncAncestors.end()) {
|
||||
continue; // Should not happen. (No ancestor to this synchronization)
|
||||
}
|
||||
std::unordered_set<std::shared_ptr<Asset>>& ancestors = it->second;
|
||||
|
||||
for (const auto& ancestor : ancestors) {
|
||||
const bool initReady = ancestor->isInitReady();
|
||||
const bool shouldInit = _stateChangesInProgress[ancestor] == AssetState::Initialized;
|
||||
if (initReady) {
|
||||
_stateChangesInProgress.erase(ancestor);
|
||||
if (shouldInit) {
|
||||
ancestor->initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
_syncAncestors.erase(syncedAsset);
|
||||
}
|
||||
|
||||
_pendingStateChangeCommands.clear();
|
||||
}
|
||||
|
||||
void AssetManager::setTargetAssetState(const std::string& path, AssetState targetState) {
|
||||
ghoul::filesystem::File file(absPath(path));
|
||||
std::string normalizedPath = file.path();
|
||||
// TODO: Use asset loader to normalize path?
|
||||
|
||||
_pendingStateChangeCommands[normalizedPath] = targetState;
|
||||
}
|
||||
|
||||
void AssetManager::clearAllTargetAssets() {
|
||||
_pendingStateChangeCommands.clear();
|
||||
_shouldClearAssets = true;
|
||||
for (const auto& i : _assetLoader->loadedAssets()) {
|
||||
_pendingStateChangeCommands[i->id()] = AssetState::Unloaded;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> AssetManager::allAssets()
|
||||
@@ -97,15 +134,15 @@ scripting::LuaLibrary AssetManager::luaLibrary() {
|
||||
"",
|
||||
{
|
||||
{
|
||||
"importAsset",
|
||||
&luascriptfunctions::importAsset,
|
||||
"loadAsset",
|
||||
&luascriptfunctions::loadAsset,
|
||||
{this},
|
||||
"string",
|
||||
""
|
||||
},
|
||||
{
|
||||
"unimportAsset",
|
||||
&luascriptfunctions::unimportAsset,
|
||||
&luascriptfunctions::unloadAsset,
|
||||
{this},
|
||||
"string",
|
||||
""
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace openspace::luascriptfunctions {
|
||||
|
||||
int importAsset(lua_State* state) {
|
||||
int loadAsset(lua_State* state) {
|
||||
AssetManager *assetManager =
|
||||
reinterpret_cast<AssetManager*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
|
||||
@@ -37,7 +37,7 @@ int importAsset(lua_State* state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unimportAsset(lua_State* state) {
|
||||
int unloadAsset(lua_State* state) {
|
||||
AssetManager *assetManager =
|
||||
reinterpret_cast<AssetManager*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*****************************************************************************************
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
@@ -87,7 +87,7 @@ void SceneLoader::loadScene(Scene* scene, const std::string& path) {
|
||||
|
||||
for (const std::string& key : keys) {
|
||||
std::string assetName = assetDictionary.value<std::string>(key);
|
||||
_assetLoader->importAsset(assetName);
|
||||
_assetLoader->loadAsset(assetName);
|
||||
}
|
||||
|
||||
// Sync all resources from assets that are dependencies of root asset.
|
||||
|
||||
@@ -96,17 +96,17 @@ int passTest(lua_State* state) {
|
||||
|
||||
TEST_F(AssetLoaderTest, Assertions) {
|
||||
try {
|
||||
_assetLoader->importAsset("passassertion");
|
||||
_assetLoader->loadAsset("passassertion");
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
EXPECT_TRUE(false) << e.what();
|
||||
}
|
||||
EXPECT_THROW(_assetLoader->importAsset("failassertion"), ghoul::lua::LuaRuntimeException);
|
||||
EXPECT_THROW(_assetLoader->loadAsset("failassertion"), ghoul::lua::LuaRuntimeException);
|
||||
}
|
||||
|
||||
TEST_F(AssetLoaderTest, BasicExportImport) {
|
||||
try {
|
||||
_assetLoader->importAsset("import");
|
||||
_assetLoader->loadAsset("import");
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
EXPECT_TRUE(false) << e.what();
|
||||
@@ -115,7 +115,7 @@ TEST_F(AssetLoaderTest, BasicExportImport) {
|
||||
|
||||
TEST_F(AssetLoaderTest, AssetFuncitons) {
|
||||
try {
|
||||
_assetLoader->importAsset("assetfunctionsexist");
|
||||
_assetLoader->loadAsset("assetfunctionsexist");
|
||||
} catch (const std::exception& e) {
|
||||
EXPECT_TRUE(false) << e.what();
|
||||
}
|
||||
@@ -123,7 +123,7 @@ TEST_F(AssetLoaderTest, AssetFuncitons) {
|
||||
|
||||
TEST_F(AssetLoaderTest, DependencyFuncitons) {
|
||||
try {
|
||||
_assetLoader->importAsset("dependencyfunctionsexist");
|
||||
_assetLoader->loadAsset("dependencyfunctionsexist");
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
EXPECT_TRUE(false) << e.what();
|
||||
@@ -132,7 +132,7 @@ TEST_F(AssetLoaderTest, DependencyFuncitons) {
|
||||
|
||||
TEST_F(AssetLoaderTest, AssetInitialization) {
|
||||
try {
|
||||
std::shared_ptr<openspace::Asset> asset = _assetLoader->loadSingleAsset("initialization");
|
||||
std::shared_ptr<openspace::Asset> asset = _assetLoader->loadAsset("initialization");
|
||||
asset->initialize();
|
||||
EXPECT_TRUE(passed());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user