Work on asset management

This commit is contained in:
Emil Axelsson
2017-09-18 18:13:20 +02:00
parent 8a30251fcb
commit f4901fa4cf
10 changed files with 259 additions and 97 deletions

View File

@@ -617,6 +617,8 @@ void OpenSpaceEngine::loadSingleAsset(const std::string& assetPath) {
}
}
_assetLoader->synchronizeEnabledAssets();
_renderEngine->setGlobalBlackOutFactor(0.0);
_renderEngine->startFading(1, 3.0);

View File

@@ -31,22 +31,25 @@
namespace {
const char* _loggerCat = "Asset";
bool isRelative(std::string path) {
if (path.size() > 2) {
if (path[0] == '.' && path[1] == '/') return true;
}
if (path.size() > 3) {
if (path[0] == '.' && path[1] == '.' && path[2] == '/') return true;
}
return false;
};
const char* AssetFileSuffix = "asset";
}
namespace openspace {
Asset::Asset(AssetLoader* loader)
//: PropertyOwner({ "RootAsset", "Root asset" })
: _readyState(Asset::ReadyState::Loaded)
, _loader(loader)
, _assetName("Root Asset")
{}
Asset::Asset(AssetLoader* loader, ghoul::filesystem::File assetPath)
//: PropertyOwner({ assetPath, assetPath })
: _readyState(Asset::ReadyState::Loaded)
, _loader(loader)
, _assetPath(assetPath)
{}
std::string Asset::resolveLocalResource(std::string resourceName) {
std::string currentAssetDirectory = assetDirectory();
return currentAssetDirectory + ghoul::filesystem::FileSystem::PathSeparator + resourceName;
@@ -54,7 +57,7 @@ std::string Asset::resolveLocalResource(std::string resourceName) {
std::string Asset::syncDirectory() const {
std::string currentAssetDirectory = assetDirectory();
std::string rootAssetDirectory = loader()->rootAsset()->assetDirectory();
std::string rootAssetDirectory = loader()->syncRootDirectory();
std::string relativePath = FileSys.relativePath(currentAssetDirectory, rootAssetDirectory);
return loader()->syncRootDirectory() +
@@ -82,6 +85,36 @@ bool Asset::isInitReady() const {
return true;
}
void Asset::synchronizeEnabledRecursive() {
synchronize();
for (Asset* a : _dependencies) {
a->synchronizeEnabledRecursive();
}
for (Optional& o : _optionals) {
if (o.second) {
o.first->synchronizeEnabledRecursive();
}
}
}
void Asset::synchronize() {
LDEBUG("Synchronizing asset " << id());
if (_readyState != Asset::ReadyState::Loaded) {
// Already synchronized or synchronizing
return;
}
// Initialize dependencies
for (auto& dependency : _dependencies) {
dependency->synchronize();
}
loader()->callOnSynchronize(this);
}
void Asset::initialize() {
LDEBUG("Initializing asset " << id());
if (_readyState == Asset::ReadyState::Initialized) {
@@ -90,6 +123,7 @@ void Asset::initialize() {
if (!isInitReady()) {
// TODO: THROW
return;
}
// Initialize dependencies
@@ -137,65 +171,27 @@ std::string Asset::resolveSyncedResource(std::string resourceName) {
resourceName;
}
Asset::Asset(AssetLoader* loader, ghoul::filesystem::Directory directory)
//: PropertyOwner({ "RootAsset", "Root asset" })
: _assetDirectory(directory)
, _loader(loader)
, _readyState(Asset::ReadyState::Loaded)
{
_id = generateAssetId(directory, "");
}
Asset::Asset(AssetLoader* loader, ghoul::filesystem::Directory baseDirectory, std::string assetPath)
//: PropertyOwner({ assetPath, assetPath })
: _readyState(Asset::ReadyState::Loaded)
, _loader(loader)
{
if (isRelative(assetPath)) {
ghoul::filesystem::File assetFile =
static_cast<std::string>(baseDirectory) +
ghoul::filesystem::FileSystem::PathSeparator +
assetPath +
"." +
AssetFileSuffix;
_assetDirectory = assetFile.directoryName();
_assetName = assetFile.baseName();
} else {
std::string assetRoot = ghoul::filesystem::Directory(loader->rootAsset()->assetDirectory());
ghoul::filesystem::File assetFile =
assetRoot +
ghoul::filesystem::FileSystem::PathSeparator +
assetPath +
"." +
AssetFileSuffix;
_assetDirectory = assetFile.directoryName();
_assetName = assetFile.baseName();
}
_id = generateAssetId(_assetDirectory, _assetName);
std::string Asset::id() const {
return _assetPath.has_value() ? _assetPath.value() : "";
}
std::string Asset::assetFilePath() const {
//ghoul::filesystem::File dir(_assetDirectory);
return _assetDirectory + ghoul::filesystem::FileSystem::PathSeparator + _assetName + "." + AssetFileSuffix;
return _assetPath.value();
}
std::string Asset::generateAssetId(std::string directory, std::string name) {
return directory + ghoul::filesystem::FileSystem::PathSeparator + name;
bool Asset::hasAssetFile() const {
return _assetPath.has_value();
}
std::string Asset::assetDirectory() const {
return ghoul::filesystem::File(_assetPath.value()).directoryName();
}
std::string Asset::assetName() const {
return _assetName;
}
std::string Asset::assetDirectory() const {
return _assetDirectory;
}
std::string Asset::id() const {
return _id;
}
AssetLoader* Asset::loader() const {
return _loader;

View File

@@ -45,6 +45,9 @@ namespace {
const char* SyncedResourceFunctionName = "syncedResource";
const char* LocalResourceFunctionName = "localResource";
const char* OnSynchronizeFunctionName = "onSynchronize";
const char* OnInitializeFunctionName = "onInitialize";
const char* OnDeinitializeFunctionName = "onDeinitialize";
@@ -52,6 +55,18 @@ namespace {
const char* DependantsTableName = "_dependants";
const char* _loggerCat = "AssetLoader";
const char* AssetFileSuffix = "asset";
bool isRelative(std::string path) {
if (path.size() > 2) {
if (path[0] == '.' && path[1] == '/') return true;
}
if (path.size() > 3) {
if (path[0] == '.' && path[1] == '.' && path[2] == '/') return true;
}
return false;
};
}
namespace openspace {
@@ -118,20 +133,34 @@ int resolveSyncedResource(lua_State* state) {
return asset->loader()->resolveSyncedResourceLua(asset);
}
int onFinishSynchronization(lua_State* state) {
Asset* asset =
reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
return asset->loader()->onFinishSynchronizationLua(asset);
}
int noOperation(lua_State* state) {
return 0;
}
int noSynchronization(lua_State* state) {
int nArguments = lua_gettop(state);
// Todo: call onFinish.
return 0;
}
} // namespace assetloader
AssetLoader::AssetLoader(
ghoul::lua::LuaState& luaState,
ResourceSynchronizer& resourceSynchronizer,
std::string assetRoot,
std::string assetRootDirectory,
std::string syncRootDirectory
)
: _luaState(&luaState)
, _rootAsset(std::make_unique<Asset>(this, std::move(assetRoot)))
, _rootAsset(std::make_unique<Asset>(this))
, _assetRootDirectory(assetRootDirectory)
, _syncRootDirectory(std::move(syncRootDirectory))
, _resourceSynchronizer(&resourceSynchronizer)
{
@@ -142,9 +171,8 @@ AssetLoader::AssetLoader(
lua_setglobal(*_luaState, AssetsTableName);
}
Asset* AssetLoader::loadAsset(std::string name) {
ghoul::filesystem::Directory directory = currentDirectory();
std::unique_ptr<Asset> asset = std::make_unique<Asset>(this, directory, name);
Asset* AssetLoader::loadAsset(std::string path) {
std::unique_ptr<Asset> asset = std::make_unique<Asset>(this, path);
Asset* rawAsset = asset.get();
@@ -153,7 +181,6 @@ Asset* AssetLoader::loadAsset(std::string name) {
popAsset();
});
const std::string path = asset->assetFilePath();
if (!FileSys.fileExists(path)) {
throw ghoul::FileNotFoundError(path);
}
@@ -175,19 +202,48 @@ Asset* AssetLoader::loadAsset(std::string name) {
return rawAsset;
}
std::string AssetLoader::generateAssetPath(const std::string& baseDirectory, const std::string& assetPath) const {
if (isRelative(assetPath)) {
ghoul::filesystem::File assetFile =
static_cast<std::string>(baseDirectory) +
ghoul::filesystem::FileSystem::PathSeparator +
assetPath +
"." +
AssetFileSuffix;
return assetFile.path();
}
else {
std::string assetRoot = ghoul::filesystem::Directory(_assetRootDirectory);
ghoul::filesystem::File assetFile =
assetRoot +
ghoul::filesystem::FileSystem::PathSeparator +
assetPath +
"." +
AssetFileSuffix;
return assetFile.path();
}
}
Asset* AssetLoader::getAsset(std::string name) {
ghoul::filesystem::Directory directory = currentDirectory();
std::string assetId = Asset::generateAssetId(directory, name);
std::string path = generateAssetPath(directory, name);
// Check if asset is already loaded.
const auto it = _importedAssets.find(assetId);
const auto it = _importedAssets.find(path);
const bool loaded = it != _importedAssets.end();
return loaded ? it->second.get() : loadAsset(name);
return loaded ? it->second.get() : loadAsset(path);
}
Asset* AssetLoader::importDependency(const std::string& name) {
Asset* asset = getAsset(name);
if (!asset) {
// TODO: Throw
return nullptr;
}
Asset* dependant = _assetStack.back();
dependant->addDependency(asset);
return asset;
@@ -195,13 +251,25 @@ Asset* AssetLoader::importDependency(const std::string& name) {
Asset* AssetLoader::importOptional(const std::string& name, bool enabled) {
Asset* asset = getAsset(name);
if (!asset) {
// TODO: Throw
return nullptr;
}
Asset* owner = _assetStack.back();
owner->addOptional(asset, enabled);
return asset;
}
ghoul::filesystem::Directory AssetLoader::currentDirectory() {
return _assetStack.back()->assetDirectory();
if (_assetStack.back()->hasAssetFile()) {
return _assetStack.back()->assetDirectory();
} else {
return _assetRootDirectory;
}
}
void AssetLoader::synchronizeEnabledAssets() {
_rootAsset->synchronizeEnabledRecursive();
}
void AssetLoader::loadSingleAsset(const std::string& identifier) {
@@ -219,7 +287,7 @@ void AssetLoader::loadSingleAsset(const std::string& identifier) {
void AssetLoader::importAsset(const std::string & identifier) {
ghoul_assert(_assetStack.size() == 1, "Can only import an asset from the root asset");
try {
importAsset(identifier);
importOptional(identifier);
}
catch (const ghoul::RuntimeError& e) {
LERROR("Error loading asset '" << identifier << "': " << e.message);
@@ -231,11 +299,7 @@ void AssetLoader::unimportAsset(const std::string & identifier) {
ghoul_assert(_assetStack.size() == 1, "Can only unimport an asset from the root asset");
ghoul::filesystem::Directory directory = currentDirectory();
Asset tempAsset(this, directory, identifier);
const std::string id = tempAsset.id();
_rootAsset->removeDependency(id);
//_rootAsset->removeOptional(id);
}
@@ -251,6 +315,25 @@ const std::string& AssetLoader::syncRootDirectory() {
return _syncRootDirectory;
}
void AssetLoader::callOnSynchronize(Asset* asset) {
if (asset == _rootAsset.get()) {
return;
}
lua_getglobal(*_luaState, AssetsTableName);
lua_getfield(*_luaState, -1, asset->id().c_str());
lua_getfield(*_luaState, -1, OnSynchronizeFunctionName);
// onSynchronize(function<void(bool)> onFinish)
lua_pushlightuserdata(*_luaState, asset);
lua_pushcclosure(*_luaState, &assetloader::onFinishSynchronization, 1);
const int status = lua_pcall(*_luaState, 1, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaExecutionException(lua_tostring(*_luaState, -1));
}
}
void AssetLoader::callOnInitialize(Asset * asset) {
if (asset == _rootAsset.get()) {
return;
@@ -308,6 +391,10 @@ void AssetLoader::callOnDependantDeinitialize(Asset* asset, Asset* dependant) {
}
}
void AssetLoader::synchronizeResource(const ghoul::Dictionary & d, std::function<void(bool)> onFinish) {
onFinish(true);
}
int AssetLoader::resolveLocalResourceLua(Asset* asset) {
int nArguments = lua_gettop(*_luaState);
@@ -335,6 +422,11 @@ int AssetLoader::resolveSyncedResourceLua(Asset* asset) {
return 1;
}
int AssetLoader::onFinishSynchronizationLua(Asset* asset) {
LINFO("Finished syncing resource!" << asset->id());
return 0;
}
void AssetLoader::pushAsset(Asset* asset) {
_assetStack.push_back(asset);
@@ -370,7 +462,12 @@ void AssetLoader::pushAsset(Asset* asset) {
lua_pushcclosure(*_luaState, &assetloader::importOptional, 1);
lua_setfield(*_luaState, assetTableIndex, ImportOptionalFunctionName);
// Register default onDeinitialize function
// Register default onSynchronize function
lua_pushlightuserdata(*_luaState, this);
lua_pushcclosure(*_luaState, &assetloader::noSynchronization, 1);
lua_setfield(*_luaState, assetTableIndex, OnSynchronizeFunctionName);
// Register default onInitialize function
lua_pushcfunction(*_luaState, &assetloader::noOperation);
lua_setfield(*_luaState, assetTableIndex, OnInitializeFunctionName);
@@ -483,6 +580,13 @@ scripting::LuaLibrary AssetLoader::luaLibrary() {
"string",
""
},
{
"synchronizeResource",
&luascriptfunctions::synchronizeResource,
{ this },
"table, function",
""
},
}
};
}

View File

@@ -22,7 +22,6 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
namespace openspace {
namespace luascriptfunctions {
@@ -52,5 +51,33 @@ int unimportAsset(lua_State* state) {
return 0;
}
int synchronizeResource(lua_State* state) {
AssetLoader *assetLoader =
reinterpret_cast<AssetLoader*>(lua_touserdata(state, lua_upvalueindex(1)));
int nArguments = lua_gettop(state);
SCRIPT_CHECK_ARGUMENTS("addSynchronization", state, 2, nArguments);
int referenceIndex = luaL_ref(state, LUA_REGISTRYINDEX);
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(state, d);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERRORC("addSceneGraphNode", e.what());
return luaL_error(state, "Error loading dictionary from lua state");
}
assetLoader->synchronizeResource(d, [state, referenceIndex](bool success) {
lua_rawgeti(state, LUA_REGISTRYINDEX, referenceIndex);
lua_pushboolean(state, success ? 1 : 0);
lua_pcall(state, 1, 0, 0);
luaL_unref(state, LUA_REGISTRYINDEX, referenceIndex);
});
}
}
}