Merge pull request #1187 from OpenSpace/feature/license

Feature/license
This commit is contained in:
Alexander Bock
2020-06-12 17:54:13 +02:00
committed by GitHub
28 changed files with 536 additions and 740 deletions

View File

@@ -18,3 +18,12 @@ end)
asset.onDeinitialize(function ()
openspace.removeInterestingNodes({ "Earth", "Mars", "Moon", "Sun" })
end)
asset.meta = {
Name = "Default scene",
Version = "1.0",
Description = [[ Bla bla, something something asteroids ]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -22,3 +22,13 @@ asset.request('./planets/uranus/major_moons')
asset.request('./planets/neptune/neptune')
asset.request('./planets/neptune/major_moons')
asset.meta = {
Name = "Planets",
Version = "1.0",
Description = [[ Collection of planets in the solar system ]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -329,3 +329,13 @@ local EarthLabel = {
assetHelper.registerSceneGraphNodesAndExport(asset, { Earth, EarthLabel })
asset.meta = {
Name = "Earth",
Version = "1.0",
Description = [[ Earth is a special planet with special needs ]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -82,3 +82,13 @@ end
asset.export("setCefRoute", setCefRoute)
asset.meta = {
Name = "WebGUI",
Version = "0.1",
Description = [[ insert CEF rant ]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -3,14 +3,12 @@
<div class="row">
<div class="col-lg-12">
<p>
<a href="#{{urlify module}}" name="{{urlify module}}">
<span class="documentation-key">{{module}}</span>
</a>
<p>{{name}}</p>
<br />
<p>{{attribution}}</p>
<p>{{url}}</p>
<p>{{licenseText}}</p>
<h3>Asset - {{name}}</h3>
<p>{{description}}</p>
<p>Version - {{version}}</p>
<p>Author - {{author}}</p>
<p>Associated URL - <a href="{{url}}">{{url}}</a></p>
<p>Filepath - {{path}}</p>
</p>
</div>
</div>

View File

@@ -28,6 +28,7 @@
#include <openspace/util/resourcesynchronization.h>
#include <openspace/util/synchronizationwatcher.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
@@ -37,7 +38,7 @@ class AssetLoader;
class Asset : public std::enable_shared_from_this<Asset> {
public:
enum class State : unsigned int {
enum class State {
Unloaded,
LoadingFailed,
Loaded,
@@ -48,8 +49,14 @@ public:
InitializationFailed
};
using StateChangeCallback = std::function<void(State)>;
using CallbackHandle = size_t;
struct MetaInformation {
std::string name;
std::string version;
std::string description;
std::string author;
std::string url;
std::string license;
};
/**
* Root asset constructor
@@ -69,10 +76,9 @@ public:
AssetLoader* loader() const;
State state() const;
void addSynchronization(std::shared_ptr<ResourceSynchronization> synchronization);
void addSynchronization(std::unique_ptr<ResourceSynchronization> synchronization);
void clearSynchronizations();
const std::vector<std::shared_ptr<ResourceSynchronization>>&
ownSynchronizations() const;
std::vector<ResourceSynchronization*> ownSynchronizations() const;
void syncStateChanged(ResourceSynchronization* sync,
ResourceSynchronization::State state);
@@ -92,12 +98,6 @@ public:
* its own synchronizations and required assets' synchronizations could start.
*/
bool startSynchronizations();
bool hasSyncingOrResolvedParent() const;
bool isSynchronized() const;
bool isSyncingOrResolved() const;
bool cancelAllSynchronizations();
bool cancelUnwantedSynchronizations();
bool restartAllSynchronizations();
float requiredSynchronizationProgress() const;
float requestedSynchronizationProgress();
@@ -120,21 +120,16 @@ public:
void request(std::shared_ptr<Asset> child);
void unrequest(Asset* child);
const std::vector<std::shared_ptr<Asset>>& requestedAssets() const;
std::vector<std::shared_ptr<Asset>> requestingAssets() const;
const std::vector<std::shared_ptr<Asset>>& requiredAssets() const;
std::vector<std::shared_ptr<Asset>> requiringAssets() const;
std::vector<Asset*> requestedAssets() const;
std::vector<Asset*> requestingAssets() const;
std::vector<Asset*> requiredAssets() const;
std::vector<Asset*> requiringAssets() const;
std::vector<std::shared_ptr<const Asset>> requiredSubTreeAssets() const;
std::vector<std::shared_ptr<const Asset>> subTreeAssets() const;
std::vector<std::shared_ptr<Asset>> childAssets() const;
std::vector<std::shared_ptr<Asset>> parentAssets() const;
std::vector<const Asset*> subTreeAssets() const;
std::vector<Asset*> childAssets() const;
bool isRequired() const;
bool isRequested() const;
bool shouldBeInitialized() const;
std::string resolveLocalResource(std::string resourceName);
void setMetaInformation(MetaInformation metaInformation);
std::optional<MetaInformation> metaInformation() const;
private:
void setState(State state);
@@ -142,7 +137,14 @@ private:
void requiredAssetChangedState(Asset::State childState);
void requestedAssetChangedState(Asset* child, Asset::State childState);
bool isSynchronized() const;
bool isSyncingOrResolved() const;
bool isSyncResolveReady();
bool hasSyncingOrResolvedParent() const;
bool cancelAllSynchronizations();
bool cancelUnwantedSynchronizations();
std::vector<const Asset*> requiredSubTreeAssets() const;
std::atomic<State> _state;
AssetLoader* _loader;
@@ -157,6 +159,8 @@ private:
// Absolute path to asset file
std::string _assetPath;
std::optional<MetaInformation> _metaInformation;
// Required assets
std::vector<std::shared_ptr<Asset>> _requiredAssets;

View File

@@ -32,12 +32,9 @@ namespace openspace {
class AssetListener {
public:
virtual ~AssetListener() = default;
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;
virtual void assetStateChanged(Asset* asset, Asset::State state) = 0;
virtual void assetRequested(Asset* parent, std::shared_ptr<Asset> child) = 0;
virtual void assetUnrequested(Asset* parent, std::shared_ptr<Asset> child) = 0;
};
} // namespace openspace

View File

@@ -49,15 +49,13 @@ int request(lua_State* state);
int exists(lua_State* state);
int localResource(lua_State* state);
int syncedResource(lua_State* state);
int noOperation(lua_State* state);
int exportAsset(lua_State* state);
} // namespace assetloader
class Asset;
class AssetListener;
class ResourceSynchronization;
class SynchronizationWatcher;
class AssetListener;
class AssetLoader {
public:
@@ -87,30 +85,26 @@ public:
void untrackAsset(Asset* asset);
/**
* Return the asset identified by the identifier,
* if the asset is tracked. Otherwise return nullptr.
*/
* Return the asset identified by the identifier,
* if the asset is tracked. Otherwise return nullptr.
*/
std::shared_ptr<Asset> has(const std::string& identifier) const;
/**
* Return the lua state
*/
ghoul::lua::LuaState* luaState();
/// Return the root asset
const Asset& rootAsset() const;
/// Return the root asset
Asset& rootAsset();
/**
* Return the root asset
* Return the asset root directory
*/
std::shared_ptr<Asset> rootAsset() const;
/**
* Return the asset root directory
*/
const std::string& assetRootDirectory() const;
/**
* Load an asset
*/
bool loadAsset(std::shared_ptr<Asset> asset);
bool loadAsset(Asset* asset);
/**
* Unload an asset
@@ -157,30 +151,29 @@ public:
/**
* Notify listeners about asset state change
*/
void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state);
void assetStateChanged(Asset* asset, Asset::State state);
/**
* Notify listeners about new requests
*/
void assetRequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child);
void assetRequested(Asset* parent, std::shared_ptr<Asset> child);
/**
* Notify listeners about removed requests
*/
void assetUnrequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child);
void assetUnrequested(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& identifier);
void unrequest(const std::string& identifier);
void setUpAssetLuaTable(Asset* asset);
void tearDownAssetLuaTable(Asset* asset);
std::shared_ptr<Asset> getAsset(std::string name);
std::shared_ptr<Asset> getAsset(const std::string& name);
ghoul::filesystem::Directory currentDirectory() const;
void setCurrentAsset(std::shared_ptr<Asset> asset);
void setCurrentAsset(Asset* asset);
void addLuaDependencyTable(Asset* dependant, Asset* dependency);
// Lua functions
@@ -195,7 +188,7 @@ private:
int syncedResourceLua(Asset* asset);
int exportAssetLua(Asset* asset);
// Friend c closures (callable from lua, and maps to lua functions above)
// Friend C closures (callable from Lua, and maps to Lua functions above)
friend int assetloader::onInitialize(lua_State* state);
friend int assetloader::onDeinitialize(lua_State* state);
friend int assetloader::onInitializeDependency(lua_State* state);
@@ -209,7 +202,7 @@ private:
// Member variables
std::shared_ptr<Asset> _rootAsset;
std::shared_ptr<Asset> _currentAsset;
Asset* _currentAsset = nullptr;
std::unordered_map<std::string, std::weak_ptr<Asset>> _trackedAssets;
SynchronizationWatcher* _synchronizationWatcher;
std::string _assetRootDirectory;
@@ -218,14 +211,14 @@ private:
// State change listeners
std::vector<AssetListener*> _assetListeners;
// References to lua values
// References to Lua values
std::unordered_map<Asset*, std::vector<int>> _onInitializationFunctionRefs;
std::unordered_map<Asset*, std::vector<int>> _onDeinitializationFunctionRefs;
std::unordered_map<Asset*, std::map<Asset*, std::vector<int>>>
_onDependencyInitializationFunctionRefs;
std::unordered_map<Asset*, std::map<Asset*, std::vector<int>>>
_onDependencyDeinitializationFunctionRefs;
int _assetsTableRef;
int _assetsTableRef = 0;
};
} // namespace openspace

View File

@@ -27,9 +27,12 @@
#include <openspace/scene/assetlistener.h>
#include <openspace/scene/assetloader.h>
#include <ghoul/lua/ghoul_lua.h>
#include <ghoul/lua/luastate.h>
#include <memory>
#include <vector>
#include <unordered_map>
#include <vector>
namespace openspace {
@@ -41,18 +44,14 @@ class SynchronizationWatcher;
/**
* Interface for managing assets.
* The asset manager interface is only concerned with "top level" assets,
* i.e. assets that are loaded using setTargetAssetState, and not their dependencies.
* However, an asset is not considered synchronized before all its deps are
* synchronized.
* Also, setting a target state of an asset to Unloaded will only unload an asset
* from the system if it is not a dependency of a loaded asset.
* The asset manager interface is only concerned with "top level" assets, and not their
* dependencies. However, an asset is not considered synchronized before all its deps are
* synchronized. Also, setting a target state of an asset to Unloaded will only unload an
* asset from the system if it is not a dependency of a loaded asset.
*/
class AssetManager : AssetListener {
public:
AssetManager(std::unique_ptr<AssetLoader> loader,
std::unique_ptr<SynchronizationWatcher> syncWatcher);
AssetManager(ghoul::lua::LuaState* state, std::string assetRootDirectory);
virtual ~AssetManager() = default;
@@ -61,13 +60,12 @@ public:
void add(const std::string& path);
void remove(const std::string& path);
void removeAll();
std::shared_ptr<Asset> rootAsset();
const Asset& rootAsset() const;
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;
void assetStateChanged(Asset* asset, Asset::State state) override;
void assetRequested(Asset* parent, std::shared_ptr<Asset> child) override;
void assetUnrequested(Asset* parent, std::shared_ptr<Asset> child) override;
bool update();
scripting::LuaLibrary luaLibrary();
@@ -77,8 +75,8 @@ private:
std::mutex _pendingInitializationsMutex;
std::vector<std::shared_ptr<Asset>> _pendingInitializations;
std::unique_ptr<SynchronizationWatcher> _synchronizationWatcher;
std::unique_ptr<AssetLoader> _assetLoader;
SynchronizationWatcher _synchronizationWatcher;
AssetLoader _assetLoader;
};
} // namespace openspace

View File

@@ -28,7 +28,6 @@
#include <openspace/properties/propertyowner.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scene/scenelicense.h>
#include <ghoul/misc/easing.h>
#include <ghoul/misc/exception.h>
#include <mutex>
@@ -134,8 +133,6 @@ public:
*/
void unregisterNode(SceneGraphNode* node);
void addSceneLicense(SceneLicense license);
/**
* Mark the node registry as dirty
*/
@@ -146,14 +143,6 @@ public:
*/
const std::vector<SceneGraphNode*>& allSceneGraphNodes() const;
/**
* Generate JSON about the license information for the scenegraph nodes that are
* contained in this scene
* \param path The file path that will contain the documentation about the licenses
* used in this scene
*/
std::string generateSceneLicenseDocumentationJson();
/**
* Returns a map from identifier to scene graph node.
*/
@@ -261,8 +250,6 @@ private:
std::vector<InterestingTime> _interestingTimes;
std::vector<SceneLicense> _licenses;
std::mutex _programUpdateLock;
std::set<ghoul::opengl::ProgramObject*> _programsToUpdate;
std::vector<std::unique_ptr<ghoul::opengl::ProgramObject>> _programs;

View File

@@ -1,56 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2020 *
* *
* 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___SCENELICENSE___H__
#define __OPENSPACE_CORE___SCENELICENSE___H__
#include <string>
#include <vector>
namespace ghoul { class Dictionary; }
namespace openspace {
namespace documentation { struct Documentation; }
struct SceneLicense {
// module must not be empty
SceneLicense(const ghoul::Dictionary& dictionary, std::string m);
std::string module;
std::string name;
std::string attribution;
std::string url;
std::string licenseText;
static documentation::Documentation Documentation();
};
void writeSceneLicenseDocumentation(const std::vector<SceneLicense>& licenses,
const std::string& file, const std::string& type);
} // namespace openspace
#endif // __OPENSPACE_CORE___SCENELICENSE___H__

View File

@@ -31,15 +31,10 @@
namespace openspace {
struct SceneLicense;
class SceneLicenseWriter : public DocumentationGenerator {
public:
SceneLicenseWriter(std::vector<SceneLicense> licenses);
SceneLicenseWriter();
std::string generateJson() const override;
private:
const std::vector<SceneLicense>& _licenses;
};
} // namespace openspace

View File

@@ -68,9 +68,9 @@ public:
State state() const;
const std::string& name() const;
bool isResolved();
bool isRejected();
bool isSyncing();
bool isResolved() const;
bool isRejected() const;
bool isSyncing() const;
CallbackHandle addStateChangeCallback(StateChangeCallback cb);
void removeStateChangeCallback(CallbackHandle id);

View File

@@ -53,12 +53,6 @@ public:
ResourceSynchronization::StateChangeCallback callback;
};
/*using SyncStateChangeCallback =
std::function<void(
std::shared_ptr<ResourceSynchronization>,
ResourceSynchronization::State
)>;*/
WatchHandle watchSynchronization(
std::shared_ptr<ResourceSynchronization> synchronization,
ResourceSynchronization::StateChangeCallback callback
@@ -69,7 +63,6 @@ public:
void notify();
private:
WatchHandle generateWatchHandle();
std::mutex _mutex;
std::unordered_map<WatchHandle, WatchData> _watchedSyncs;
std::vector<NotificationData> _pendingNotifications;

View File

@@ -39,14 +39,14 @@ namespace {
using State = openspace::Asset::State;
switch (state) {
case State::Loaded: return "Loaded";
case State::LoadingFailed: return "LoadingFailed";
case State::Synchronizing: return "Synchronizing";
case State::SyncRejected: return "SyncRejected";
case State::SyncResolved: return "SyncResolved";
case State::Initialized: return "Initialized";
case State::InitializationFailed: return "InitializationFailed";
default: return "Unknown";
case State::Loaded: return "Loaded";
case State::LoadingFailed: return "LoadingFailed";
case State::Synchronizing: return "Synchronizing";
case State::SyncRejected: return "SyncRejected";
case State::SyncResolved: return "SyncResolved";
case State::Initialized: return "Initialized";
case State::InitializationFailed: return "InitializationFailed";
default: return "Unknown";
}
}
@@ -54,14 +54,14 @@ namespace {
using State = openspace::ResourceSynchronization::State;
switch (state) {
case State::Unsynced: return "Unsynced";
case State::Syncing: return "Syncing";
case State::Resolved: return "Resolved";
case State::Rejected: return "Rejected";
default: return "Unknown";
case State::Unsynced: return "Unsynced";
case State::Syncing: return "Syncing";
case State::Resolved: return "Resolved";
case State::Rejected: return "Rejected";
default: return "Unknown";
}
}
}
} // namespace
namespace openspace::gui {
@@ -69,7 +69,6 @@ GuiAssetComponent::GuiAssetComponent()
: GuiComponent("Assets")
{}
void GuiAssetComponent::render() {
bool e = _isEnabled;
ImGui::Begin("Assets", &e);
@@ -79,7 +78,7 @@ void GuiAssetComponent::render() {
std::string rootPath;
for (const std::shared_ptr<Asset>& a : assetManager.rootAsset()->childAssets()) {
for (Asset* a : assetManager.rootAsset().childAssets()) {
renderTree(*a, rootPath);
}
@@ -104,29 +103,29 @@ void GuiAssetComponent::renderTree(const Asset& asset, const std::string& relati
assetText += " (" + std::to_string(prog) + "%)";
}
const std::vector<std::shared_ptr<Asset>>& requested = asset.requestedAssets();
const std::vector<std::shared_ptr<Asset>>& required = asset.requiredAssets();
std::vector<Asset*> requested = asset.requestedAssets();
std::vector<Asset*> required = asset.requiredAssets();
const std::vector<std::shared_ptr<ResourceSynchronization>>& resourceSyncs =
const std::vector<ResourceSynchronization*>& resourceSyncs =
asset.ownSynchronizations();
if (requested.empty() && required.empty() && resourceSyncs.empty()) {
ImGui::Text("%s", assetText.c_str());
}
else if (ImGui::TreeNode(assetPath.c_str(), "%s", assetText.c_str())) {
for (const std::shared_ptr<Asset>& child : required) {
for (const Asset* child : required) {
renderTree(*child, assetDirectory);
}
if (!requested.empty() && ImGui::TreeNode("Requested assets")) {
for (const std::shared_ptr<Asset>& child : requested) {
for (const Asset* child : requested) {
renderTree(*child, assetDirectory);
}
ImGui::TreePop();
}
if (!resourceSyncs.empty() && ImGui::TreeNode("Resource Synchronizations")) {
for (const std::shared_ptr<ResourceSynchronization>& sync : resourceSyncs) {
for (ResourceSynchronization* sync : resourceSyncs) {
std::string resourceText = sync->directory() +
" " + syncStateToString(sync->state());
if (sync->state() == ResourceSynchronization::State::Syncing) {

View File

@@ -29,7 +29,6 @@
#include <openspace/documentation/verifier.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/globals.h>
#include <openspace/scene/assetlistener.h>
#include <openspace/scene/assetloader.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/openspacemodule.h>
@@ -74,21 +73,6 @@ documentation::Documentation SyncAssetTask::documentation() {
};
}
class RequestListener : public AssetListener {
public:
virtual ~RequestListener() = default;
void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state) override {
if (state == Asset::State::LoadingFailed) {
LERROR(fmt::format("Failed to load asset: {}", asset->id()));
}
if (state == Asset::State::SyncRejected) {
LERROR(fmt::format("Failed to sync asset: {}", asset->id()));
}
}
void assetRequested(std::shared_ptr<Asset>, std::shared_ptr<Asset>) override {};
void assetUnrequested(std::shared_ptr<Asset>, std::shared_ptr<Asset>) override {};
};
SyncAssetTask::SyncAssetTask(const ghoul::Dictionary& dictionary) {
documentation::testSpecificationAndThrow(
documentation(),
@@ -125,18 +109,14 @@ void SyncAssetTask::perform(const Task::ProgressCallback& progressCallback) {
AssetLoader loader(&luaState, &watcher, "${ASSETS}");
RequestListener listener;
loader.addAssetListener(&listener);
loader.add(_asset);
loader.rootAsset()->startSynchronizations();
loader.rootAsset().startSynchronizations();
std::vector<std::shared_ptr<const Asset>> allAssets =
loader.rootAsset()->subTreeAssets();
std::vector<const Asset*> allAssets = loader.rootAsset().subTreeAssets();
while (true) {
bool inProgress = false;
for (const std::shared_ptr<const Asset>& asset : allAssets) {
for (const Asset* asset : allAssets) {
Asset::State state = asset->state();
if (state == Asset::State::Unloaded ||
state == Asset::State::Loaded ||
@@ -145,7 +125,7 @@ void SyncAssetTask::perform(const Task::ProgressCallback& progressCallback) {
inProgress = true;
}
}
progressCallback(loader.rootAsset()->requestedSynchronizationProgress());
progressCallback(loader.rootAsset().requestedSynchronizationProgress());
std::this_thread::sleep_for(ProgressPollInterval);
watcher.notify();
if (!inProgress) {

View File

@@ -157,7 +157,6 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/scene/scene.cpp
${OPENSPACE_BASE_DIR}/src/scene/scene_lua.inl
${OPENSPACE_BASE_DIR}/src/scene/sceneinitializer.cpp
${OPENSPACE_BASE_DIR}/src/scene/scenelicense.cpp
${OPENSPACE_BASE_DIR}/src/scene/scenelicensewriter.cpp
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode.cpp
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode_doc.inl
@@ -346,7 +345,6 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/scene/scale.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/scene.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/sceneinitializer.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenelicense.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenelicensewriter.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenegraphnode.h
${OPENSPACE_BASE_DIR}/include/openspace/scene/timeframe.h

View File

@@ -341,17 +341,9 @@ void OpenSpaceEngine::initialize() {
}
// Set up asset loader
std::unique_ptr<SynchronizationWatcher> w =
std::make_unique<SynchronizationWatcher>();
SynchronizationWatcher* rawWatcher = w.get();
global::openSpaceEngine._assetManager = std::make_unique<AssetManager>(
std::make_unique<AssetLoader>(
global::scriptEngine.luaState(),
rawWatcher,
FileSys.absPath("${ASSETS}")
),
std::move(w)
global::scriptEngine.luaState(),
FileSys.absPath("${ASSETS}")
);
global::scriptEngine.addLibrary(global::openSpaceEngine._assetManager->luaLibrary());
@@ -754,15 +746,13 @@ void OpenSpaceEngine::loadSingleAsset(const std::string& assetPath) {
_loadingScreen->setPhase(LoadingScreen::Phase::Synchronization);
_loadingScreen->postMessage("Synchronizing assets");
std::vector<std::shared_ptr<const Asset>> allAssets =
_assetManager->rootAsset()->subTreeAssets();
std::vector<const Asset*> allAssets = _assetManager->rootAsset().subTreeAssets();
std::unordered_set<std::shared_ptr<ResourceSynchronization>> resourceSyncs;
for (const std::shared_ptr<const Asset>& a : allAssets) {
std::vector<std::shared_ptr<ResourceSynchronization>> syncs =
a->ownSynchronizations();
std::unordered_set<ResourceSynchronization*> resourceSyncs;
for (const Asset* a : allAssets) {
std::vector<ResourceSynchronization*> syncs = a->ownSynchronizations();
for (const std::shared_ptr<ResourceSynchronization>& s : syncs) {
for (ResourceSynchronization* s : syncs) {
ZoneScopedN("Update resource synchronization")
if (s->state() == ResourceSynchronization::State::Syncing) {
@@ -1030,7 +1020,7 @@ void OpenSpaceEngine::writeSceneDocumentation() {
_documentationJson += "{\"name\":\"Scene License Information\",";
_documentationJson += "\"identifier\":\"sceneLicense";
_documentationJson += "\",\"data\":";
_documentationJson += _scene->generateSceneLicenseDocumentationJson();
_documentationJson += SceneLicenseWriter().generateJson();
_documentationJson += "},";
_documentationJson += "{\"name\":\"Scene Properties\",";
_documentationJson += "\"identifier\":\"propertylist";// + _scene->jsonName();
@@ -1045,8 +1035,7 @@ void OpenSpaceEngine::writeSceneDocumentation() {
DocEng.addHandlebarTemplates(global::keybindingManager.templatesToRegister());
//TODO this is in efficaiant, here i am just instaning the class to get
//at a member variable which is staticly defined. How do i just get that
const std::vector<SceneLicense> licenses;
SceneLicenseWriter writer(licenses);
SceneLicenseWriter writer;
DocEng.addHandlebarTemplates(writer.templatesToRegister());
DocEng.addHandlebarTemplates(global::rootPropertyOwner.templatesToRegister());

View File

@@ -33,19 +33,19 @@
#include <algorithm>
#include <unordered_set>
namespace {
const constexpr char* _loggerCat = "Asset";
namespace openspace {
float syncProgress(const std::vector<std::shared_ptr<const openspace::Asset>>& assets)
{
namespace {
constexpr const char* _loggerCat = "Asset";
float syncProgress(const std::vector<const Asset*>& assets) {
size_t nTotalBytes = 0;
size_t nSyncedBytes = 0;
for (const std::shared_ptr<const openspace::Asset>& a : assets) {
const std::vector<std::shared_ptr<openspace::ResourceSynchronization>>& s =
a->ownSynchronizations();
for (const Asset* a : assets) {
std::vector<ResourceSynchronization*> s = a->ownSynchronizations();
for (const std::shared_ptr<openspace::ResourceSynchronization>& sync : s) {
for (ResourceSynchronization* sync : s) {
if (sync->nTotalBytesIsKnown()) {
nTotalBytes += sync->nTotalBytes();
nSyncedBytes += sync->nSynchronizedBytes();
@@ -62,9 +62,8 @@ namespace {
}
return static_cast<float>(nSyncedBytes) / static_cast<float>(nTotalBytes);
}
}
} // namespace
namespace openspace {
Asset::Asset(AssetLoader* loader, SynchronizationWatcher* watcher)
: _state(State::SyncResolved)
@@ -74,9 +73,7 @@ Asset::Asset(AssetLoader* loader, SynchronizationWatcher* watcher)
, _assetName("Root Asset")
{}
Asset::Asset(AssetLoader* loader, SynchronizationWatcher* watcher,
std::string assetPath
)
Asset::Asset(AssetLoader* loader, SynchronizationWatcher* watcher, std::string assetPath)
: _state(State::Unloaded)
, _loader(loader)
, _synchronizationWatcher(watcher)
@@ -84,10 +81,12 @@ Asset::Asset(AssetLoader* loader, SynchronizationWatcher* watcher,
, _assetPath(std::move(assetPath))
{}
std::string Asset::resolveLocalResource(std::string resourceName) {
std::string assetDir = assetDirectory();
return assetDir + ghoul::filesystem::FileSystem::PathSeparator +
std::move(resourceName);
void Asset::setMetaInformation(MetaInformation metaInformation) {
_metaInformation = std::move(metaInformation);
}
std::optional<Asset::MetaInformation> Asset::metaInformation() const {
return _metaInformation;
}
Asset::State Asset::state() const {
@@ -108,8 +107,7 @@ void Asset::setState(Asset::State state) {
}
_state = state;
std::shared_ptr<Asset> thisAsset = shared_from_this();
_loader->assetStateChanged(thisAsset, state);
_loader->assetStateChanged(this, state);
for (const std::weak_ptr<Asset>& requiringAsset : _requiringAssets) {
if (std::shared_ptr<Asset> a = requiringAsset.lock()) {
@@ -127,18 +125,17 @@ void Asset::setState(Asset::State state) {
void Asset::requiredAssetChangedState(Asset::State childState) {
if (!isLoaded()) {
// Prohibit state change to SyncResolved if additional requirements
// may still be added.
// may still be added
return;
}
if (isInitialized()) {
// Do not do anything if this asset was already initialized.
// This may happen if there are multiple requirement paths from
// this asset to the same child, which causes this method to be
// called more than once.
// Do not do anything if this asset was already initialized. This may happen if
// there are multiple requirement paths from this asset to the same child, which
// causes this method to be called more than once
return;
}
if (state() == State::InitializationFailed) {
// Do not do anything if the asset failed to initialize.
if (_state == State::InitializationFailed) {
// Do not do anything if the asset failed to initialize
return;
}
if (childState == State::SyncResolved) {
@@ -153,21 +150,19 @@ void Asset::requiredAssetChangedState(Asset::State childState) {
void Asset::requestedAssetChangedState(Asset* child, Asset::State childState) {
if (child->hasInitializedParent()) {
if (childState == State::Loaded &&
child->state() == State::Loaded)
{
if (childState == State::Loaded && child->state() == State::Loaded) {
child->startSynchronizations();
}
if (childState == State::SyncResolved &&
child->state() == State::SyncResolved)
{
if (childState == State::SyncResolved && child->state() == State::SyncResolved) {
child->initialize();
}
}
}
void Asset::addSynchronization(std::shared_ptr<ResourceSynchronization> synchronization) {
_synchronizations.push_back(synchronization);
void Asset::addSynchronization(std::unique_ptr<ResourceSynchronization> synchronization) {
std::shared_ptr<ResourceSynchronization> sync = std::move(synchronization);
_synchronizations.push_back(sync);
// Set up callback for synchronization state change
// The synchronization watcher will make sure that callbacks
@@ -175,9 +170,9 @@ void Asset::addSynchronization(std::shared_ptr<ResourceSynchronization> synchron
SynchronizationWatcher::WatchHandle watch =
_synchronizationWatcher->watchSynchronization(
synchronization,
[this, synchronization](ResourceSynchronization::State state) {
syncStateChanged(synchronization.get(), state);
sync,
[this, sync](ResourceSynchronization::State state) {
syncStateChanged(sync.get(), state);
}
);
_syncWatches.push_back(watch);
@@ -201,7 +196,7 @@ void Asset::syncStateChanged(ResourceSynchronization* sync,
}
else if (state == ResourceSynchronization::State::Rejected) {
LERROR(fmt::format(
"Failed to synchronize resource '{}'' in asset '{}'", sync->name(), id()
"Failed to synchronize resource '{}' in asset '{}'", sync->name(), id()
));
setState(State::SyncRejected);
@@ -209,93 +204,84 @@ void Asset::syncStateChanged(ResourceSynchronization* sync,
}
bool Asset::isSyncResolveReady() {
std::vector<std::shared_ptr<Asset>> requiredAssets = this->requiredAssets();
std::vector<Asset*> requiredAssets = this->requiredAssets();
auto unsynchronizedAsset = std::find_if(
requiredAssets.begin(),
requiredAssets.end(),
[](std::shared_ptr<Asset>& a) {
return !a->isSynchronized();
}
const auto unsynchronizedAsset = std::find_if(
requiredAssets.cbegin(),
requiredAssets.cend(),
[](Asset* a) { return !a->isSynchronized(); }
);
if (unsynchronizedAsset != requiredAssets.end()) {
if (unsynchronizedAsset != requiredAssets.cend()) {
// Not considered resolved if there is one or more unresolved children
return false;
}
const std::vector<std::shared_ptr<ResourceSynchronization>>& syncs =
ownSynchronizations();
auto unresolvedOwnSynchronization = std::find_if(
syncs.begin(),
syncs.end(),
[](const std::shared_ptr<ResourceSynchronization>& s) {
return !s->isResolved();
}
const auto unresolvedOwnSynchronization = std::find_if(
_synchronizations.cbegin(),
_synchronizations.cend(),
[](const std::shared_ptr<ResourceSynchronization>& s) { return !s->isResolved(); }
);
// To be considered resolved, all own synchronizations need to be resolved
return unresolvedOwnSynchronization == syncs.end();
return unresolvedOwnSynchronization == _synchronizations.cend();
}
const std::vector<std::shared_ptr<ResourceSynchronization>>&
Asset::ownSynchronizations() const
{
return _synchronizations;
std::vector<ResourceSynchronization*> Asset::ownSynchronizations() const {
std::vector<ResourceSynchronization*> res;
res.reserve(_synchronizations.size());
std::transform(
_synchronizations.begin(), _synchronizations.end(),
std::back_inserter(res),
std::mem_fn(&std::shared_ptr<ResourceSynchronization>::get)
);
return res;
}
std::vector<std::shared_ptr<const Asset>> Asset::subTreeAssets() const {
std::unordered_set<std::shared_ptr<const Asset>> assets({ shared_from_this() });
for (const std::shared_ptr<Asset>& c : childAssets()) {
if (c.get() == this) {
std::vector<const Asset*> Asset::subTreeAssets() const {
std::unordered_set<const Asset*> assets({ this });
for (Asset* c : childAssets()) {
if (c == this) {
throw ghoul::RuntimeError(fmt::format(
"Detected cycle in asset inclusion for {} at {}", _assetName, _assetPath
));
}
const std::vector<std::shared_ptr<const Asset>>& subTree = c->subTreeAssets();
std::vector<const Asset*> subTree = c->subTreeAssets();
std::copy(subTree.begin(), subTree.end(), std::inserter(assets, assets.end()));
}
std::vector<std::shared_ptr<const Asset>> assetVector(assets.begin(), assets.end());
std::vector<const Asset*> assetVector(assets.begin(), assets.end());
return assetVector;
}
std::vector<std::shared_ptr<const Asset>> Asset::requiredSubTreeAssets() const {
std::unordered_set<std::shared_ptr<const Asset>> assets({ shared_from_this() });
std::vector<const Asset*> Asset::requiredSubTreeAssets() const {
std::unordered_set<const Asset*> assets({ this });
for (const std::shared_ptr<Asset>& dep : _requiredAssets) {
const std::vector<std::shared_ptr<const Asset>>& subTree =
dep->requiredSubTreeAssets();
std::vector<const Asset*> subTree = dep->requiredSubTreeAssets();
std::copy(subTree.begin(), subTree.end(), std::inserter(assets, assets.end()));
}
std::vector<std::shared_ptr<const Asset>> assetVector(assets.begin(), assets.end());
std::vector<const Asset*> assetVector(assets.begin(), assets.end());
return assetVector;
}
bool Asset::isLoaded() const {
State s = state();
return s != State::Unloaded && s != State::LoadingFailed;
return _state != State::Unloaded && _state != State::LoadingFailed;
}
bool Asset::isSynchronized() const {
State s = state();
return s == State::SyncResolved ||
s == State::Initialized ||
s == State::InitializationFailed;
return _state == State::SyncResolved || _state == State::Initialized ||
_state == State::InitializationFailed;
}
bool Asset::isSyncingOrResolved() const {
State s = state();
return s == State::Synchronizing ||
s == State::SyncResolved ||
s == State::Initialized ||
s == State::InitializationFailed;
return _state == State::Synchronizing || _state == State::SyncResolved ||
_state == State::Initialized || _state == State::InitializationFailed;
}
bool Asset::hasLoadedParent() {
{
std::vector<std::weak_ptr<Asset>>::iterator it = _requiringAssets.begin();
auto it = _requiringAssets.begin();
while (it != _requiringAssets.end()) {
std::shared_ptr<Asset> parent = it->lock();
if (!parent) {
@@ -309,7 +295,7 @@ bool Asset::hasLoadedParent() {
}
}
{
std::vector<std::weak_ptr<Asset>>::iterator it = _requestingAssets.begin();
auto it = _requestingAssets.begin();
while (it != _requestingAssets.end()) {
std::shared_ptr<Asset> parent = it->lock();
if (!parent) {
@@ -371,8 +357,7 @@ bool Asset::hasInitializedParent() const {
}
bool Asset::isInitialized() const {
State s = state();
return s == State::Initialized;
return _state == State::Initialized;
}
bool Asset::startSynchronizations() {
@@ -380,33 +365,33 @@ bool Asset::startSynchronizations() {
LWARNING(fmt::format("Cannot start synchronizations of unloaded asset {}", id()));
return false;
}
for (const std::shared_ptr<Asset>& child : requestedAssets()) {
for (Asset* child : requestedAssets()) {
child->startSynchronizations();
}
// Do not attempt to resync if this is already done
if (isSyncingOrResolved()) {
return state() != State::SyncResolved;
return _state != State::SyncResolved;
}
setState(State::Synchronizing);
bool childFailed = false;
// Start synchronization of all children first.
for (const std::shared_ptr<Asset>& child : requiredAssets()) {
// Start synchronization of all children first
for (Asset* child : requiredAssets()) {
if (!child->startSynchronizations()) {
childFailed = true;
}
}
// Now synchronize its own synchronizations.
for (const std::shared_ptr<ResourceSynchronization>& s : ownSynchronizations()) {
// Now synchronize its own synchronizations
for (const std::shared_ptr<ResourceSynchronization>& s : _synchronizations) {
if (!s->isResolved()) {
s->start();
}
}
// If all syncs are resolved (or no syncs exist), mark as resolved.
// If all syncs are resolved (or no syncs exist), mark as resolved
if (!isInitialized() && isSyncResolveReady()) {
setState(State::SyncResolved);
}
@@ -414,14 +399,14 @@ bool Asset::startSynchronizations() {
}
bool Asset::cancelAllSynchronizations() {
bool cancelledAnySync = false;
for (const std::shared_ptr<Asset>& child : childAssets()) {
const bool cancelled = child->cancelAllSynchronizations();
if (cancelled) {
cancelledAnySync = true;
}
}
for (const std::shared_ptr<ResourceSynchronization>& s : ownSynchronizations()) {
std::vector<Asset*> children = childAssets();
bool cancelledAnySync = std::any_of(
children.cbegin(),
children.cend(),
std::mem_fn(&Asset::cancelAllSynchronizations)
);
for (const std::shared_ptr<ResourceSynchronization>& s : _synchronizations) {
if (s->isSyncing()) {
cancelledAnySync = true;
s->cancel();
@@ -438,14 +423,15 @@ bool Asset::cancelUnwantedSynchronizations() {
if (hasSyncingOrResolvedParent()) {
return false;
}
bool cancelledAnySync = false;
for (const std::shared_ptr<Asset>& child : childAssets()) {
bool cancelled = child->cancelUnwantedSynchronizations();
if (cancelled) {
cancelledAnySync = true;
}
}
for (const std::shared_ptr<ResourceSynchronization>& s : ownSynchronizations()) {
const std::vector<Asset*>& children = childAssets();
bool cancelledAnySync = std::any_of(
children.begin(),
children.end(),
std::mem_fn(&Asset::cancelUnwantedSynchronizations)
);
for (const std::shared_ptr<ResourceSynchronization>& s : _synchronizations) {
if (s->isSyncing()) {
cancelledAnySync = true;
s->cancel();
@@ -458,18 +444,13 @@ bool Asset::cancelUnwantedSynchronizations() {
return cancelledAnySync;
}
bool Asset::restartAllSynchronizations() {
cancelAllSynchronizations();
return startSynchronizations();
}
float Asset::requiredSynchronizationProgress() const {
const std::vector<std::shared_ptr<const Asset>>& assets = requiredSubTreeAssets();
std::vector<const Asset*> assets = requiredSubTreeAssets();
return syncProgress(assets);
}
float Asset::requestedSynchronizationProgress() {
const std::vector<std::shared_ptr<const Asset>>& assets = subTreeAssets();
std::vector<const Asset*> assets = subTreeAssets();
return syncProgress(assets);
}
@@ -478,7 +459,7 @@ bool Asset::load() {
return true;
}
bool loaded = loader()->loadAsset(shared_from_this());
const bool loaded = loader()->loadAsset(this);
setState(loaded ? State::Loaded : State::LoadingFailed);
return loaded;
}
@@ -491,11 +472,11 @@ void Asset::unload() {
setState(State::Unloaded);
loader()->unloadAsset(this);
for (const std::shared_ptr<Asset>& child : requiredAssets()) {
unrequire(child.get());
for (Asset* child : requiredAssets()) {
unrequire(child);
}
for (const std::shared_ptr<Asset>& child : requestedAssets()) {
unrequest(child.get());
for (Asset* child : requestedAssets()) {
unrequest(child);
}
}
@@ -537,12 +518,12 @@ bool Asset::initialize() {
"Failed to initialize asset {}; {}: {}", id(), e.component, e.message
));
// TODO: rollback;
setState(Asset::State::InitializationFailed);
setState(State::InitializationFailed);
return false;
}
// 4. Update state
setState(Asset::State::Initialized);
setState(State::Initialized);
// 5. Call dependency lua onInitialize of this and requirements
for (const std::shared_ptr<Asset>& child : _requiredAssets) {
@@ -552,13 +533,10 @@ bool Asset::initialize() {
catch (const ghoul::lua::LuaRuntimeException& e) {
LERROR(fmt::format(
"Failed to initialize required asset {} of {}; {}: {}",
child->id(),
id(),
e.component,
e.message
child->id(), id(), e.component, e.message
));
// TODO: rollback;
setState(Asset::State::InitializationFailed);
setState(State::InitializationFailed);
return false;
}
}
@@ -572,10 +550,7 @@ bool Asset::initialize() {
catch (const ghoul::lua::LuaRuntimeException& e) {
LERROR(fmt::format(
"Failed to initialize requested asset {} of {}; {}: {}",
child->id(),
id(),
e.component,
e.message
child->id(), id(), e.component, e.message
));
// TODO: rollback;
}
@@ -592,10 +567,7 @@ bool Asset::initialize() {
catch (const ghoul::lua::LuaRuntimeException& e) {
LERROR(fmt::format(
"Failed to initialize required asset {} of {}; {}: {}",
id(),
p->id(),
e.component,
e.message
id(), p->id(), e.component, e.message
));
// TODO: rollback;
}
@@ -678,7 +650,7 @@ void Asset::deinitialize() {
}
// 2 and 1. Deinitialize unwanted requirements and requests
for (const std::shared_ptr<Asset>& dependency : childAssets()) {
for (Asset* dependency : childAssets()) {
dependency->deinitializeIfUnwanted();
}
}
@@ -709,13 +681,11 @@ AssetLoader* Asset::loader() const {
bool Asset::requires(const Asset* asset) const {
const auto it = std::find_if(
_requiredAssets.begin(),
_requiredAssets.end(),
[asset](std::shared_ptr<Asset> dep) {
return dep.get() == asset;
}
_requiredAssets.cbegin(),
_requiredAssets.cend(),
[asset](const std::shared_ptr<Asset> dep) { return dep.get() == asset; }
);
return it != _requiredAssets.end();
return it != _requiredAssets.cend();
}
void Asset::require(std::shared_ptr<Asset> child) {
@@ -723,12 +693,12 @@ void Asset::require(std::shared_ptr<Asset> child) {
throw ghoul::RuntimeError("Cannot require child asset when already loaded");
}
const auto it = std::find(_requiredAssets.begin(), _requiredAssets.end(), child);
if (it != _requiredAssets.end()) {
const auto it = std::find(_requiredAssets.cbegin(), _requiredAssets.cend(), child);
if (it != _requiredAssets.cend()) {
// Do nothing if the requirement already exists.
return;
}
_requiredAssets.push_back(child);
child->_requiringAssets.push_back(shared_from_this());
@@ -761,12 +731,12 @@ void Asset::unrequire(Asset* child) {
}
const auto childIt = std::find_if(
_requiredAssets.begin(),
_requiredAssets.end(),
_requiredAssets.cbegin(),
_requiredAssets.cend(),
[child](const std::shared_ptr<Asset>& asset) { return asset.get() == child; }
);
if (childIt == _requiredAssets.end()) {
if (childIt == _requiredAssets.cend()) {
// Do nothing if the request node not exist.
return;
}
@@ -774,14 +744,11 @@ void Asset::unrequire(Asset* child) {
_requiredAssets.erase(childIt);
const auto parentIt = std::find_if(
child->_requiringAssets.begin(),
child->_requiringAssets.end(),
[this](std::weak_ptr<Asset> a) {
return a.lock().get() == this;
}
child->_requiringAssets.cbegin(),
child->_requiringAssets.cend(),
[this](const std::weak_ptr<Asset> a) { return a.lock().get() == this; }
);
if (parentIt == child->_requiringAssets.end()) {
if (parentIt == child->_requiringAssets.cend()) {
return;
}
@@ -793,12 +760,12 @@ void Asset::unrequire(Asset* child) {
}
void Asset::request(std::shared_ptr<Asset> child) {
const auto it = std::find(_requestedAssets.begin(), _requestedAssets.end(), child);
if (it != _requestedAssets.end()) {
const auto it = std::find(_requestedAssets.cbegin(), _requestedAssets.cend(), child);
if (it != _requestedAssets.cend()) {
// Do nothing if the request already exists.
return;
}
_requestedAssets.push_back(child);
child->_requestingAssets.push_back(shared_from_this());
@@ -817,12 +784,11 @@ void Asset::request(std::shared_ptr<Asset> child) {
void Asset::unrequest(Asset* child) {
const auto childIt = std::find_if(
_requestedAssets.begin(),
_requestedAssets.end(),
_requestedAssets.cbegin(),
_requestedAssets.cend(),
[child](const std::shared_ptr<Asset>& asset) { return asset.get() == child; }
);
if (childIt == _requestedAssets.end()) {
if (childIt == _requestedAssets.cend()) {
// Do nothing if the request node not exist.
return;
}
@@ -830,14 +796,11 @@ void Asset::unrequest(Asset* child) {
_requestedAssets.erase(childIt);
const auto parentIt = std::find_if(
child->_requestingAssets.begin(),
child->_requestingAssets.end(),
[this](std::weak_ptr<Asset> a) {
return a.lock().get() == this;
}
child->_requestingAssets.cbegin(),
child->_requestingAssets.cend(),
[this](const std::weak_ptr<Asset> a) { return a.lock().get() == this; }
);
if (parentIt == child->_requestingAssets.end()) {
if (parentIt == child->_requestingAssets.cend()) {
return;
}
@@ -850,83 +813,64 @@ void Asset::unrequest(Asset* child) {
bool Asset::requests(Asset* asset) const {
const auto it = std::find_if(
_requestedAssets.begin(),
_requestedAssets.end(),
[asset](const std::shared_ptr<Asset>& dep) {
return dep.get() == asset;
}
_requestedAssets.cbegin(),
_requestedAssets.cend(),
[asset](const std::shared_ptr<Asset>& dep) { return dep.get() == asset; }
);
return it != _requiredAssets.end();
return it != _requiredAssets.cend();
}
const std::vector<std::shared_ptr<Asset>>& Asset::requiredAssets() const {
return _requiredAssets;
std::vector<Asset*> Asset::requiredAssets() const {
std::vector<Asset*> res;
res.reserve(_requiredAssets.size());
for (const std::shared_ptr<Asset>& a : _requiredAssets) {
res.push_back(a.get());
}
return res;
}
std::vector<std::shared_ptr<Asset>> Asset::requiringAssets() const {
std::vector<std::shared_ptr<Asset>> assets;
assets.reserve(_requiringAssets.size());
std::vector<Asset*> Asset::requiringAssets() const {
std::vector<Asset*> res;
res.reserve(_requiringAssets.size());
for (const std::weak_ptr<Asset>& a : _requiringAssets) {
std::shared_ptr<Asset> shared = a.lock();
if (shared) {
assets.push_back(shared);
if (std::shared_ptr<Asset> shared = a.lock(); shared) {
res.push_back(shared.get());
}
}
return assets;
return res;
}
const std::vector<std::shared_ptr<Asset>>& Asset::requestedAssets() const {
return _requestedAssets;
std::vector<Asset*> Asset::requestedAssets() const {
std::vector<Asset*> res;
res.reserve(_requestedAssets.size());
for (const std::shared_ptr<Asset>& a : _requestedAssets) {
res.push_back(a.get());
}
return res;
}
std::vector<std::shared_ptr<Asset>> Asset::requestingAssets() const {
std::vector<std::shared_ptr<Asset>> assets;
assets.reserve(_requestingAssets.size());
std::vector<Asset*> Asset::requestingAssets() const {
std::vector<Asset*> res;
res.reserve(_requestingAssets.size());
for (const std::weak_ptr<Asset>& a : _requestingAssets) {
std::shared_ptr<Asset> shared = a.lock();
if (shared) {
assets.push_back(shared);
if (std::shared_ptr<Asset> shared = a.lock(); shared) {
res.push_back(shared.get());
}
}
return assets;
return res;
}
std::vector<std::shared_ptr<Asset>> Asset::childAssets() const {
std::vector<std::shared_ptr<Asset>> children;
std::vector<Asset*> Asset::childAssets() const {
std::vector<Asset*> children;
children.reserve(_requiredAssets.size() + _requestedAssets.size());
children.insert(children.end(), _requiredAssets.begin(), _requiredAssets.end());
children.insert(children.end(), _requestedAssets.begin(), _requestedAssets.end());
for (const std::shared_ptr<Asset>& a : _requiredAssets) {
children.push_back(a.get());
}
for (const std::shared_ptr<Asset>& a : _requestedAssets) {
children.push_back(a.get());
}
return children;
}
std::vector<std::shared_ptr<Asset>> Asset::parentAssets() const {
std::vector<std::shared_ptr<Asset>> parents;
std::vector<std::shared_ptr<Asset>> requiring = requiringAssets();
std::vector<std::shared_ptr<Asset>> requesting = requestingAssets();
parents.reserve(requiring.size() + requesting.size());
parents.insert(parents.end(), requiring.begin(), requiring.end());
parents.insert(parents.end(), requesting.begin(), requesting.end());
return parents;
}
bool Asset::isRequired() const {
return !_requiringAssets.empty();
}
bool Asset::isRequested() const {
return !_requestingAssets.empty();
}
bool Asset::shouldBeInitialized() const {
std::vector<std::shared_ptr<Asset>> parents = parentAssets();
const auto initializedAsset = std::find_if(
parents.begin(),
parents.end(),
[](const std::shared_ptr<Asset>& a) {
return a->state() == State::Initialized;
}
);
return initializedAsset != parents.end();
}
} // namespace openspace

View File

@@ -33,9 +33,9 @@
#include <ghoul/lua/luastate.h>
#include <ghoul/lua/lua_helper.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <ghoul/misc/defer.h>
#include "assetloader_lua.inl"
namespace {
@@ -55,6 +55,14 @@ namespace {
constexpr const char* DirectoryConstantName = "directory";
constexpr const char* FilePathConstantName = "filePath";
constexpr const char* MetaInformationKey = "meta";
constexpr const char* MetaInformationName = "Name";
constexpr const char* MetaInformationVersion = "Version";
constexpr const char* MetaInformationDescription = "Description";
constexpr const char* MetaInformationAuthor = "Author";
constexpr const char* MetaInformationURL = "URL";
constexpr const char* MetaInformationLicense = "License";
constexpr const char* ExportsTableName = "_exports";
constexpr const char* AssetTableName = "_asset";
constexpr const char* DependantsTableName = "_dependants";
@@ -64,7 +72,7 @@ namespace {
constexpr const char* AssetFileSuffix = "asset";
constexpr const char* SceneFileSuffix = "scene";
enum class PathType : int {
enum class PathType {
RelativeToAsset = 0,
RelativeToAssetRoot,
Absolute
@@ -85,7 +93,7 @@ namespace {
}
return PathType::RelativeToAssetRoot;
}
}
} // namespace
namespace openspace {
@@ -97,9 +105,9 @@ AssetLoader::AssetLoader(ghoul::lua::LuaState* luaState,
, _assetRootDirectory(std::move(assetRootDirectory))
, _luaState(luaState)
{
setCurrentAsset(_rootAsset);
setCurrentAsset(_rootAsset.get());
// Create _assets table.
// Create _assets table
lua_newtable(*_luaState);
_assetsTableRef = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
}
@@ -124,37 +132,35 @@ void AssetLoader::untrackAsset(Asset* asset) {
}
void AssetLoader::setUpAssetLuaTable(Asset* asset) {
/*
Set up lua table:
AssetInfo
|- Exports (table<name, exported data>)
|- Asset
| |- localResource
| |- syncedResource
| |- require
| |- request
| |- exists
| |- export
| |- onInitialize
| |- onDeinitialize
| |- directory
|- Dependants (table<dependant, Dependency dep>)
// Set up lua table:
// AssetInfo
// |- Exports (table<name, exported data>)
// |- Asset
// | |- localResource
// | |- syncedResource
// | |- require
// | |- request
// | |- exists
// | |- export
// | |- onInitialize
// | |- onDeinitialize
// | |- directory
// |- Dependants (table<dependant, Dependency dep>)
//
// where Dependency is a table:
// Dependency
// |- onInitialize
// |- onDeinitialize
where Dependency is a table:
Dependency
|- onInitialize
|- onDeinitialize
*/
int top = lua_gettop(*_luaState);
const int top = lua_gettop(*_luaState);
// Push the global table of AssetInfos to the lua stack.
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef);
int globalTableIndex = lua_gettop(*_luaState);
const int globalTableIndex = lua_gettop(*_luaState);
// Create a AssetInfo table for the current asset.
lua_newtable(*_luaState);
int assetInfoTableIndex = lua_gettop(*_luaState);
const int assetInfoTableIndex = lua_gettop(*_luaState);
// Register empty Exports table for the current asset.
// (string => exported object)
@@ -164,7 +170,7 @@ void AssetLoader::setUpAssetLuaTable(Asset* asset) {
// Create Asset table
// (string => lua functions)
lua_newtable(*_luaState);
int assetTableIndex = lua_gettop(*_luaState);
const int assetTableIndex = lua_gettop(*_luaState);
// Register local resource function
// string localResource(string path)
@@ -191,7 +197,7 @@ void AssetLoader::setUpAssetLuaTable(Asset* asset) {
lua_setfield(*_luaState, assetTableIndex, RequestFunctionName);
// Register exists function
// bool exsists(string path)
// bool exists(string path)
lua_pushlightuserdata(*_luaState, asset);
lua_pushcclosure(*_luaState, &assetloader::exists, 1);
lua_setfield(*_luaState, assetTableIndex, ExistsFunctionName);
@@ -239,10 +245,10 @@ void AssetLoader::setUpAssetLuaTable(Asset* asset) {
}
void AssetLoader::tearDownAssetLuaTable(Asset* asset) {
int top = lua_gettop(*_luaState);
const int top = lua_gettop(*_luaState);
// Push the global table of AssetInfos to the lua stack.
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef);
int globalTableIndex = lua_gettop(*_luaState);
const int globalTableIndex = lua_gettop(*_luaState);
lua_pushnil(*_luaState);
@@ -251,9 +257,9 @@ void AssetLoader::tearDownAssetLuaTable(Asset* asset) {
lua_settop(*_luaState, top);
}
bool AssetLoader::loadAsset(std::shared_ptr<Asset> asset) {
int top = lua_gettop(*_luaState);
std::shared_ptr<Asset> parentAsset = _currentAsset;
bool AssetLoader::loadAsset(Asset* asset) {
const int top = lua_gettop(*_luaState);
Asset* parentAsset = _currentAsset;
setCurrentAsset(asset);
defer {
@@ -270,7 +276,8 @@ bool AssetLoader::loadAsset(std::shared_ptr<Asset> asset) {
try {
ghoul::lua::runScriptFile(*_luaState, asset->assetFilePath());
} catch (const ghoul::lua::LuaRuntimeException& e) {
}
catch (const ghoul::lua::LuaRuntimeException& e) {
LERROR(fmt::format(
"Could not load asset '{}': {}", asset->assetFilePath(), e.message)
);
@@ -278,6 +285,35 @@ bool AssetLoader::loadAsset(std::shared_ptr<Asset> asset) {
return false;
}
// Extract meta information from the asset file if it was provided
// 1. Load the asset table
lua_getglobal(*_luaState, AssetGlobalVariableName);
ghoul_assert(lua_istable(*_luaState, -1), "Expected 'asset' table");
lua_getfield(*_luaState, -1, MetaInformationKey);
if (!lua_isnil(*_luaState, -1)) {
// The 'meta' object exist; quick sanity check that it is a table
if (!lua_istable(*_luaState, -1)) {
LWARNING(fmt::format(
"When loading asset '{}', encountered a '{}' entry that was not a table",
asset->assetFilePath(), MetaInformationKey
));
}
else {
// The 'meta' object exists and it is a table
ghoul::Dictionary metaDict;
ghoul::lua::luaDictionaryFromState(*_luaState, metaDict);
Asset::MetaInformation meta;
metaDict.getValue(MetaInformationName, meta.name);
metaDict.getValue(MetaInformationVersion, meta.version);
metaDict.getValue(MetaInformationDescription, meta.description);
metaDict.getValue(MetaInformationAuthor, meta.author);
metaDict.getValue(MetaInformationURL, meta.url);
metaDict.getValue(MetaInformationLicense, meta.license);
asset->setMetaInformation(std::move(meta));
}
}
lua_settop(*_luaState, top);
return true;
}
@@ -293,14 +329,18 @@ void AssetLoader::unloadAsset(Asset* asset) {
}
_onDeinitializationFunctionRefs[asset].clear();
for (const auto& it : _onDependencyInitializationFunctionRefs[asset]) {
for (const std::pair<const Asset*, std::vector<int>>& it :
_onDependencyInitializationFunctionRefs[asset])
{
for (int ref : it.second) {
luaL_unref(*_luaState, LUA_REGISTRYINDEX, ref);
}
}
_onDependencyInitializationFunctionRefs.erase(asset);
for (const auto& it : _onDependencyDeinitializationFunctionRefs[asset]) {
for (const std::pair<Asset*, std::vector<int>>& it :
_onDependencyDeinitializationFunctionRefs[asset])
{
for (int ref : it.second) {
luaL_unref(*_luaState, LUA_REGISTRYINDEX, ref);
}
@@ -330,60 +370,54 @@ std::string AssetLoader::generateAssetPath(const std::string& baseDirectory,
// Construct the full path including the .asset extension
std::string assetSuffix = std::string(".") + AssetFileSuffix;
bool hasAssetSuffix =
const bool hasAssetSuffix =
(assetPath.size() > assetSuffix.size()) &&
(assetPath.substr(assetPath.size() - assetSuffix.size()) == assetSuffix);
std::string fullAssetPath =
const std::string fullAssetPath =
hasAssetSuffix ?
prefix + assetPath :
prefix + assetPath + assetSuffix;
bool fullAssetPathExists = FileSys.fileExists(FileSys.absPath(fullAssetPath));
// Construct the full path including the .scene extension
std::string sceneSuffix = std::string(".") + SceneFileSuffix;
bool hasSceneSuffix =
const std::string sceneSuffix = std::string(".") + SceneFileSuffix;
const bool hasSceneSuffix =
(assetPath.size() > sceneSuffix.size()) &&
(assetPath.substr(assetPath.size() - sceneSuffix.size()) == sceneSuffix);
std::string fullScenePath =
const std::string fullScenePath =
hasSceneSuffix ?
prefix + assetPath :
prefix + assetPath + sceneSuffix;
bool fullScenePathExists = FileSys.fileExists(FileSys.absPath(fullScenePath));
const bool fullScenePathExists = FileSys.fileExists(FileSys.absPath(fullScenePath));
if (fullAssetPathExists && fullScenePathExists) {
LWARNING(
fmt::format(
"'{}' and '{}' file found with non-specific request '{}'. Loading '{}'. "
"Explicitly add extension to suppress this warning.",
fullAssetPath,
fullScenePath,
prefix + assetPath,
fullAssetPath
)
);
LWARNING(fmt::format(
"'{}' and '{}' file found with non-specific request '{}'. Loading '{}'. "
"Explicitly add extension to suppress this warning.",
fullAssetPath, fullScenePath, prefix + assetPath, fullAssetPath
));
return ghoul::filesystem::File(FileSys.absPath(fullAssetPath));
return FileSys.absPath(fullAssetPath);
}
if (fullScenePathExists) {
return ghoul::filesystem::File(FileSys.absPath(fullScenePath));
return FileSys.absPath(fullScenePath);
}
// We don't check whether the file exists here as the error will be more
// comprehensively logged by Lua either way
return ghoul::filesystem::File(FileSys.absPath(fullAssetPath));
return FileSys.absPath(fullAssetPath);
}
std::shared_ptr<Asset> AssetLoader::getAsset(std::string name) {
std::shared_ptr<Asset> AssetLoader::getAsset(const std::string& name) {
ghoul::filesystem::Directory directory = currentDirectory();
std::string path = generateAssetPath(directory, std::move(name));
const std::string path = generateAssetPath(directory, name);
// Check if asset is already loaded.
const auto it = _trackedAssets.find(path);
if (it != _trackedAssets.end()) {
std::shared_ptr<Asset> a = it->second.lock();
if (a != nullptr) {
if (std::shared_ptr<Asset> a = it->second.lock(); a != nullptr) {
return a;
}
}
@@ -401,7 +435,7 @@ std::shared_ptr<Asset> AssetLoader::getAsset(std::string name) {
int AssetLoader::onInitializeLua(Asset* asset) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 1, "lua::onInitialize");
int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
const int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
_onInitializationFunctionRefs[asset].push_back(referenceIndex);
lua_settop(*_luaState, 0);
@@ -411,7 +445,7 @@ int AssetLoader::onInitializeLua(Asset* asset) {
int AssetLoader::onDeinitializeLua(Asset* asset) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 1, "lua::onDeinitialize");
int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
const int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
_onDeinitializationFunctionRefs[asset].push_back(referenceIndex);
lua_settop(*_luaState, 0);
@@ -421,9 +455,8 @@ int AssetLoader::onDeinitializeLua(Asset* asset) {
int AssetLoader::onInitializeDependencyLua(Asset* dependant, Asset* dependency) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 1, "lua::onInitializeDependency");
int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
_onDependencyInitializationFunctionRefs[dependant][dependency]
.push_back(referenceIndex);
const int refIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
_onDependencyInitializationFunctionRefs[dependant][dependency].push_back(refIndex);
lua_settop(*_luaState, 0);
return 0;
@@ -432,24 +465,16 @@ int AssetLoader::onInitializeDependencyLua(Asset* dependant, Asset* dependency)
int AssetLoader::onDeinitializeDependencyLua(Asset* dependant, Asset* dependency) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 1, "lua::onDeinitializeDependency");
int referenceIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
_onDependencyDeinitializationFunctionRefs[dependant][dependency]
.push_back(referenceIndex);
const int refIndex = luaL_ref(*_luaState, LUA_REGISTRYINDEX);
_onDependencyDeinitializationFunctionRefs[dependant][dependency].push_back(refIndex);
lua_settop(*_luaState, 0);
return 0;
}
std::shared_ptr<Asset> AssetLoader::require(const std::string& identifier) {
std::shared_ptr<Asset> asset = getAsset(identifier);
std::shared_ptr<Asset> dependant = _currentAsset;
dependant->require(asset);
return asset;
}
std::shared_ptr<Asset> AssetLoader::request(const std::string& identifier) {
std::shared_ptr<Asset> asset = getAsset(identifier);
std::shared_ptr<Asset> parent = _currentAsset;
Asset* parent = _currentAsset;
parent->request(asset);
assetRequested(parent, asset);
return asset;
@@ -457,7 +482,7 @@ std::shared_ptr<Asset> AssetLoader::request(const std::string& identifier) {
void AssetLoader::unrequest(const std::string& identifier) {
std::shared_ptr<Asset> asset = has(identifier);
std::shared_ptr<Asset> parent = _currentAsset;
Asset* parent = _currentAsset;
parent->unrequest(asset.get());
assetUnrequested(parent, asset);
}
@@ -472,13 +497,12 @@ ghoul::filesystem::Directory AssetLoader::currentDirectory() const {
}
std::shared_ptr<Asset> AssetLoader::add(const std::string& identifier) {
setCurrentAsset(_rootAsset);
setCurrentAsset(_rootAsset.get());
return request(identifier);
}
void AssetLoader::remove(const std::string& identifier) {
setCurrentAsset(_rootAsset);
setCurrentAsset(_rootAsset.get());
unrequest(identifier);
}
@@ -493,12 +517,12 @@ std::shared_ptr<Asset> AssetLoader::has(const std::string& identifier) const {
return it->second.lock();
}
ghoul::lua::LuaState* AssetLoader::luaState() {
return _luaState;
const Asset& AssetLoader::rootAsset() const {
return *_rootAsset;
}
std::shared_ptr<Asset> AssetLoader::rootAsset() const {
return _rootAsset;
Asset& AssetLoader::rootAsset() {
return *_rootAsset;
}
const std::string& AssetLoader::assetRootDirectory() const {
@@ -520,7 +544,7 @@ void AssetLoader::callOnInitialize(Asset* asset) {
}
void AssetLoader::callOnDeinitialize(Asset * asset) {
std::vector<int>& funs = _onDeinitializationFunctionRefs[asset];
const std::vector<int>& funs = _onDeinitializationFunctionRefs[asset];
for (auto it = funs.rbegin(); it != funs.rend(); it++) {
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, *it);
if (lua_pcall(*_luaState, 0, 0, 0) != LUA_OK) {
@@ -553,7 +577,9 @@ void AssetLoader::callOnDependencyInitialize(Asset* asset, Asset* dependant) {
}
void AssetLoader::callOnDependencyDeinitialize(Asset* asset, Asset* dependant) {
std::vector<int>& funs = _onDependencyDeinitializationFunctionRefs[dependant][asset];
const std::vector<int>& funs =
_onDependencyDeinitializationFunctionRefs[dependant][asset];
for (auto it = funs.rbegin(); it != funs.rend(); it++) {
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, *it);
if (lua_pcall(*_luaState, 0, 0, 0) != LUA_OK) {
@@ -571,14 +597,16 @@ void AssetLoader::callOnDependencyDeinitialize(Asset* asset, Asset* dependant) {
int AssetLoader::localResourceLua(Asset* asset) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 1, "lua::localResourceLua");
std::string resourceName = ghoul::lua::value<std::string>(
std::string name = ghoul::lua::value<std::string>(
*_luaState,
1,
ghoul::lua::PopValue::Yes
);
std::string resolved = asset->resolveLocalResource(resourceName);
lua_pushstring(*_luaState, resolved.c_str());
const std::string resolvedName =
asset->assetDirectory() + ghoul::filesystem::FileSystem::PathSeparator + name;
lua_pushstring(*_luaState, resolvedName.c_str());
ghoul_assert(lua_gettop(*_luaState) == 1, "Incorrect number of items left on stack");
return 1;
@@ -590,12 +618,12 @@ int AssetLoader::syncedResourceLua(Asset* asset) {
ghoul::Dictionary d;
ghoul::lua::luaDictionaryFromState(*_luaState, d);
std::shared_ptr<ResourceSynchronization> sync =
std::unique_ptr<ResourceSynchronization> sync =
ResourceSynchronization::createFromDictionary(d);
std::string absolutePath = sync->directory();
const std::string absolutePath = sync->directory();
asset->addSynchronization(sync);
asset->addSynchronization(std::move(sync));
lua_settop(*_luaState, 0);
lua_pushstring(*_luaState, absolutePath.c_str());
@@ -604,13 +632,13 @@ int AssetLoader::syncedResourceLua(Asset* asset) {
return 1;
}
void AssetLoader::setCurrentAsset(std::shared_ptr<Asset> asset) {
int top = lua_gettop(*_luaState);
void AssetLoader::setCurrentAsset(Asset* asset) {
const int top = lua_gettop(*_luaState);
_currentAsset = asset;
// Set `asset` lua global to point to the current asset table
if (asset == _rootAsset) {
if (asset == _rootAsset.get()) {
lua_pushnil(*_luaState);
lua_setglobal(*_luaState, AssetGlobalVariableName);
lua_settop(*_luaState, top);
@@ -631,7 +659,8 @@ int AssetLoader::requireLua(Asset* dependant) {
std::string assetName = luaL_checkstring(*_luaState, 1);
lua_settop(*_luaState, 0);
std::shared_ptr<Asset> dependency = require(assetName);
std::shared_ptr<Asset> dependency = getAsset(assetName);
_currentAsset->require(dependency);
if (!dependency) {
return ghoul::lua::luaError(
@@ -646,14 +675,14 @@ int AssetLoader::requireLua(Asset* dependant) {
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef);
lua_getfield(*_luaState, -1, dependency->id().c_str());
lua_getfield(*_luaState, -1, ExportsTableName);
int exportsTableIndex = lua_gettop(*_luaState);
const int exportsTableIndex = lua_gettop(*_luaState);
// Get the dependency table
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef);
lua_getfield(*_luaState, -1, dependency->id().c_str());
lua_getfield(*_luaState, -1, DependantsTableName);
lua_getfield(*_luaState, -1, dependant->id().c_str());
int dependencyTableIndex = lua_gettop(*_luaState);
const int dependencyTableIndex = lua_gettop(*_luaState);
lua_pushvalue(*_luaState, exportsTableIndex);
lua_pushvalue(*_luaState, dependencyTableIndex);
@@ -669,7 +698,7 @@ int AssetLoader::requireLua(Asset* dependant) {
int AssetLoader::requestLua(Asset* parent) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 1, "lua::request");
std::string assetName = luaL_checkstring(*_luaState, 1);
const std::string assetName = luaL_checkstring(*_luaState, 1);
lua_settop(*_luaState, 0);
std::shared_ptr<Asset> child = request(assetName);
@@ -681,7 +710,7 @@ int AssetLoader::requestLua(Asset* parent) {
lua_getfield(*_luaState, -1, child->id().c_str());
lua_getfield(*_luaState, -1, DependantsTableName);
lua_getfield(*_luaState, -1, parent->id().c_str());
int dependencyTableIndex = lua_gettop(*_luaState);
const int dependencyTableIndex = lua_gettop(*_luaState);
lua_pushvalue(*_luaState, dependencyTableIndex);
@@ -695,10 +724,10 @@ int AssetLoader::requestLua(Asset* parent) {
int AssetLoader::existsLua(Asset*) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 1, "lua::exists");
std::string assetName = luaL_checkstring(*_luaState, 1);
const std::string assetName = luaL_checkstring(*_luaState, 1);
ghoul::filesystem::Directory directory = currentDirectory();
std::string path = generateAssetPath(directory, assetName);
const ghoul::filesystem::Directory directory = currentDirectory();
const std::string path = generateAssetPath(directory, assetName);
lua_settop(*_luaState, 0);
lua_pushboolean(*_luaState, FileSys.fileExists(path));
@@ -709,12 +738,12 @@ int AssetLoader::existsLua(Asset*) {
int AssetLoader::exportAssetLua(Asset* asset) {
ghoul::lua::checkArgumentsAndThrow(*_luaState, 2, "lua::exportAsset");
std::string exportName = luaL_checkstring(*_luaState, 1);
const std::string exportName = luaL_checkstring(*_luaState, 1);
lua_rawgeti(*_luaState, LUA_REGISTRYINDEX, _assetsTableRef);
lua_getfield(*_luaState, -1, asset->id().c_str());
lua_getfield(*_luaState, -1, ExportsTableName);
int exportsTableIndex = lua_gettop(*_luaState);
const int exportsTableIndex = lua_gettop(*_luaState);
// push the second argument
lua_pushvalue(*_luaState, 2);
@@ -726,7 +755,7 @@ int AssetLoader::exportAssetLua(Asset* asset) {
}
void AssetLoader::addLuaDependencyTable(Asset* dependant, Asset* dependency) {
int top = lua_gettop(*_luaState);
const int top = lua_gettop(*_luaState);
const std::string dependantId = dependant->id();
const std::string dependencyId = dependency->id();
@@ -765,13 +794,9 @@ void AssetLoader::addLuaDependencyTable(Asset* dependant, Asset* dependency) {
}
void AssetLoader::addAssetListener(AssetListener* listener) {
auto it = std::find(
_assetListeners.begin(),
_assetListeners.end(),
listener
);
const auto it = std::find(_assetListeners.cbegin(), _assetListeners.cend(), listener);
if (it == _assetListeners.end()) {
if (it == _assetListeners.cend()) {
_assetListeners.push_back(listener);
}
}
@@ -784,23 +809,19 @@ void AssetLoader::removeAssetListener(AssetListener* listener) {
));
}
void AssetLoader::assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state) {
void AssetLoader::assetStateChanged(Asset* asset, Asset::State state) {
for (AssetListener* listener : _assetListeners) {
listener->assetStateChanged(asset, state);
}
}
void AssetLoader::assetRequested(std::shared_ptr<Asset> parent,
std::shared_ptr<Asset> child)
{
void AssetLoader::assetRequested(Asset* parent, std::shared_ptr<Asset> child) {
for (AssetListener* listener : _assetListeners) {
listener->assetRequested(parent, child);
}
}
void AssetLoader::assetUnrequested(std::shared_ptr<Asset> parent,
std::shared_ptr<Asset> child)
{
void AssetLoader::assetUnrequested(Asset* parent, std::shared_ptr<Asset> child) {
for (AssetListener* listener : _assetListeners) {
listener->assetUnrequested(parent, child);
}

View File

@@ -108,10 +108,6 @@ int syncedResource(lua_State* state) {
return asset->loader()->syncedResourceLua(asset);
}
int noOperation(lua_State*) {
return 0;
}
int exportAsset(lua_State* state) {
Asset* asset = reinterpret_cast<Asset*>(lua_touserdata(state, lua_upvalueindex(1)));
return asset->loader()->exportAssetLua(asset);

View File

@@ -36,23 +36,19 @@
namespace openspace {
AssetManager::AssetManager(std::unique_ptr<AssetLoader> loader,
std::unique_ptr<SynchronizationWatcher> syncWatcher)
: _synchronizationWatcher(std::move(syncWatcher))
, _assetLoader(std::move(loader))
AssetManager::AssetManager(ghoul::lua::LuaState* state, std::string assetRootDirectory)
: _assetLoader(state, &_synchronizationWatcher, std::move(assetRootDirectory))
{}
void AssetManager::initialize() {
_assetLoader->addAssetListener(this);
std::shared_ptr<Asset> rootAsset = _assetLoader->rootAsset();
rootAsset->initialize();
_assetLoader.addAssetListener(this);
_assetLoader.rootAsset().initialize();
}
void AssetManager::deinitialize() {
_assetLoader->rootAsset()->deinitialize();
_assetLoader->rootAsset()->unload();
_assetLoader->removeAssetListener(this);
_assetLoader = nullptr;
_assetLoader.rootAsset().deinitialize();
_assetLoader.rootAsset().unload();
_assetLoader.removeAssetListener(this);
}
bool AssetManager::update() {
@@ -63,36 +59,36 @@ bool AssetManager::update() {
const std::string& path = c.first;
const bool add = c.second;
if (add) {
std::shared_ptr<Asset> asset = _assetLoader->add(path);
_assetLoader.add(path);
}
}
// Remove assets
for (const std::pair<const std::string, bool>& c : _pendingStateChangeCommands) {
const std::string& path = c.first;
const bool remove = !c.second;
if (remove && _assetLoader->has(path)) {
_assetLoader->remove(path);
if (remove && _assetLoader.has(path)) {
_assetLoader.remove(path);
}
}
_pendingStateChangeCommands.clear();
// Change state based on synchronizations
_synchronizationWatcher->notify();
_synchronizationWatcher.notify();
return false;
}
void AssetManager::assetStateChanged(std::shared_ptr<Asset>, Asset::State) {
void AssetManager::assetStateChanged(Asset*, Asset::State) {
// Potential todo: notify user about asset stage change
//LINFO(asset->id() << " changed state to " << static_cast<int>(state));
}
void AssetManager::assetRequested(std::shared_ptr<Asset>, std::shared_ptr<Asset>) {
void AssetManager::assetRequested(Asset*, std::shared_ptr<Asset>) {
// Potential todo: notify user about asset request
//LINFO(parent->id() << " requested " << child->id());
}
void AssetManager::assetUnrequested(std::shared_ptr<Asset>, std::shared_ptr<Asset>) {
void AssetManager::assetUnrequested(Asset*, std::shared_ptr<Asset>) {
// Potential todo: notify user about asset unrequest
//LINFO(parent->id() << " unrequested " << child->id());
}
@@ -109,16 +105,17 @@ void AssetManager::removeAll() {
ZoneScoped
_pendingStateChangeCommands.clear();
std::vector<std::shared_ptr<Asset>> allAssets =
_assetLoader->rootAsset()->requestedAssets();
for (const std::shared_ptr<Asset>& a : allAssets) {
for (const Asset* a : _assetLoader.rootAsset().requestedAssets()) {
_pendingStateChangeCommands[a->assetFilePath()] = false;
}
}
std::shared_ptr<Asset> AssetManager::rootAsset() {
return _assetLoader->rootAsset();
const Asset& AssetManager::rootAsset() const {
return _assetLoader.rootAsset();
}
Asset& AssetManager::rootAsset() {
return _assetLoader.rootAsset();
}
scripting::LuaLibrary AssetManager::luaLibrary() {
@@ -144,4 +141,4 @@ scripting::LuaLibrary AssetManager::luaLibrary() {
};
}
}
} // namespace openspace

View File

@@ -146,10 +146,6 @@ void Scene::updateNodeRegistry() {
_dirtyNodeRegistry = false;
}
void Scene::addSceneLicense(SceneLicense license) {
_licenses.push_back(std::move(license));
}
void Scene::sortTopologically() {
_topologicallySortedNodes.insert(
_topologicallySortedNodes.end(),
@@ -597,11 +593,6 @@ const std::vector<Scene::InterestingTime>& Scene::interestingTimes() const {
return _interestingTimes;
}
std::string Scene::generateSceneLicenseDocumentationJson() {
SceneLicenseWriter writer(_licenses);
return writer.generateJson();
}
scripting::LuaLibrary Scene::luaLibrary() {
return {
"",

View File

@@ -1,87 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2020 *
* *
* 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/scenelicense.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
namespace {
constexpr const char* LicenseKeyName = "Name";
constexpr const char* LicenseKeyAttribution = "Attribution";
constexpr const char* LicenseKeyUrl = "URL";
constexpr const char* LicenseKeyLicenseText = "License";
} // namespace
namespace openspace {
documentation::Documentation SceneLicense::Documentation() {
using namespace documentation;
return {
"License Information",
"core_license",
{
{
LicenseKeyName,
new StringVerifier,
Optional::No,
"A short, descriptive name for the license employed for this node."
},
{
LicenseKeyAttribution,
new StringVerifier,
Optional::No,
"The organization that shall be attributed to the licensed content."
},
{
LicenseKeyUrl,
new StringVerifier,
Optional::Yes,
"The URL pointing to the original license."
},
{
LicenseKeyLicenseText,
new StringVerifier,
Optional::No,
"The full text of the license agreements."
}
}
};
}
SceneLicense::SceneLicense(const ghoul::Dictionary& dictionary, std::string m)
: module(std::move(m))
{
ghoul_assert(!module.empty(), "Module name must not be empty");
documentation::testSpecificationAndThrow(Documentation(), dictionary, "SceneLicense");
name = dictionary.value<std::string>(LicenseKeyName);
attribution = dictionary.value<std::string>(LicenseKeyAttribution);
dictionary.getValue(LicenseKeyUrl, url);
licenseText = dictionary.value<std::string>(LicenseKeyLicenseText);
}
} // namespace openspace

View File

@@ -24,13 +24,17 @@
#include <openspace/scene/scenelicensewriter.h>
#include <openspace/scene/scenelicense.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/scene/asset.h>
#include <openspace/scene/assetmanager.h>
#include <ghoul/fmt.h>
#include <sstream>
namespace openspace {
SceneLicenseWriter::SceneLicenseWriter(std::vector<SceneLicense> licenses)
SceneLicenseWriter::SceneLicenseWriter()
: DocumentationGenerator(
"Scene Licenses",
"sceneLicense",
@@ -38,24 +42,49 @@ SceneLicenseWriter::SceneLicenseWriter(std::vector<SceneLicense> licenses)
{ "sceneLicenseTemplate", "${WEB}/documentation/scenelicense.hbs" }
}
)
, _licenses(std::move(licenses))
{}
std::string SceneLicenseWriter::generateJson() const {
std::stringstream json;
json << "[";
for (const SceneLicense& license : _licenses) {
std::vector<const Asset*> assets =
global::openSpaceEngine.assetManager().rootAsset().subTreeAssets();
int metaTotal = 0;
for (const Asset* asset : assets) {
std::optional<Asset::MetaInformation> meta = asset->metaInformation();
if (!meta.has_value()) {
continue;
}
metaTotal++;
}
int metaCount = 0;
for (const Asset* asset : assets) {
std::optional<Asset::MetaInformation> meta = asset->metaInformation();
if (!meta.has_value()) {
continue;
}
constexpr const char* replStr = R"("{}": "{}", )";
constexpr const char* replStr2 = R"("{}": "{}")";
json << "{";
json << fmt::format(replStr, "module", escapedJson(license.module));
json << fmt::format(replStr, "name", escapedJson(license.name));
json << fmt::format(replStr, "attribution", escapedJson(license.attribution));
json << fmt::format(replStr, "url", escapedJson(license.url));
json << fmt::format(replStr2, "licenseText", escapedJson(license.licenseText));
//json << fmt::format(replStr, "module", escapedJson(license.module));
json << fmt::format(replStr, "name", escapedJson(meta->name));
json << fmt::format(replStr, "version", escapedJson(meta->version));
json << fmt::format(replStr, "description", escapedJson(meta->description));
//json << fmt::format(replStr, "attribution", escapedJson(license.attribution));
json << fmt::format(replStr, "author", escapedJson(meta->author));
json << fmt::format(replStr, "url", escapedJson(meta->url));
//json << fmt::format(replStr2, "licenseText", escapedJson(license.licenseText));
json << fmt::format(replStr, "license", escapedJson(meta->license));
json << fmt::format(replStr2, "path", escapedJson(asset->assetFilePath()));
json << "}";
if (&license != &(_licenses.back())) {
metaCount++;
if (metaCount != metaTotal) {
json << ",";
}
}

View File

@@ -95,15 +95,15 @@ ResourceSynchronization::State ResourceSynchronization::state() const {
return _state;
}
bool ResourceSynchronization::isResolved() {
bool ResourceSynchronization::isResolved() const {
return _state == State::Resolved;
}
bool ResourceSynchronization::isRejected() {
bool ResourceSynchronization::isRejected() const {
return _state == State::Rejected;
}
bool ResourceSynchronization::isSyncing() {
bool ResourceSynchronization::isSyncing() const {
return _state == State::Syncing;
}

View File

@@ -32,21 +32,16 @@ SynchronizationWatcher::WatchHandle SynchronizationWatcher::watchSynchronization
std::shared_ptr<ResourceSynchronization> synchronization,
ResourceSynchronization::StateChangeCallback callback)
{
std::lock_guard<std::mutex> guard(_mutex);
std::lock_guard guard(_mutex);
WatchHandle watchHandle = generateWatchHandle();
WatchHandle watchHandle = nextWatchHandle++;
ResourceSynchronization::CallbackHandle cbh = synchronization->addStateChangeCallback(
[this, synchronization, watchHandle, cb = std::move(callback)]
(ResourceSynchronization::State state)
{
std::lock_guard<std::mutex> g(_mutex);
_pendingNotifications.push_back({
synchronization,
state,
watchHandle,
cb
});
_pendingNotifications.push_back({ synchronization, state, watchHandle, cb });
}
);
@@ -56,7 +51,7 @@ SynchronizationWatcher::WatchHandle SynchronizationWatcher::watchSynchronization
}
void SynchronizationWatcher::unwatchSynchronization(WatchHandle watchHandle) {
std::lock_guard<std::mutex> guard(_mutex);
std::lock_guard guard(_mutex);
const auto it = _watchedSyncs.find(watchHandle);
if (it == _watchedSyncs.end()) {
@@ -84,7 +79,7 @@ void SynchronizationWatcher::unwatchSynchronization(WatchHandle watchHandle) {
void SynchronizationWatcher::notify() {
std::vector<NotificationData> notifications;
{
std::lock_guard<std::mutex> guard(_mutex);
std::lock_guard guard(_mutex);
notifications = _pendingNotifications;
_pendingNotifications.clear();
}
@@ -98,8 +93,4 @@ void SynchronizationWatcher::notify() {
}
}
SynchronizationWatcher::WatchHandle SynchronizationWatcher::generateWatchHandle() {
return nextWatchHandle++;
}
} // namespace openspace