Prepare for data sync

This commit is contained in:
Emil Axelsson
2017-09-14 20:16:51 +02:00
parent 4cdae984e9
commit af8bec1441
20 changed files with 925 additions and 604 deletions
+9
View File
@@ -1,3 +1,12 @@
asset.registerSynchronizations = function (asset, syncs)
local oldSync = asset.onSync;
asset.onSynchronize = function()
for i, sync in ipairs(syncs) do
openspace.addSynchronization(asset, sync)
end
end
end
asset.registerSceneGraphNodes = function (sceneAsset, nodes)
local oldInit = sceneAsset.onInitialize;
sceneAsset.onInitialize = function ()
+5 -8
View File
@@ -1,15 +1,12 @@
local assetHelper = asset.import("assethelper")
local transforms = asset.import("./transforms")
asset.data = {
FileRequest = {
{
Destination = asset.syncedResource("textures"),
Identifier = "earth_textures",
Version = 2
}
assetHelper.registerSynchronization(asset, {
{
Type = "HTTPSynchronization",
--- todo...
}
}
})
asset.Earth = {
Name = "Earth",
+7 -5
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -42,6 +42,7 @@ namespace ghoul::fontrendering { class FontManager; }
namespace openspace {
class AssetLoader;
class ConfigurationManager;
class DownloadManager;
class GUI;
@@ -50,14 +51,13 @@ class ModuleEngine;
class NetworkEngine;
class ParallelConnection;
class RenderEngine;
class SettingsEngine;
class VirtualPropertyManager;
class ResourceSynchronizer;
class Scene;
class AssetLoader;
class SceneLoader;
class SyncEngine;
class SettingsEngine;
class TimeManager;
class VirtualPropertyManager;
class WindowWrapper;
namespace interaction {
@@ -122,6 +122,7 @@ public:
TimeManager& timeManager();
WindowWrapper& windowWrapper();
AssetLoader& assetLoader();
ResourceSynchronizer& resourceSynchronizer();
ghoul::fontrendering::FontManager& fontManager();
interaction::NavigationHandler& navigationHandler();
interaction::KeyBindingManager& keyBindingManager();
@@ -201,6 +202,7 @@ private:
std::unique_ptr<ghoul::fontrendering::FontManager> _fontManager;
std::unique_ptr<interaction::NavigationHandler> _navigationHandler;
std::unique_ptr<interaction::KeyBindingManager> _keyBindingManager;
std::unique_ptr<ResourceSynchronizer> _resourceSynchronizer;
std::unique_ptr<scripting::ScriptEngine> _scriptEngine;
std::unique_ptr<scripting::ScriptScheduler> _scriptScheduler;
std::unique_ptr<VirtualPropertyManager> _virtualPropertyManager;
+127
View File
@@ -0,0 +1,127 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___ASSET___H__
#define __OPENSPACE_CORE___ASSET___H__
#include <openspace/properties/property.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalarproperty.h>
#include <ghoul/filesystem/filesystem.h>
#include <string>
#include <vector>
namespace openspace {
class AssetLoader;
class Asset : public properties::PropertyOwner {
public:
struct Optional : public properties::PropertyOwner {
public:
Optional(Asset* asset, Asset* owner, bool enabled = false);
private:
properties::BoolProperty _enabled;
Asset* asset;
};
enum class ReadyState : unsigned int {
Loaded,
Synchronizing,
Synchronized,
Initialized
};
/**
* Root asset constructor
*/
Asset(AssetLoader* loader, ghoul::filesystem::Directory directory);
/**
* Dependency or Optional constructor
*/
Asset(AssetLoader* loader, ghoul::filesystem::Directory baseDirectory, std::string assetPath);
std::string id();
std::string assetFilePath();
std::string assetName();
std::string assetDirectory();
AssetLoader* loader();
std::string syncDirectory();
ReadyState readyState();
bool isInitReady() const;
void initialize();
void deinitialize();
bool hasDependency(Asset* asset);
void addDependency(Asset* asset);
void removeDependency(Asset* asset);
void removeDependency(const std::string& assetId);
bool hasDependants();
bool hasInitializedDependants();
bool hasOptional(Asset* asset);
bool setOptionalEnabled(Asset* asset, bool enabled);
bool addOptional(Asset* asset, bool enabled);
bool removeOptional(Asset* asset);
void dependantDidInitialize(Asset* dependant);
void dependantWillDeinitialize(Asset* dependant);
void optionalDidInitialize(Asset* optional);
void optionalWillDeinitialize(Asset* optional);
bool shouldSynchronize();
bool shouldInitialize();
private:
std::string resolveLocalResource(std::string resourceName);
std::string resolveSyncedResource(std::string resourceName);
ReadyState _readyState;
AssetLoader* _loader;
// Base name of .asset file
std::string _assetName;
// Asbolute path to directory with the .asset file
std::string _assetDirectory;
// Asset dependencies
std::vector<Asset*> _dependencies;
// Asset dependants
std::vector<Asset*> _dependants;
// Optional sub-assets
std::vector<Optional> _optionalAssets;
// Assets that refers to this asset as an optional
std::vector<Asset*> _optionalOwners;
};
} // namespace openspace
#endif // __OPENSPACE_CORE___ASSET__H__
+61 -92
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -28,9 +28,7 @@
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/properties/property.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalarproperty.h>
#include <openspace/util/resourcesynchronizer.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/lua/luastate.h>
@@ -43,109 +41,79 @@
namespace openspace {
class Asset;
namespace assetloader {
int importAsset(lua_State* state);
int importAssetToggle(lua_State* state);
int importDependency(lua_State* state);
int importOptional(lua_State* state);
int resolveLocalResource(lua_State* state);
int resolveSyncedResource(lua_State* state);
} // namespace assetloader
class AssetLoader {
public:
class Asset;
/**
* Constructor
*/
AssetLoader(
ghoul::lua::LuaState& luaState,
ResourceSynchronizer& resourceSynchronizer,
std::string assetRoot,
std::string syncRoot
);
using InitializationRequirement = ghoul::Boolean;
using Dependency = std::pair<Asset*, InitializationRequirement>;
class DependencyToggle : public properties::PropertyOwner {
public:
DependencyToggle(Asset* dependency, Asset* dependant, bool enabled = false);
private:
properties::BoolProperty _enabled;
Asset* _dependant;
Asset* _dependency;
};
class Asset : public properties::PropertyOwner {
public:
Asset(AssetLoader* loader, ghoul::filesystem::Directory directory);
Asset(AssetLoader* loader, ghoul::filesystem::Directory baseDirectory, std::string assetPath);
std::string id();
std::string assetFilePath();
std::string assetName();
std::string assetDirectory();
AssetLoader* loader();
ghoul::Dictionary syncDictionary();
std::string syncDirectory();
bool isInitialized();
bool hasLuaTable();
void initialize();
void deinitialize();
bool hasDependency(Asset* asset, InitializationRequirement initReq);
void addDependency(Asset* asset, bool togglableInitReq, InitializationRequirement initReq);
void setInitializationRequirement(Asset* dependency, InitializationRequirement initReq);
void removeDependency(Asset* asset);
void removeDependency(const std::string& assetId);
void dependantDidInitialize(Asset* dependant);
void dependantWillDeinitialize(Asset* dependant);
bool hasInitializedDependants(InitializationRequirement initReq);
bool hasDependant(InitializationRequirement initReq);
private:
std::string resolveLocalResource(std::string resourceName);
std::string resolveSyncedResource(std::string resourceName);
// lua methods
friend int assetloader::resolveLocalResource(lua_State* state);
int resolveLocalResourceLua();
friend int assetloader::resolveSyncedResource(lua_State* state);
int resolveSyncedResourceLua();
bool _hasLuaTable;
bool _initialized;
AssetLoader* _loader;
// Base name of .asset file
std::string _assetName;
// Asbolute path to directory with the .asset file
std::string _assetDirectory;
// Other assets that this asset depend on
std::vector<Dependency> _dependencies;
// Other assets that depend on this asset
std::vector<Asset*> _dependants;
std::vector<std::unique_ptr<DependencyToggle>> _dependencyToggles;
// Other assets that this asset may toggle
//std::vector<Asset*> _toggles;
// Other assets that may toggle this asset
//std::vector<Asset*> _togglers;
};
AssetLoader(ghoul::lua::LuaState* _luaState, std::string assetRoot, std::string syncRoot);
/**
* Destructor
*/
~AssetLoader() = default;
/**
* Import an asset
* Add the asset as an optional on the root asset
*/
void importAsset(const std::string& identifier);
void loadAsset(const std::string& identifier);
void unloadAsset(const std::string& identifier);
/**
* Unimport an asset
* Remove the asset as an optional on the root asset
*/
void unimportAsset(const std::string& identifier);
/**
* Return the lua library
*/
scripting::LuaLibrary luaLibrary();
/**
* Return the lua state
*/
ghoul::lua::LuaState* luaState();
ghoul::filesystem::Directory currentDirectory();
/**
* Return the root asset
*/
Asset* rootAsset();
const std::string& syncRoot();
/**
* Return the sync root directory
*/
const std::string& syncRootDirectory();
void callOnInitialize(Asset* asset);
void callOnDeinitialize(Asset* asset);
void callOnDependantInitialize(Asset* asset, Asset* dependant);
void callOnDependantDeinitialize(Asset* asset, Asset* dependant);
private:
Asset* importAsset(
const std::string& identifier,
bool togglableInitializationRequirement = false,
bool toggleOn = true);
Asset* importDependency(const std::string& identifier);
Asset* importOptional(const std::string& identifier, bool enabled = true);
Asset* loadAsset(std::string name);
Asset* getAsset(std::string name);
ghoul::filesystem::Directory currentDirectory();
void pushAsset(Asset* asset);
void popAsset();
@@ -155,10 +123,11 @@ private:
std::map<std::string, std::unique_ptr<Asset>> _importedAssets;
std::vector<Asset*> _assetStack;
std::string _syncRoot;
ResourceSynchronizer* _resourceSynchronizer;
std::string _syncRootDirectory;
friend int assetloader::importAsset(lua_State* state);
friend int assetloader::importAssetToggle(lua_State* state);
friend int assetloader::importDependency(lua_State* state);
friend int assetloader::importOptional(lua_State* state);
int importAssetLua(
std::string assetName,
bool togglableInitializationRequirement = false,
+136
View File
@@ -0,0 +1,136 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___ASYNCHTTPREQUEST___H__
#define __OPENSPACE_CORE___ASYNCHTTPREQUEST___H__
#include <future>
#include <string>
namespace openspace {
class AsncHttpRequestData {
public:
std::chrono::system_clock::time_point startTime();
std::chrono::system_clock::time_point finishTime();
private:
std::chrono::system_clock::time_point _startTime;
std::chrono::system_clock::time_point _finishTime;
};
class AsyncHttpRequest {
public:
enum class ReadyState : unsigned int {
Unsent,
Loading,
Done
};
using StateChangeCallback = std::function<void(ReadyState)>;
using ProgressCallback = std::function<void(float)>;
using DataCallback = std::function<void(char*, size_t)>;
AsyncHttpRequest(
std::string url,
DataCallback dataCallback);
~AsyncHttpRequest();
virtual std::future<AsncHttpRequestData> start(
StateChangeCallback stateChangeCallback,
ProgressCallback progressCallback);
void wait();
std::chrono::system_clock::duration timeElapsed();
std::chrono::system_clock::duration estimatedTimeRemaining();
float progress();
ReadyState readyState();
private:
std::chrono::system_clock::time_point startTime;
float _progress;
};
//////
class AsncHttpDownloadData : public AsncHttpRequestData {
public:
std::string url();
private:
std::string _url;
};
class AsyncHttpDownload : public AsyncHttpRequest {
public:
AsyncHttpDownload(
std::string url,
std::string path);
virtual ~AsyncHttpDownload();
/*std::future<AsncHttpDownloadData> start(
StateChangeCallback stateChangeCallback,
ProgressCallback progressCallback) override;*/
};
////
class AsyncHttpReadData : public AsncHttpRequestData {
public:
std::vector<char>& buffer();
private:
std::vector<char> _buffer;
};
class AsyncHttpRead : public AsyncHttpRequest {
public:
AsyncHttpRead(std::string url);
~AsyncHttpRead();
/*std::future<AsncHttpReadData> start(
StateChangeCallback stateChangeCallback,
ProgressCallback progressCallback) override;*/
};
} // namespace openspace
#endif // __OPENSPACE_CORE___ASYNCHTTPREQUEST___H__
/*
// start
std::ostream file();
AsyncHttpDownload d(url, file);
std::future<AsyncHttpDownloadData> data = d->start(progressCallback, progressCallback);
// in event loop
AsyncHttpRequest::ReadyState status = d.readyState();
if (status == AsyncHttpRequest::ReadyState::Loading) {
float progress = d.progress();
// update some progress bar..
}
// usage:
HTTPDownload ();
*/
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -32,12 +32,6 @@
namespace openspace {
struct SynchronizationProduct {
ghoul::filesystem::Directory destination;
std::string folderName;
};
using SynchronizationJob = Job<SynchronizationProduct>;
class ResourceSynchronization {
public:
@@ -45,7 +39,6 @@ public:
ResourceSynchronization() = default;
virtual bool needsSync() = 0;
virtual std::shared_ptr<SynchronizationJob> createSynchronizationJob() = 0;
};
@@ -0,0 +1,40 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
#define __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
#include <openspace/util/resourcesynchronization.h>
#include <openspace/util/concurrentjobmanager.h>
namespace openspace {
class ResourceSynchronizer {
};
} // namespace openspace
#endif // __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
@@ -240,6 +240,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
{
"loadWMSCapabilities",
&globebrowsing::luascriptfunctions::loadWMSCapabilities,
{},
"string, string, string",
"Loads and parses the WMS capabilities xml file from a remote server. "
"The first argument is the name of the capabilities that can be used to "
@@ -250,6 +251,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
{
"removeWMSServer",
&globebrowsing::luascriptfunctions::removeWMSServer,
{},
"string",
"Removes the WMS server identified by the first argument from the list "
"of available servers. The parameter corrsponds to the first argument in "
@@ -258,6 +260,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
{
"capabilitiesWMS",
&globebrowsing::luascriptfunctions::capabilities,
{},
"string",
"Returns an array of tables that describe the available layers that are "
"supported by the WMS server identified by the provided name. The 'URL'"
+4 -2
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -39,7 +39,9 @@
namespace openspace {
SyncModule::SyncModule() : OpenSpaceModule(Name) {}
SyncModule::SyncModule()
: OpenSpaceModule(Name)
{}
void SyncModule::internalInitialize() {
+1 -1
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
+5 -22
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -24,40 +24,23 @@
#include "httpsynchronization.h"
#include <openspace/util/asynchttprequest.h>
namespace openspace {
HttpSynchronization::HttpSynchronization(const ghoul::Dictionary& dict)
: openspace::ResourceSynchronization()
{
}
bool HttpSynchronization::needsSync() {
return true;
}
std::shared_ptr<SynchronizationJob> HttpSynchronization::createSynchronizationJob() {
return std::make_shared<HttpSynchronizationJob>();
}
documentation::Documentation HttpSynchronization::Documentation() {
return {};
}
HttpSynchronizationJob::HttpSynchronizationJob() {
}
HttpSynchronizationJob::~HttpSynchronizationJob() {
}
void HttpSynchronizationJob::execute() {
}
std::shared_ptr<SynchronizationProduct> HttpSynchronizationJob::product() {
return nullptr;
}
} // namespace openspace
+2 -11
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -36,19 +36,10 @@ class HttpSynchronization : public ResourceSynchronization {
public:
HttpSynchronization(const ghoul::Dictionary& dict);
bool needsSync() override;
std::shared_ptr<SynchronizationJob> createSynchronizationJob() override;
void start();
static documentation::Documentation Documentation();
};
class HttpSynchronizationJob : public SynchronizationJob {
public:
HttpSynchronizationJob();
virtual ~HttpSynchronizationJob();
void execute() override;
std::shared_ptr<SynchronizationProduct> product() override;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_SYNC___HTTPSYNCHRONIZATION___H__
+5
View File
@@ -126,6 +126,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/rendering/renderengine_lua.inl
${OPENSPACE_BASE_DIR}/src/rendering/screenspacerenderable.cpp
${OPENSPACE_BASE_DIR}/src/rendering/transferfunction.cpp
${OPENSPACE_BASE_DIR}/src/scene/asset.cpp
${OPENSPACE_BASE_DIR}/src/scene/assetloader_lua.inl
${OPENSPACE_BASE_DIR}/src/scene/assetloader.cpp
${OPENSPACE_BASE_DIR}/src/scene/translation.cpp
@@ -153,6 +154,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/util/powerscaledscalar.cpp
${OPENSPACE_BASE_DIR}/src/util/powerscaledsphere.cpp
${OPENSPACE_BASE_DIR}/src/util/progressbar.cpp
${OPENSPACE_BASE_DIR}/src/util/resourcesynchronizer.cpp
${OPENSPACE_BASE_DIR}/src/util/screenlog.cpp
${OPENSPACE_BASE_DIR}/src/util/spicemanager.cpp
${OPENSPACE_BASE_DIR}/src/util/spicemanager_lua.inl
@@ -283,6 +285,7 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/rendering/screenspacerenderable.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/volumeraycaster.h
${OPENSPACE_BASE_DIR}/include/openspace/rendering/transferfunction.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/asset.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/assetloader.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/translation.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/rotation.h
@@ -311,6 +314,8 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/util/powerscaledscalar.h
${OPENSPACE_BASE_DIR}/include/openspace/util/powerscaledsphere.h
${OPENSPACE_BASE_DIR}/include/openspace/util/progressbar.h
${OPENSPACE_BASE_DIR}/include/openspace/util/resourcesynchronization.h
${OPENSPACE_BASE_DIR}/include/openspace/util/resourcesynchronizer.h
${OPENSPACE_BASE_DIR}/include/openspace/util/screenlog.h
${OPENSPACE_BASE_DIR}/include/openspace/util/spicemanager.h
${OPENSPACE_BASE_DIR}/include/openspace/util/syncbuffer.h
+11 -4
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -54,11 +54,12 @@
#include <openspace/util/resourcesynchronization.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/task.h>
#include <openspace/util/openspacemodule.h>
#include <openspace/util/resourcesynchronizer.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/task.h>
#include <openspace/util/time.h>
#include <openspace/util/timemanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/transformationmanager.h>
#include <ghoul/ghoul.h>
@@ -144,6 +145,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
, _networkEngine(new NetworkEngine)
, _parallelConnection(new ParallelConnection)
, _renderEngine(new RenderEngine)
, _resourceSynchronizer(new ResourceSynchronizer(8))
, _settingsEngine(new SettingsEngine)
, _syncEngine(std::make_unique<SyncEngine>(4096))
, _timeManager(new TimeManager)
@@ -409,7 +411,7 @@ void OpenSpaceEngine::create(int argc, char** argv,
// Set up asset loader and scene loader
_engine->_assetLoader = std::make_unique<AssetLoader>(
OsEng.scriptEngine().luaState(), "${ASSETS}", "${SYNC}");
*OsEng.scriptEngine().luaState(), OsEng.resourceSynchronizer(), "${ASSETS}", "${SYNC}");
_engine->_sceneLoader = std::make_unique<SceneLoader>(_engine->_assetLoader.get());
_engine->_globalPropertyNamespace->addPropertySubOwner(_engine->_assetLoader->rootAsset());
}
@@ -1473,6 +1475,11 @@ AssetLoader & OpenSpaceEngine::assetLoader() {
return *_assetLoader;
}
ResourceSynchronizer & OpenSpaceEngine::resourceSynchronizer() {
ghoul_assert(_resourceSynchronizer, "Resource Synchronizer must not be nullptr");
return *_resourceSynchronizer;
}
ghoul::fontrendering::FontManager& OpenSpaceEngine::fontManager() {
ghoul_assert(_fontManager, "Font Manager must not be nullptr");
return *_fontManager;
+288
View File
@@ -0,0 +1,288 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/scene/asset.h>
#include <openspace/scene/assetloader.h>
#include <algorithm>
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;
};
}
namespace openspace {
std::string Asset::resolveLocalResource(std::string resourceName) {
std::string currentAssetDirectory = assetDirectory();
return currentAssetDirectory + ghoul::filesystem::FileSystem::PathSeparator + resourceName;
}
std::string Asset::syncDirectory() {
std::string currentAssetDirectory = assetDirectory();
std::string rootAssetDirectory = loader()->rootAsset()->assetDirectory();
std::string relativePath = FileSys.relativePath(currentAssetDirectory, rootAssetDirectory);
return loader()->syncRootDirectory() +
ghoul::filesystem::FileSystem::PathSeparator +
relativePath +
ghoul::filesystem::FileSystem::PathSeparator +
assetName();
}
Asset::ReadyState Asset::readyState() {
return _readyState;
}
bool Asset::isInitReady() const {
// An asset is ready for initialization if it is synchronized
// and all its dependencies are ready for initialization.
if (_readyState != Asset::ReadyState::Synchronized) {
return false;
}
for (const auto& dependency : _dependencies) {
if (!dependency->isInitReady()) {
return false;
}
}
return true;
}
void Asset::initialize() {
LDEBUG("Initializing asset " << id());
if (_readyState == Asset::ReadyState::Initialized) {
return;
}
if (!isInitReady()) {
// TODO: THROW
}
// Initialize dependencies
for (auto& dependency : _dependencies) {
dependency->initialize();
}
_readyState = Asset::ReadyState::Initialized;
// Call onInitialize in Lua
loader()->callOnInitialize(this);
// Notify dependencies
for (auto& dependency : _dependencies) {
dependency->dependantDidInitialize(this);
}
}
void Asset::deinitialize() {
if (_readyState != Asset::ReadyState::Initialized) {
return;
}
// Notify dependencies
for (auto& dependency : _dependencies) {
dependency->dependantWillDeinitialize(this);
}
// Call onDeinitialize in Lua
loader()->callOnDeinitialize(this);
_readyState = Asset::ReadyState::Synchronized;
// Make sure no dependencies are left dangling
for (auto& dependency : _dependencies) {
if (!dependency->hasInitializedDependants()) {
dependency->deinitialize();
}
}
}
std::string Asset::resolveSyncedResource(std::string resourceName) {
return syncDirectory() +
ghoul::filesystem::FileSystem::PathSeparator +
resourceName;
}
Asset::Asset(AssetLoader* loader, ghoul::filesystem::Directory directory)
: PropertyOwner({ "RootAsset", "Root asset" })
, _assetDirectory(directory)
, _loader(loader)
, _readyState(Asset::ReadyState::Loaded)
{}
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();
}
}
std::string Asset::assetFilePath() {
ghoul::filesystem::File dir(_assetDirectory);
return _assetDirectory + ghoul::filesystem::FileSystem::PathSeparator + _assetName + "." + AssetFileSuffix;
}
std::string Asset::assetName() {
return _assetName;
}
std::string Asset::assetDirectory() {
return _assetDirectory;
}
std::string Asset::id() {
return assetFilePath();
}
AssetLoader* Asset::loader() {
return _loader;
}
bool Asset::hasDependency(Asset* asset) {
auto it = std::find(_dependencies.begin(), _dependencies.end(), dependency);
return it != _dependencies.end();
}
void Asset::addDependency(Asset* dependency) {
if (readyState == Initialized) {
// TODO: Throw: cannot add dep while asset is initialized.
return;
}
// Do nothing if the dependency already exists.
auto it = std::find(_dependencies.begin(), _dependencies.end(), dependency);
if (it != _dependencies.end()) {
return;
}
_dependencies.push_back(dependency);
dependency->_dependants.push_back(this);
addPropertySubOwner(dependency);
}
void Asset::removeDependency(Asset* dependency) {
_dependencies.erase(
std::remove(_dependencies.begin(), _dependencies.end(), dependency),
_dependencies.end()
);
std::vector<Asset*>& dependants = dependency->_dependants;
dependants.erase(
std::remove(dependants.begin(), dependants.end(), this),
dependants.end()
);
if (!dependency->hasInitializedDependants()) {
dependency->deinitialize();
}
}
void Asset::removeDependency(const std::string& assetId) {
auto dep = std::find_if(_dependencies.begin(), _dependencies.end(), [&assetId](const Asset& d) {
return d.id() == assetId;
});
if (dep != _dependencies.end()) {
removeDependency(dep);
} else {
LERROR("No such dependency '" << assetId << "'");
}
}
void Asset::dependantDidInitialize(Asset* dependant) {
loader()->callOnDependantInitialize(this, dependant);
}
void Asset::dependantWillDeinitialize(Asset* dependant) {
loader()->callOnDependantDeinitialize(this, dependant);
}
bool Asset::hasDependants() {
bool foundDep = false;
for (auto& dependant : _dependants) {
if (dependant->hasDependency(this)) {
foundDep = true;
}
}
return foundDep;
}
bool Asset::hasInitializedDependants() {
bool foundInitializedDep = false;
for (auto& dependant : _dependants) {
if (dependant->isInitialized() && dependant->hasDependency(this)) {
foundInitializedDep = true;
}
}
return foundInitializedDep;
}
// Dependency toggle
Asset::Optional::Optional(Asset* asset, Asset* owner, bool enabled)
: PropertyOwner({ dependency->name(), dependency->name() })
, _enabled({ "enabled", "Enabled", "Enable optional" }, enabled)
, _asset(asset)
, _owner(owner)
{
addProperty(_enabled);
addPropertySubOwner(asset);
_enabled.onChange([this]() {
_owner->setOptionalEnabled(
asset,
_enabled
);
});
}
}
+197 -433
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -24,6 +24,7 @@
#include <openspace/scene/assetloader.h>
#include <openspace/scene/asset.h>
#include <openspace/scripting/script_helper.h>
#include <ghoul/lua/ghoul_lua.h>
@@ -42,7 +43,8 @@ namespace {
const char* SyncTableName = "sync";
const char* ImportFunctionName = "import";
const char* ImportToggleFunctionName = "importToggle";
const char* ImportOptionalFunctionName = "importOptional";
const char* SyncedResourceFunctionName = "syncedResource";
const char* LocalResourceFunctionName = "localResource";
const char* OnInitializeFunctionName = "onInitialize";
@@ -52,24 +54,15 @@ namespace {
const char* DependantsTableName = "_dependants";
const char* _loggerCat = "AssetLoader";
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 {
namespace assetloader {
int importAsset(lua_State* state) {
AssetLoader *assetLoader = (AssetLoader*)lua_touserdata(state, lua_upvalueindex(1));
int importDependency(lua_State* state) {
AssetLoader *assetLoader =
reinterpret_cast<AssetLoader*>(lua_touserdata(state, lua_upvalueindex(1)));
int nArguments = lua_gettop(state);
if (nArguments != 1) {
@@ -79,38 +72,52 @@ int importAsset(lua_State* state) {
std::string assetName = luaL_checkstring(state, 1);
try {
return assetLoader->importAssetLua(assetName, false, false);
return assetLoader->importDependencyLua(assetName);
} catch (const ghoul::RuntimeError& e) {
return luaL_error(state, "Failed to import asset '%s'. %s: %s", assetName.c_str(), e.message.c_str(), e.component.c_str());
return luaL_error(
state,
"Failed to import asset '%s'. %s: %s",
assetName.c_str(),
e.message.c_str(),
e.component.c_str()
);
}
}
int importAssetToggle(lua_State* state) {
AssetLoader *assetLoader = (AssetLoader*)lua_touserdata(state, lua_upvalueindex(1));
int importOptional(lua_State* state) {
AssetLoader *assetLoader =
reinterpret_cast<AssetLoader*>(lua_touserdata(state, lua_upvalueindex(1)));
int nArguments = lua_gettop(state);
if (nArguments != 2) {
return luaL_error(state, "Expected 2 arguments, got %i", nArguments);
}
bool toggleEnabled = lua_toboolean(state, 2);
std::string assetName = luaL_checkstring(state, 1);
bool enabled = lua_toboolean(state, 2);
try {
return assetLoader->importAssetLua(assetName, true, toggleEnabled);
return assetLoader->importOptionalLua(assetName, enabled);
} catch (const ghoul::RuntimeError& e) {
return luaL_error(state, "Failed to import asset '%s'. %s: %s", assetName.c_str(), e.message.c_str(), e.component.c_str());
return luaL_error(
state,
"Failed to import optional asset '%s'. %s: %s",
assetName.c_str(),
e.message.c_str(),
e.component.c_str());
}
}
int resolveLocalResource(lua_State* state) {
AssetLoader::Asset* asset = (AssetLoader::Asset*)lua_touserdata(state, lua_upvalueindex(1));
return asset->resolveLocalResourceLua();
Asset* asset =
reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
return asset->loader()->resolveLocalResourceLua(asset);
}
int resolveSyncedResource(lua_State* state) {
AssetLoader::Asset* asset = (AssetLoader::Asset*)lua_touserdata(state, lua_upvalueindex(1));
return asset->resolveSyncedResourceLua();
Asset* asset =
reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
return asset->loader()->resolveSyncedResourceLua(asset);
}
int noOperation(lua_State* state) {
@@ -119,10 +126,16 @@ int noOperation(lua_State* state) {
} // namespace assetloader
AssetLoader::AssetLoader(ghoul::lua::LuaState* luaState, std::string assetRoot, std::string syncRoot)
: _luaState(luaState)
AssetLoader::AssetLoader(
ghoul::lua::LuaState& luaState,
ResourceSynchronizer& resourceSynchronizer,
std::string assetRoot,
std::string syncRootDirectory
)
: _luaState(&luaState)
, _rootAsset(std::make_unique<Asset>(this, std::move(assetRoot)))
, _syncRoot(std::move(syncRoot))
, _syncRootDirectory(std::move(syncRootDirectory))
, _resourceSynchronizer(&resourceSynchronizer)
{
pushAsset(_rootAsset.get());
@@ -131,50 +144,24 @@ AssetLoader::AssetLoader(ghoul::lua::LuaState* luaState, std::string assetRoot,
lua_setglobal(*_luaState, AssetsTableName);
}
AssetLoader::Asset* AssetLoader::importAsset(
const std::string& name,
bool togglableInitializationRequirement,
bool toggleOn)
{
Asset* AssetLoader::loadAsset(std::string name) {
ghoul::filesystem::Directory directory = currentDirectory();
std::unique_ptr<Asset> newAsset = std::make_unique<Asset>(this, directory, name);
const std::string id = newAsset->id();
std::unique_ptr<Asset> asset = std::make_unique<Asset>(this, directory, name);
Asset* asset = newAsset.get();
// Check if asset is already loaded.
const auto it = _importedAssets.find(id);
const bool loaded = it != _importedAssets.end();
if (loaded) {
asset = it->second.get();
}
InitializationRequirement reqInit = InitializationRequirement::Yes;
if (togglableInitializationRequirement && !toggleOn) {
reqInit = InitializationRequirement::No;
}
Asset* dependant = _assetStack.back();
dependant->addDependency(asset, togglableInitializationRequirement, reqInit);
if (loaded) {
return asset;
}
pushAsset(asset);
ghoul::OnScopeExit e([this]() {
popAsset();
});
const std::string path = asset->assetFilePath();
if (!FileSys.fileExists(path)) {
throw ghoul::FileNotFoundError(path);
}
// Actually loading asset.
pushAsset(asset);
ghoul::OnScopeExit e([this]() {
popAsset();
});
try {
ghoul::lua::runScriptFile(*_luaState, path);
} catch (const ghoul::lua::LuaRuntimeException& e) {
}
catch (const ghoul::lua::LuaRuntimeException& e) {
LERROR(e.message);
return nullptr;
}
@@ -183,19 +170,43 @@ AssetLoader::Asset* AssetLoader::importAsset(
return nullptr;
}
LDEBUG("Imported asset " << asset->id());
_importedAssets.emplace(id, std::move(newAsset));
Asset* rawAsset = asset.get();
_importedAssets.emplace(id, std::move(asset));
return _importedAssets[id].get();
return rawAsset;
}
Asset* AssetLoader::getAsset(std::string name) {
ghoul::filesystem::Directory directory = currentDirectory();
std::string assetId = generateAssetId(directory, name);
// Check if asset is already loaded.
const auto it = _importedAssets.find(assetId);
const bool loaded = it != _importedAssets.end();
return loaded ? it->second.get() : loadAsset(name);
}
AssetLoader::Asset* AssetLoader::importDependency(const std::string& name) {
Asset* asset = getAsset(name);
Asset* dependant = _assetStack.back();
dependant->addDependency(asset);
return asset;
}
AssetLoader::Asset* AssetLoader::importOptional(const std::string& name, bool enabled) {
Asset* asset = getAsset(name);
Asset* owner = _assetStack.back();
owner->addOptional(asset, enabled);
return asset;
}
ghoul::filesystem::Directory AssetLoader::currentDirectory() {
return _assetStack.back()->assetDirectory();
}
void AssetLoader::loadAsset(const std::string & identifier) {
ghoul_assert(_assetStack.size() == 1, "Can only load an asset from the root asset");
void AssetLoader::importAsset(const std::string & identifier) {
ghoul_assert(_assetStack.size() == 1, "Can only import an asset from the root asset");
try {
importAsset(identifier);
}
@@ -205,8 +216,8 @@ void AssetLoader::loadAsset(const std::string & identifier) {
}
void AssetLoader::unloadAsset(const std::string & identifier) {
ghoul_assert(_assetStack.size() == 1, "Can only unload an asset from the root asset");
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);
@@ -225,8 +236,92 @@ AssetLoader::Asset* AssetLoader::rootAsset() {
return _rootAsset.get();
}
const std::string& AssetLoader::syncRoot() {
return _syncRoot;
const std::string& AssetLoader::syncRootDirectory() {
return _syncRootDirectory;
}
void AssetLoader::callOnInitialize(Asset * asset) {
if (asset == _rootAsset.get()) {
return;
}
lua_getglobal(*_luaState, AssetsTableName);
lua_getfield(*_luaState, -1, asset->id().c_str());
lua_getfield(*_luaState, -1, OnInitializeFunctionName);
const int status = lua_pcall(*_luaState, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaExecutionException(lua_tostring(*state, -1));
}
}
void AssetLoader::callOnDeinitialize(Asset* asset) {
if (asset == _rootAsset.get()) {
return;
}
lua_getglobal(*_luaState, AssetsTableName);
lua_getfield(*_luaState, -1, asset->id().c_str());
lua_getfield(*_luaState, -1, OnDeinitializeFunctionName);
const int status = lua_pcall(*_luaState, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaExecutionException(lua_tostring(*state, -1));
}
}
void AssetLoader::callOnDependantInitialize(Asset* asset, Asset* dependant) {
if (asset == _rootAsset.get()) {
return;
}
lua_getglobal(*_luaState, AssetsTableName);
lua_getfield(*_luaState, -1, asset->id().c_str());
lua_getfield(*_luaState, -1, DependantsTableName);
lua_getfield(*_luaState, -1, dependant->id().c_str());
lua_getfield(*_luaState, -1, OnInitializeFunctionName);
const int status = lua_pcall(*_luaState, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaLoadingException(lua_tostring(*state, -1));
}
}
void AssetLoader::callOnDependantDeinitialize(Asset* asset, Asset* dependant) {
if (asset == _rootAsset.get()) {
return;
}
lua_getglobal(*_luaState, AssetsTableName);
lua_getfield(*_luaState, -1, asset->id().c_str());
lua_getfield(*_luaState, -1, DependantsTableName);
lua_getfield(*_luaState, -1, dependant->id().c_str());
lua_getfield(*_luaState, -1, OnDeinitializeFunctionName);
const int status = lua_pcall(*_luaState, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaLoadingException(lua_tostring(*state, -1));
}
}
int AssetLoader::resolveLocalResourceLua(Asset* asset) {
int nArguments = lua_gettop(*state);
if (nArguments != 1) {
return luaL_error(*state, "Expected %i arguments, got %i", 1, nArguments);
}
std::string resourceName = luaL_checkstring(*_luaState, -1);
std::string resolved = asset->resolveLocalResource(resourceName);
lua_pushstring(*state, resolved.c_str());
return 1;
}
int AssetLoader::resolveSyncedResourceLua(Asset* asset) {
int nArguments = lua_gettop(*state);
if (nArguments != 1) {
return luaL_error(*state, "Expected %i arguments, got %i", 1, nArguments);
}
std::string resourceName = luaL_checkstring(*_luaState, -1);
std::string resolved = asset->resolveSyncedResource(resourceName);
lua_pushstring(*state, resolved.c_str());
return 1;
}
void AssetLoader::pushAsset(Asset* asset) {
@@ -254,14 +349,14 @@ void AssetLoader::pushAsset(Asset* asset) {
lua_pushcclosure(*_luaState, &assetloader::resolveSyncedResource, 1);
lua_setfield(*_luaState, assetTableIndex, SyncedResourceFunctionName);
// Register import function
lua_pushlightuserdata(*_luaState, asset->loader());
lua_pushcclosure(*_luaState, &assetloader::importAsset, 1);
// Register import-dependency function
lua_pushlightuserdata(*_luaState, this);
lua_pushcclosure(*_luaState, &assetloader::importDependency, 1);
lua_setfield(*_luaState, assetTableIndex, ImportFunctionName);
// Register importToggle function
lua_pushlightuserdata(*_luaState, asset->loader());
lua_pushcclosure(*_luaState, &assetloader::importAssetToggle, 1);
// Register import-optional function
lua_pushlightuserdata(*_luaState, this);
lua_pushcclosure(*_luaState, &assetloader::importOptional, 1);
lua_setfield(*_luaState, assetTableIndex, ImportToggleFunctionName);
// Register default onDeinitialize function
@@ -301,13 +396,29 @@ void AssetLoader::updateLuaGlobals() {
lua_setglobal(*_luaState, AssetGlobalVariableName);
}
int AssetLoader::importAssetLua(std::string assetName, bool togglableInitializationRequirement, bool toggleEnabled) {
int AssetLoader::importDependencyLua(std::string assetName) {
Asset* importer = _assetStack.back();
Asset* importedAsset = importAsset(assetName, togglableInitializationRequirement, toggleEnabled);
Asset* importedAsset = importDependency(assetName, toggleEnabled);
if (!importedAsset) {
return luaL_error(*_luaState, "Asset '%s' not found", assetName.c_str());
}
return createLuaTableEntries(importer, importedAsset);
}
int AssetLoader::importOptionalLua(std::string assetName, bool enabled) {
Asset* importer = _assetStack.back();
Asset* importedAsset = importOptional(assetName, enabled);
if (!importedAsset) {
return luaL_error(*_luaState, "Asset '%s' not found", assetName.c_str());
}
return createLuaTableEntries(importer, importedAsset);
}
void AssetLoader::createAssetLuaTableEntries(Asset* importer, Asset* importedAsset) {
const std::string importerId = importer->id();
const std::string importedAssetId = importedAsset->id();
@@ -348,15 +459,15 @@ scripting::LuaLibrary AssetLoader::luaLibrary() {
"",
{
{
"loadAsset",
&luascriptfunctions::loadAsset,
"importAsset",
&luascriptfunctions::importAsset,
{this},
"string",
""
},
{
"unloadAsset",
&luascriptfunctions::unloadAsset,
"unimportAsset",
&luascriptfunctions::unimportAsset,
{this},
"string",
""
@@ -365,351 +476,4 @@ scripting::LuaLibrary AssetLoader::luaLibrary() {
};
}
// Asset methods.
std::string AssetLoader::Asset::resolveLocalResource(std::string resourceName) {
std::string currentAssetDirectory = assetDirectory();
return currentAssetDirectory + ghoul::filesystem::FileSystem::PathSeparator + resourceName;
}
std::string AssetLoader::Asset::syncDirectory() {
std::string currentAssetDirectory = assetDirectory();
std::string rootAssetDirectory = loader()->rootAsset()->assetDirectory();
std::string relativePath = FileSys.relativePath(currentAssetDirectory, rootAssetDirectory);
return loader()->syncRoot() +
ghoul::filesystem::FileSystem::PathSeparator +
relativePath +
ghoul::filesystem::FileSystem::PathSeparator +
assetName();
}
bool AssetLoader::Asset::isInitialized() {
return _initialized;
}
bool AssetLoader::Asset::hasLuaTable() {
return _hasLuaTable;
}
void AssetLoader::Asset::initialize() {
LDEBUG("Initializing asset " << id());
if (_initialized) {
return;
}
// Initialize dependencies
for (auto& dependency : _dependencies) {
dependency.first->initialize();
}
_initialized = true;
// Call onInitialize
if (_hasLuaTable) {
ghoul::lua::LuaState* state = loader()->luaState();
lua_getglobal(*state, AssetsTableName);
lua_getfield(*state, -1, id().c_str());
lua_getfield(*state, -1, OnInitializeFunctionName);
const int status = lua_pcall(*state, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaExecutionException(lua_tostring(*state, -1));
}
}
// Notify dependencies
for (auto& dependency : _dependencies) {
dependency.first->dependantDidInitialize(this);
}
}
void AssetLoader::Asset::deinitialize() {
if (!_initialized) {
return;
}
// Notify dependencies
for (auto& dependency : _dependencies) {
dependency.first->dependantWillDeinitialize(this);
}
// Call onDeinitialize
if (_hasLuaTable) {
ghoul::lua::LuaState* state = loader()->luaState();
lua_getglobal(*state, AssetsTableName);
lua_getfield(*state, -1, id().c_str());
lua_getfield(*state, -1, OnDeinitializeFunctionName);
const int status = lua_pcall(*state, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaExecutionException(lua_tostring(*state, -1));
}
}
_initialized = false;
// Make sure no dependencies are left dangling
for (auto& dependency : _dependencies) {
if (!dependency.first->hasInitializedDependants(InitializationRequirement::Yes)) {
dependency.first->deinitialize();
}
}
}
std::string AssetLoader::Asset::resolveSyncedResource(std::string resourceName) {
return syncDirectory() +
ghoul::filesystem::FileSystem::PathSeparator +
resourceName;
}
int AssetLoader::Asset::resolveLocalResourceLua() {
ghoul::lua::LuaState* state = loader()->luaState();
int nArguments = lua_gettop(*state);
if (nArguments != 1) {
return luaL_error(*state, "Expected %i arguments, got %i", 1, nArguments);
}
std::string resourceName = luaL_checkstring(*state, -1);
std::string resolved = resolveLocalResource(resourceName);
lua_pushstring(*state, resolved.c_str());
return 1;
}
int AssetLoader::Asset::resolveSyncedResourceLua() {
ghoul::lua::LuaState* state = loader()->luaState();
int nArguments = lua_gettop(*state);
if (nArguments != 1) {
return luaL_error(*state, "Expected %i arguments, got %i", 1, nArguments);
}
std::string resourceName = luaL_checkstring(*state, -1);
std::string resolved = resolveSyncedResource(resourceName);
lua_pushstring(*state, resolved.c_str());
return 1;
}
AssetLoader::Asset::Asset(AssetLoader* loader, ghoul::filesystem::Directory directory)
: PropertyOwner({ "RootAsset", "Root asset" })
, _assetDirectory(directory)
, _loader(loader)
, _initialized(false)
, _hasLuaTable(false)
{}
AssetLoader::Asset::Asset(AssetLoader* loader, ghoul::filesystem::Directory baseDirectory, std::string assetPath)
: PropertyOwner({ assetPath, assetPath })
, _initialized(false)
, _hasLuaTable(true)
, _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();
}
}
std::string AssetLoader::Asset::assetFilePath() {
ghoul::filesystem::File dir(_assetDirectory);
return _assetDirectory + ghoul::filesystem::FileSystem::PathSeparator + _assetName + "." + AssetFileSuffix;
}
std::string AssetLoader::Asset::assetName() {
return _assetName;
}
std::string AssetLoader::Asset::assetDirectory() {
return _assetDirectory;
}
std::string AssetLoader::Asset::id() {
return assetFilePath();
}
AssetLoader* AssetLoader::Asset::loader() {
return _loader;
}
ghoul::Dictionary AssetLoader::Asset::syncDictionary() {
ghoul::lua::LuaState* state = loader()->luaState();
lua_getglobal(*state, AssetsTableName);
lua_getfield(*state, -1, id().c_str());
lua_getfield(*state, -1, SyncTableName);
ghoul::Dictionary dictionary;
ghoul::lua::luaDictionaryFromState(*state, dictionary);
return dictionary;
}
bool AssetLoader::Asset::hasDependency(Asset* asset, InitializationRequirement initReq) {
auto it = std::find_if(_dependencies.begin(), _dependencies.end(), [asset](const Dependency& d) {
return d.first == asset;
});
if (it == _dependencies.end()) {
return false;
}
return initReq ? (it->second == true) : true;
}
void AssetLoader::Asset::addDependency(Asset* dependency, bool togglableInitReq, InitializationRequirement initReq) {
// Do nothing if the dependency already exists.
auto it = std::find_if(_dependencies.begin(), _dependencies.end(), [dependency](const Dependency& d) {
return d.first == dependency;
});
if (it != _dependencies.end()) {
return;
}
if (_initialized && initReq) {
dependency->initialize();
}
_dependencies.push_back(std::make_pair(dependency, initReq));
dependency->_dependants.push_back(this);
if (togglableInitReq) {
std::unique_ptr<DependencyToggle> dt = std::make_unique<DependencyToggle>(dependency, this, initReq);
addPropertySubOwner(dt.get());
_dependencyToggles.push_back(std::move(dt));
} else {
addPropertySubOwner(dependency);
}
}
void AssetLoader::Asset::setInitializationRequirement(Asset* dependency, InitializationRequirement initReq) {
auto it = std::find_if(_dependencies.begin(), _dependencies.end(), [dependency](const Dependency& d) {
return d.first == dependency;
});
if (it == _dependencies.end()) {
LERROR("The dependency does not exist");
}
it->second = initReq;
if (_initialized && initReq) {
dependency->initialize();
dependency->dependantDidInitialize(this);
}
if (!initReq && !dependency->hasInitializedDependants(InitializationRequirement::Yes)) {
dependency->dependantWillDeinitialize(this);
dependency->deinitialize();
}
}
void AssetLoader::Asset::removeDependency(Asset * dependency) {
_dependencies.erase(
std::remove_if(_dependencies.begin(), _dependencies.end(), [dependency](const Dependency& d) {
return d.first == dependency;
}),
_dependencies.end()
);
std::vector<Asset*>& dependants = dependency->_dependants;
dependants.erase(
std::remove(dependants.begin(), dependants.end(), this),
dependants.end()
);
if (!dependency->hasInitializedDependants(InitializationRequirement::No)) {
dependency->deinitialize();
}
}
void AssetLoader::Asset::removeDependency(const std::string& assetId) {
auto dep = std::find_if(_dependencies.begin(), _dependencies.end(), [&assetId](const Dependency& d) {
return d.first->id() == assetId;
});
if (dep != _dependencies.end()) {
removeDependency(dep->first);
} else {
LERROR("No such dependency '" << assetId << "'");
}
}
void AssetLoader::Asset::dependantDidInitialize(Asset* dependant) {
if (dependant->_hasLuaTable) {
ghoul::lua::LuaState* state = _loader->luaState();
lua_getglobal(*state, AssetsTableName);
lua_getfield(*state, -1, id().c_str());
lua_getfield(*state, -1, DependantsTableName);
lua_getfield(*state, -1, dependant->id().c_str());
lua_getfield(*state, -1, OnInitializeFunctionName);
const int status = lua_pcall(*state, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaLoadingException(lua_tostring(*state, -1));
}
}
}
void AssetLoader::Asset::dependantWillDeinitialize(Asset* dependant) {
if (dependant->_hasLuaTable) {
ghoul::lua::LuaState* state = _loader->luaState();
lua_getglobal(*state, AssetsTableName);
lua_getfield(*state, -1, id().c_str());
lua_getfield(*state, -1, DependantsTableName);
lua_getfield(*state, -1, dependant->id().c_str());
lua_getfield(*state, -1, OnDeinitializeFunctionName);
const int status = lua_pcall(*state, 0, 0, 0);
if (status != LUA_OK) {
throw ghoul::lua::LuaLoadingException(lua_tostring(*state, -1));
}
}
}
bool AssetLoader::Asset::hasDependant(InitializationRequirement initReq) {
bool foundDep = false;
for (auto& dependant : _dependants) {
if (dependant->hasDependency(this, initReq)) {
foundDep = true;
}
}
return foundDep;
}
bool AssetLoader::Asset::hasInitializedDependants(InitializationRequirement initReq) {
bool foundInitializedDep = false;
for (auto& dependant : _dependants) {
if (dependant->isInitialized() && dependant->hasDependency(this, initReq)) {
foundInitializedDep = true;
}
}
return foundInitializedDep;
}
// Dependency toggle
AssetLoader::DependencyToggle::DependencyToggle(Asset* dependency, Asset* dependant, bool enabled)
: PropertyOwner({ dependency->name(), dependency->name() })
, _enabled({ "enabled", "Enabled", "Enable dependency" }, enabled)
, _dependency(dependency)
, _dependant(dependant)
{
addProperty(_enabled);
addPropertySubOwner(_dependency);
_enabled.onChange([this]() {
_dependant->setInitializationRequirement(
_dependency,
_enabled ? InitializationRequirement::Yes : InitializationRequirement::No
);
});
}
}
+11 -11
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -26,29 +26,29 @@
namespace openspace {
namespace luascriptfunctions {
int loadAsset(lua_State* state) {
AssetLoader *assetLoader = (AssetLoader*)lua_touserdata(state, lua_upvalueindex(1));
int importAsset(lua_State* state) {
AssetLoader *assetLoader =
reinterpret_cast<AssetLoader*>(lua_touserdata(state, lua_upvalueindex(1)));
int nArguments = lua_gettop(state);
SCRIPT_CHECK_ARGUMENTS("loadAsset", state, 1, nArguments);
SCRIPT_CHECK_ARGUMENTS("importAsset", state, 1, nArguments);
std::string assetName = luaL_checkstring(state, -1);
assetLoader->loadAsset(assetName);
assetLoader->importAsset(assetName);
return 0;
}
int unloadAsset(lua_State* state) {
AssetLoader *assetLoader = (AssetLoader*)lua_touserdata(state, lua_upvalueindex(1));
int unimportAsset(lua_State* state) {
AssetLoader *assetLoader =
reinterpret_cast<AssetLoader*>(lua_touserdata(state, lua_upvalueindex(1)));
int nArguments = lua_gettop(state);
SCRIPT_CHECK_ARGUMENTS("unloadAsset", state, 1, nArguments);
SCRIPT_CHECK_ARGUMENTS("unimportAsset", state, 1, nArguments);
std::string assetName = luaL_checkstring(state, -1);
assetLoader->unloadAsset(assetName);
return 0;
assetLoader->unimportAsset(assetName);
return 0;
}
+10 -1
View File
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -22,6 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/scene/asset.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/scene/sceneloader.h>
#include <openspace/scene/scene.h>
@@ -89,6 +90,14 @@ void SceneLoader::loadScene(Scene* scene, const std::string& path) {
std::string assetName = assetDictionary.value<std::string>(key);
_assetLoader->loadAsset(assetName);
}
// Sync all resources from assets that are dependencies of root asset.
// whenever an asset has all its resources synced: init the asset.
//_assetLoader->rootAsset()->getSynchronizations();
// also show
try {
_assetLoader->rootAsset()->initialize();
} catch (const ghoul::RuntimeError& e) {
@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -22,13 +22,9 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_SYNC___RESOURCESYNCHRONIZATION___H__
#define __OPENSPACE_MODULE_SYNC___RESOURCESYNCHRONIZATION___H__
#include <openspace/util/resourcesynchronizer.h>
namespace openspace {
} // namespace openspace
#endif // __OPENSPACE_MODULE_SYNC___RESOURCESYNCHRONIZATION___H__