mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-24 04:58:59 -05:00
Let assets control their own lifecycle
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#define __OPENSPACE_CORE___ASSET___H__
|
||||
|
||||
#include <openspace/util/resourcesynchronization.h>
|
||||
#include <openspace/util/synchronizationwatcher.h>
|
||||
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
@@ -59,12 +60,14 @@ public:
|
||||
/**
|
||||
* Root asset constructor
|
||||
*/
|
||||
Asset(AssetLoader* loader);
|
||||
Asset(AssetLoader* loader, SynchronizationWatcher* watcher);
|
||||
|
||||
/**
|
||||
* Regular asset constructor
|
||||
*/
|
||||
Asset(AssetLoader* loader, ghoul::filesystem::File assetPath);
|
||||
Asset(AssetLoader* loader,
|
||||
SynchronizationWatcher* watcher,
|
||||
ghoul::filesystem::File assetPath);
|
||||
|
||||
~Asset();
|
||||
|
||||
@@ -76,24 +79,31 @@ public:
|
||||
AssetLoader* loader() const;
|
||||
State state() const;
|
||||
|
||||
void setState(State state);
|
||||
void addSynchronization(std::shared_ptr<ResourceSynchronization> synchronization);
|
||||
std::vector<std::shared_ptr<ResourceSynchronization>> ownSynchronizations() const;
|
||||
|
||||
void syncStateChanged(std::shared_ptr<ResourceSynchronization> sync,
|
||||
ResourceSynchronization::State s);
|
||||
|
||||
void load();
|
||||
bool isLoaded() const;
|
||||
void unload();
|
||||
void unloadIfUnwanted();
|
||||
|
||||
// Sync
|
||||
bool isSynchronized();
|
||||
bool isSynchronized() const;
|
||||
bool startSynchronizations();
|
||||
bool cancelSynchronizations();
|
||||
bool restartSynchronizations();
|
||||
bool cancelAllSynchronizations();
|
||||
bool cancelUnwantedSynchronizations();
|
||||
bool restartAllSynchronizations();
|
||||
float synchronizationProgress();
|
||||
|
||||
// Init
|
||||
bool isInitReady() const;
|
||||
bool hasInitializedRequester() const;
|
||||
bool isInitialized() const;
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
void deinitializeIfUnwanted();
|
||||
|
||||
// Dependency graph
|
||||
bool requires(const Asset* asset) const;
|
||||
@@ -103,33 +113,34 @@ public:
|
||||
void request(std::shared_ptr<Asset> child);
|
||||
void unrequest(std::shared_ptr<Asset> child);
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> requestedAssets();
|
||||
std::vector<std::shared_ptr<Asset>> requestingAssets();
|
||||
std::vector<std::shared_ptr<Asset>> requiredAssets();
|
||||
std::vector<std::shared_ptr<Asset>> requiringAssets();
|
||||
std::vector<std::shared_ptr<Asset>> requestedAssets() const;
|
||||
std::vector<std::shared_ptr<Asset>> requestingAssets() const;
|
||||
std::vector<std::shared_ptr<Asset>> requiredAssets() const;
|
||||
std::vector<std::shared_ptr<Asset>> requiringAssets() const;
|
||||
|
||||
std::vector<std::shared_ptr<Asset>> requiredSubTreeAssets();
|
||||
std::vector<std::shared_ptr<Asset>> subTreeAssets();
|
||||
std::vector<std::shared_ptr<Asset>> childAssets();
|
||||
std::vector<std::shared_ptr<Asset>> childAssets() const;
|
||||
std::vector<std::shared_ptr<Asset>> parentAssets() const;
|
||||
|
||||
bool isRequired() const;
|
||||
bool isRequested() const;
|
||||
bool shouldBeInitialized() const;
|
||||
|
||||
std::string resolveLocalResource(std::string resourceName);
|
||||
private:
|
||||
void requiredAssetChangedState(std::shared_ptr<Asset> a);
|
||||
void setState(State state);
|
||||
|
||||
void addRequestingAsset(std::shared_ptr<Asset> a);
|
||||
void removeRequestingAsset(std::shared_ptr<Asset> a);
|
||||
void addRequiringAsset(std::shared_ptr<Asset> a);
|
||||
void removeRequiringAsset(std::shared_ptr<Asset> a);
|
||||
void requiredAssetChangedState(std::shared_ptr<Asset> a);
|
||||
void requestedAssetChangedState(std::shared_ptr<Asset> a);
|
||||
|
||||
bool isSyncResolveReady();
|
||||
|
||||
std::atomic<State> _state;
|
||||
AssetLoader* _loader;
|
||||
SynchronizationWatcher* _synchronizationWatcher;
|
||||
|
||||
std::vector<std::shared_ptr<ResourceSynchronization>> _synchronizations;
|
||||
mutable std::mutex _synchronizationsMutex;
|
||||
|
||||
bool _hasAssetPath;
|
||||
// The name of the asset
|
||||
@@ -150,9 +161,8 @@ private:
|
||||
// Assets that refers to this asset as a requested asset
|
||||
std::vector<std::weak_ptr<Asset>> _requestingAssets;
|
||||
|
||||
// Synchronization callback handles
|
||||
std::unordered_map<ResourceSynchronization*, ResourceSynchronization::CallbackHandle>
|
||||
_syncCallbackHandles;
|
||||
// Synchronization watches
|
||||
std::vector<SynchronizationWatcher::WatchHandle> _syncWatches;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -56,20 +56,23 @@ int noOperation(lua_State* state);
|
||||
int exportAsset(lua_State* state);
|
||||
} // namespace assetloader
|
||||
|
||||
class AssetStateChangeListener {
|
||||
class AssetListener {
|
||||
public:
|
||||
virtual void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state) = 0;
|
||||
virtual void assetRequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) = 0;
|
||||
virtual void assetUnrequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) = 0;
|
||||
};
|
||||
|
||||
class SynchronizationWatcher;
|
||||
|
||||
class AssetLoader {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
AssetLoader(
|
||||
ghoul::lua::LuaState& luaState,
|
||||
std::string assetRoot
|
||||
);
|
||||
AssetLoader(ghoul::lua::LuaState& luaState,
|
||||
SynchronizationWatcher* syncWatcher,
|
||||
std::string assetRoot);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
@@ -88,18 +91,15 @@ public:
|
||||
*/
|
||||
void remove(const std::string& identifier);
|
||||
|
||||
void trackAsset(std::shared_ptr<Asset> asset);
|
||||
void untrackAsset(Asset* asset);
|
||||
|
||||
/**
|
||||
* Returns the asset identified by the identifier,
|
||||
* if the asset is loaded. Otherwise return nullptr.
|
||||
*/
|
||||
std::shared_ptr<Asset> has(const std::string& identifier) const;
|
||||
|
||||
/**
|
||||
* Return all assets loaded using the loadAsset method.
|
||||
* Non-recursive (does not include imports of the loaded assets)
|
||||
*/
|
||||
//std::vector<std::shared_ptr<Asset>> loadedAssets();
|
||||
|
||||
/**
|
||||
* Return the lua state
|
||||
*/
|
||||
@@ -115,6 +115,8 @@ public:
|
||||
*/
|
||||
const std::string& assetRootDirectory() const;
|
||||
|
||||
bool loadAsset(std::shared_ptr<Asset> asset);
|
||||
|
||||
void callOnInitialize(Asset* asset);
|
||||
|
||||
void callOnDeinitialize(Asset* asset);
|
||||
@@ -127,22 +129,46 @@ public:
|
||||
const std::string& path) const;
|
||||
|
||||
|
||||
void addAssetStateChangeListener(AssetStateChangeListener* listener);
|
||||
void removeAssetStateChangeListener(AssetStateChangeListener* listener);
|
||||
/**
|
||||
* Add listener to asset state changes
|
||||
*/
|
||||
void addAssetListener(AssetListener* listener);
|
||||
|
||||
/**
|
||||
* Remove listener to asset state changes
|
||||
*/
|
||||
void removeAssetListener(AssetListener* listener);
|
||||
|
||||
/**
|
||||
* Notify listeners about asset state change
|
||||
*/
|
||||
void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state);
|
||||
|
||||
/**
|
||||
* Notify listeners about new requests
|
||||
*/
|
||||
void assetRequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child);
|
||||
|
||||
/**
|
||||
* Notify listeners about removed requests
|
||||
*/
|
||||
void assetUnrequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Asset> require(const std::string& identifier);
|
||||
std::shared_ptr<Asset> request(const std::string& path);
|
||||
void unrequest(const std::string& path);
|
||||
|
||||
std::shared_ptr<Asset> loadAsset(std::string path);
|
||||
/**
|
||||
* Add the global assets table to the lua stack.
|
||||
*/
|
||||
void setUpAssetLuaTable(Asset* asset);
|
||||
void tearDownAssetLuaTable(Asset* asset);
|
||||
|
||||
std::shared_ptr<Asset> getAsset(std::string path);
|
||||
ghoul::filesystem::Directory currentDirectory() const;
|
||||
|
||||
void pushAsset(std::shared_ptr<Asset> asset);
|
||||
void popAsset();
|
||||
void updateLuaGlobals();
|
||||
void setCurrentAsset(std::shared_ptr<Asset> asset);
|
||||
void addLuaDependencyTable(Asset* dependant, Asset* dependency);
|
||||
|
||||
// Lua functions
|
||||
@@ -168,12 +194,17 @@ private:
|
||||
friend int assetloader::exportAsset(lua_State* state);
|
||||
|
||||
std::shared_ptr<Asset> _rootAsset;
|
||||
std::unordered_map<std::string, std::shared_ptr<Asset>> _loadedAssets;
|
||||
std::vector<std::shared_ptr<Asset>> _assetStack;
|
||||
std::shared_ptr<Asset> _currentAsset;
|
||||
std::unordered_map<std::string, std::weak_ptr<Asset>> _loadedAssets;
|
||||
|
||||
SynchronizationWatcher* _synchronizationWatcher;
|
||||
|
||||
std::string _assetRootDirectory;
|
||||
ghoul::lua::LuaState* _luaState;
|
||||
|
||||
// State change listeners
|
||||
std::vector<AssetListener*> _assetListeners;
|
||||
|
||||
// References to lua values
|
||||
std::unordered_map<Asset*, std::vector<int>> _onInitializationFunctionRefs;
|
||||
std::unordered_map<Asset*, std::vector<int>> _onDeinitializationFunctionRefs;
|
||||
@@ -181,9 +212,6 @@ private:
|
||||
_onDependencyInitializationFunctionRefs;
|
||||
std::unordered_map<Asset*, std::map<Asset*, std::vector<int>>>
|
||||
_onDependencyDeinitializationFunctionRefs;
|
||||
|
||||
std::vector<AssetStateChangeListener*> _assetStateChangeListeners;
|
||||
|
||||
int _assetsTableRef;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <openspace/scene/asset.h>
|
||||
|
||||
#include <openspace/scene/assetloader.h>
|
||||
#include <openspace/util/resourcesynchronizer.h>
|
||||
#include <openspace/util/synchronizationwatcher.h>
|
||||
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
|
||||
@@ -51,11 +51,12 @@ class Asset;
|
||||
* from the system if it is not a dependency of a loaded asset.
|
||||
*/
|
||||
|
||||
class AssetManager : AssetStateChangeListener {
|
||||
class AssetManager : AssetListener {
|
||||
public:
|
||||
AssetManager(
|
||||
std::unique_ptr<AssetLoader> loader
|
||||
);
|
||||
AssetManager(std::unique_ptr<AssetLoader> loader,
|
||||
std::unique_ptr<SynchronizationWatcher> syncWatcher);
|
||||
|
||||
virtual ~AssetManager() = default;
|
||||
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
@@ -65,6 +66,8 @@ public:
|
||||
std::shared_ptr<Asset> rootAsset();
|
||||
|
||||
void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state) override;
|
||||
void assetRequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) override;
|
||||
void assetUnrequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) override;
|
||||
|
||||
bool update();
|
||||
scripting::LuaLibrary luaLibrary();
|
||||
@@ -77,6 +80,7 @@ private:
|
||||
std::vector<std::shared_ptr<Asset>> _pendingInitializations;
|
||||
|
||||
std::unique_ptr<AssetLoader> _assetLoader;
|
||||
std::unique_ptr<SynchronizationWatcher> _synchronizationWatcher;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
+55
-3
@@ -22,11 +22,63 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
|
||||
#define __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
|
||||
#ifndef __OPENSPACE_CORE___SYNCHRONIZATIONWATCHER___H__
|
||||
#define __OPENSPACE_CORE___SYNCHRONIZATIONWATCHER___H__
|
||||
|
||||
#include <openspace/util/resourcesynchronization.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
/**
|
||||
* Delays callbacks of synchronization state changes to
|
||||
* when notify is called.
|
||||
*/
|
||||
class SynchronizationWatcher {
|
||||
public:
|
||||
using WatchHandle = size_t;
|
||||
|
||||
struct WatchData {
|
||||
std::weak_ptr<ResourceSynchronization> synchronization;
|
||||
ResourceSynchronization::CallbackHandle callbackHandle;
|
||||
};
|
||||
|
||||
struct NotificationData {
|
||||
std::weak_ptr<ResourceSynchronization> synchronization;
|
||||
ResourceSynchronization::State state;
|
||||
WatchHandle handle;
|
||||
ResourceSynchronization::StateChangeCallback callback;
|
||||
};
|
||||
|
||||
/*using SyncStateChangeCallback =
|
||||
std::function<void(
|
||||
std::shared_ptr<ResourceSynchronization>,
|
||||
ResourceSynchronization::State
|
||||
)>;*/
|
||||
|
||||
WatchHandle watchSynchronization(
|
||||
std::shared_ptr<ResourceSynchronization> synchronization,
|
||||
ResourceSynchronization::StateChangeCallback callback
|
||||
);
|
||||
|
||||
void unwatchSynchronization(WatchHandle watch);
|
||||
|
||||
void notify();
|
||||
|
||||
private:
|
||||
WatchHandle generateWatchHandle();
|
||||
std::mutex _mutex;
|
||||
std::unordered_map<WatchHandle, WatchData> _watchedSyncs;
|
||||
std::vector<NotificationData> _pendingNotifications;
|
||||
|
||||
WatchHandle nextWatchHandle = 0;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
|
||||
#endif // __OPENSPACE_CORE___SYNCHRONIZATIONWATCHER___H__
|
||||
Reference in New Issue
Block a user