mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-12 14:29:42 -05:00
Prepare for data sync
This commit is contained in:
@@ -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 ()
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__
|
||||
@@ -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,
|
||||
|
||||
@@ -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'"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*****************************************************************************************
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
@@ -39,7 +39,9 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
SyncModule::SyncModule() : OpenSpaceModule(Name) {}
|
||||
SyncModule::SyncModule()
|
||||
: OpenSpaceModule(Name)
|
||||
{}
|
||||
|
||||
void SyncModule::internalInitialize() {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*****************************************************************************************
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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__
|
||||
Reference in New Issue
Block a user