mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-22 04:49:12 -06:00
Improve asset lua interface. Simplify scene loading.
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
export ({
|
||||
SceneGraphNodes = {
|
||||
}
|
||||
})
|
||||
@@ -1,8 +1,9 @@
|
||||
Sun = import('sun');
|
||||
local Sun = asset.import('sun');
|
||||
local AssetHelper = asset.import('assethelper')
|
||||
|
||||
EarthBarycenter = {
|
||||
asset.EarthBarycenter = {
|
||||
Name = "EarthBarycenter",
|
||||
Parent = Sun.SceneGraphNodes.SolarSystemBarycenter.Name,
|
||||
Parent = Sun.SolarSystemBarycenter.Name,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "SpiceTranslation",
|
||||
@@ -13,22 +14,22 @@ EarthBarycenter = {
|
||||
}
|
||||
}
|
||||
|
||||
EarthInertial = {
|
||||
asset.EarthInertial = {
|
||||
-- The default reference frame for Earth-orbiting satellites
|
||||
Name = "EarthInertial",
|
||||
Parent = EarthBarycenter.Name,
|
||||
Parent = asset.EarthBarycenter.Name,
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "J2000",
|
||||
DestinationFrame = "GALACTIC",
|
||||
}
|
||||
},z
|
||||
},
|
||||
}
|
||||
|
||||
Earth = {
|
||||
asset.Earth = {
|
||||
Name = "Earth",
|
||||
Parent = EarthBarycenter.Name,
|
||||
Parent = asset.EarthBarycenter.Name,
|
||||
Renderable = {
|
||||
Type = "RenderablePlanet",
|
||||
Frame = "IAU_EARTH",
|
||||
@@ -40,10 +41,10 @@ Earth = {
|
||||
},
|
||||
Textures = {
|
||||
Type = "simple",
|
||||
Color = syncedResource("textures/earth_bluemarble.jpg"),
|
||||
--Color = Sun.syncedResource("textures/sun.jpg"),
|
||||
Night = syncedResource("textures/earth_night.jpg"),
|
||||
Height = syncedResource("textures/earth_bluemarble_height.jpg")
|
||||
--Color = resource("textures/earth_bluemarble.jpg"),
|
||||
Color = asset.syncedResource("textures/earth_bluemarble.jpg"),
|
||||
Night = asset.syncedResource("textures/earth_night.jpg"),
|
||||
Height = asset.syncedResource("textures/earth_bluemarble_height.jpg")
|
||||
},
|
||||
Atmosphere = {
|
||||
Type = "Nishita", -- for example, values missing etc etc
|
||||
@@ -67,9 +68,9 @@ Earth = {
|
||||
|
||||
}
|
||||
|
||||
EarthTrail = {
|
||||
asset.EarthTrail = {
|
||||
Name = "EarthTrail",
|
||||
Parent = Sun.SceneGraphNodes.SolarSystemBarycenter.Name,
|
||||
Parent = Sun.SolarSystemBarycenter.Name,
|
||||
Renderable = {
|
||||
Type = "RenderableTrailOrbit",
|
||||
Translation = {
|
||||
@@ -88,25 +89,24 @@ EarthTrail = {
|
||||
GuiName = "/Solar/EarthTrail",
|
||||
}
|
||||
|
||||
EarthMarker = {
|
||||
asset.EarthMarker = {
|
||||
Name = "EarthMarker",
|
||||
Parent = Earth.Name,
|
||||
Parent = asset.Earth.Name,
|
||||
Renderable = {
|
||||
Type = "RenderablePlane",
|
||||
Size = 3.0E11,
|
||||
Origin = "Center",
|
||||
Billboard = true,
|
||||
Texture = syncedResource("textures/marker.png"),
|
||||
Texture = asset.syncedResource("textures/marker.png"),
|
||||
BlendMode = "Additive"
|
||||
}
|
||||
}
|
||||
|
||||
export({
|
||||
SceneGraphNodes = {
|
||||
EarthBarycenter = EarthBarycenter,
|
||||
EarthInertial = EarthInertial,
|
||||
Earth = Earth,
|
||||
EarthTrail = EarthTrail,
|
||||
EarthMarker = EarthMarker
|
||||
}
|
||||
|
||||
AssetHelper.registerSceneGraphNodes(asset, {
|
||||
asset.EarthBarycenter,
|
||||
asset.EarthInertial,
|
||||
asset.Earth,
|
||||
asset.EarthTrail,
|
||||
asset.EarthMarker
|
||||
})
|
||||
@@ -1,19 +1,20 @@
|
||||
Base = import('base')
|
||||
--local Base = asset.import('base')
|
||||
--BaseSpiceKernels = import('base-spice-kernels')
|
||||
local AssetHelper = asset.import('assethelper')
|
||||
|
||||
SolarSystem = {
|
||||
asset.SolarSystem = {
|
||||
Name = "SolarSystem",
|
||||
Parent = "Root"
|
||||
}
|
||||
|
||||
SolarSystemBarycenter = {
|
||||
asset.SolarSystemBarycenter = {
|
||||
Name = "SolarSystemBarycenter",
|
||||
Parent = SolarSystem.Name
|
||||
Parent = asset.SolarSystem.Name
|
||||
}
|
||||
|
||||
Sun = {
|
||||
asset.Sun = {
|
||||
Name = "Sun",
|
||||
Parent = SolarSystemBarycenter.Name,
|
||||
Parent = asset.SolarSystemBarycenter.Name,
|
||||
Renderable = {
|
||||
Type = "RenderablePlanet",
|
||||
Frame = "IAU_SUN",
|
||||
@@ -26,7 +27,7 @@ Sun = {
|
||||
},
|
||||
Textures = {
|
||||
Type = "simple",
|
||||
Color = syncedResource("textures/sun.jpg"),
|
||||
Color = asset.syncedResource("textures/sun.jpg"),
|
||||
},
|
||||
PerformShading = false,
|
||||
},
|
||||
@@ -45,15 +46,15 @@ Sun = {
|
||||
}
|
||||
}
|
||||
|
||||
SunGlare = {
|
||||
asset.SunGlare = {
|
||||
Name = "SunGlare",
|
||||
Parent = SolarSystemBarycenter.Name,
|
||||
Parent = asset.SolarSystemBarycenter.Name,
|
||||
Renderable = {
|
||||
Type = "RenderablePlane",
|
||||
Size = 1.3*10^10.5,
|
||||
Origin = "Center",
|
||||
Billboard = true,
|
||||
Texture = syncedResource("textures/sun-glare.png"),
|
||||
Texture = asset.syncedResource("textures/sun-glare.png"),
|
||||
BlendMode = "Additive"
|
||||
},
|
||||
Transform = {
|
||||
@@ -66,15 +67,15 @@ SunGlare = {
|
||||
}
|
||||
}
|
||||
|
||||
SunMarker = {
|
||||
asset.SunMarker = {
|
||||
Name = "SunMarker",
|
||||
Parent = Sun.Name,
|
||||
Parent = asset.Sun.Name,
|
||||
Renderable = {
|
||||
Type = "RenderablePlane",
|
||||
Size = 3.0E11,
|
||||
Origin = "Center",
|
||||
Billboard = true,
|
||||
Texture = syncedResource("textures/marker.png"),
|
||||
Texture = asset.syncedResource("textures/marker.png"),
|
||||
BlendMode = "Additive"
|
||||
},
|
||||
Transformation = {
|
||||
@@ -85,12 +86,10 @@ SunMarker = {
|
||||
}
|
||||
}
|
||||
|
||||
export ({
|
||||
SceneGraphNodes = {
|
||||
SolarSystem = SolarSystem,
|
||||
SolarSystemBarycenter = SolarSystemBarycenter,
|
||||
Sun = Sun,
|
||||
SunGlare = SunGlare,
|
||||
SunMarker = SunMarker
|
||||
}
|
||||
AssetHelper.registerSceneGraphNodes(asset, {
|
||||
asset.SolarSystem,
|
||||
asset.SolarSystemBarycenter,
|
||||
asset.Sun,
|
||||
asset.SunGlare,
|
||||
asset.SunMarker
|
||||
})
|
||||
@@ -55,8 +55,10 @@ class NetworkEngine;
|
||||
class ParallelConnection;
|
||||
class RenderEngine;
|
||||
class SettingsEngine;
|
||||
class SceneManager;
|
||||
class VirtualPropertyManager;
|
||||
class Scene;
|
||||
class AssetLoader;
|
||||
class SceneLoader;
|
||||
|
||||
class SyncEngine;
|
||||
class TimeManager;
|
||||
@@ -182,7 +184,9 @@ private:
|
||||
|
||||
// Components
|
||||
std::unique_ptr<ConfigurationManager> _configurationManager;
|
||||
std::unique_ptr<SceneManager> _sceneManager;
|
||||
std::unique_ptr<Scene> _scene;
|
||||
std::unique_ptr<AssetLoader> _assetLoader;
|
||||
std::unique_ptr<SceneLoader> _sceneLoader;
|
||||
std::unique_ptr<DownloadManager> _downloadManager;
|
||||
std::unique_ptr<LuaConsole> _console;
|
||||
std::unique_ptr<ModuleEngine> _moduleEngine;
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace openspace {
|
||||
|
||||
namespace assetloader {
|
||||
int importAsset(lua_State* state);
|
||||
int exportAsset(lua_State* state);
|
||||
int resolveLocalResource(lua_State* state);
|
||||
int resolveSyncedResource(lua_State* state);
|
||||
}
|
||||
@@ -70,16 +69,13 @@ public:
|
||||
friend int assetloader::resolveSyncedResource(lua_State* state);
|
||||
int resolveSyncedResourceLua();
|
||||
|
||||
friend int assetloader::exportAsset(lua_State* state);
|
||||
int exportAssetLua();
|
||||
|
||||
AssetLoader* _loader;
|
||||
std::string _directory;
|
||||
std::vector<Asset*> _dependencies;
|
||||
std::vector<Asset*> _dependants;
|
||||
};
|
||||
|
||||
AssetLoader(std::string assetRoot, std::string syncRoot);
|
||||
AssetLoader(ghoul::lua::LuaState* _luaState, std::string assetRoot, std::string syncRoot);
|
||||
~AssetLoader() = default;
|
||||
|
||||
|
||||
@@ -87,7 +83,7 @@ public:
|
||||
* Load an asset file.
|
||||
*/
|
||||
Asset* loadAsset(const std::string& identifier);
|
||||
ghoul::lua::LuaState& luaState();
|
||||
ghoul::lua::LuaState* luaState();
|
||||
ghoul::filesystem::Directory currentDirectory();
|
||||
Asset* rootAsset();
|
||||
const std::string& syncRoot();
|
||||
@@ -95,7 +91,7 @@ public:
|
||||
private:
|
||||
void pushAsset(Asset* asset);
|
||||
void popAsset();
|
||||
void updateGlobalLuaFunctions();
|
||||
void updateLuaGlobals();
|
||||
|
||||
std::unique_ptr<Asset> _rootAsset;
|
||||
std::map<std::string, std::unique_ptr<Asset>> _loadedAssets;
|
||||
@@ -106,7 +102,7 @@ private:
|
||||
friend int assetloader::importAsset(lua_State* state);
|
||||
int importAssetLua();
|
||||
|
||||
ghoul::lua::LuaState _luaState;
|
||||
ghoul::lua::LuaState* _luaState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -65,11 +65,6 @@ public:
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
/**
|
||||
* Initalizes the SceneGraph
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Clear the scene graph,
|
||||
* i.e. set the root node to nullptr and deallocate all scene graph nodes.
|
||||
@@ -137,6 +132,11 @@ public:
|
||||
*/
|
||||
const std::map<std::string, SceneGraphNode*>& nodesByName() const;
|
||||
|
||||
/**
|
||||
* Load a scene graph node from a dictionary and return it.
|
||||
*/
|
||||
SceneGraphNode* loadNode(const ghoul::Dictionary& nodeDictionary);
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to change the
|
||||
* scene graph. The functions contained are
|
||||
|
||||
@@ -47,37 +47,10 @@ public:
|
||||
/**
|
||||
* Load a scene file.
|
||||
*/
|
||||
std::unique_ptr<Scene> loadScene(const std::string& path);
|
||||
|
||||
/**
|
||||
* Import a directory of scene contents into an existing scene.
|
||||
*/
|
||||
std::vector<SceneGraphNode*> importDirectory(Scene& scene, const std::string& directory);
|
||||
|
||||
/**
|
||||
* Import a scene graph node from a dictionary into an existing scene.
|
||||
*/
|
||||
SceneGraphNode* importNodeDictionary(Scene& scene, const ghoul::Dictionary& dictionary);
|
||||
void loadScene(Scene* scene, const std::string& path);
|
||||
|
||||
private:
|
||||
struct LoadedNode {
|
||||
LoadedNode(
|
||||
const std::string& nodeName,
|
||||
const std::string& parentName,
|
||||
const std::vector<std::string>& deps,
|
||||
std::unique_ptr<SceneGraphNode> n
|
||||
)
|
||||
: name(nodeName)
|
||||
, parent(parentName)
|
||||
, dependencies(deps)
|
||||
, node(std::move(n)) {}
|
||||
|
||||
std::string name;
|
||||
std::string parent;
|
||||
std::vector<std::string> dependencies;
|
||||
std::unique_ptr<SceneGraphNode> node;
|
||||
};
|
||||
|
||||
|
||||
struct LoadedCamera {
|
||||
LoadedCamera(
|
||||
const std::string& parentName,
|
||||
@@ -89,30 +62,15 @@ private:
|
||||
std::unique_ptr<Camera> camera;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a scene graph node from a dictionary
|
||||
*/
|
||||
SceneLoader::LoadedNode loadNode(const ghoul::Dictionary& dictionary);
|
||||
|
||||
/**
|
||||
* Load a mod file.
|
||||
*/
|
||||
std::vector<SceneLoader::LoadedNode> loadAsset(const std::string& path, lua_State* luaState);
|
||||
|
||||
/**
|
||||
* Load a directory.
|
||||
*/
|
||||
std::vector<SceneLoader::LoadedNode> loadDirectory(const std::string& path, lua_State* luaState);
|
||||
void loadDirectory(const std::string& path);
|
||||
|
||||
/**
|
||||
* Load a camera from a dictionary
|
||||
*/
|
||||
SceneLoader::LoadedCamera loadCamera(const ghoul::Dictionary& dictionary);
|
||||
|
||||
/**
|
||||
* Add loaded nodes to an existing scene
|
||||
*/
|
||||
std::vector<SceneGraphNode*> addLoadedNodes(Scene& scene, std::vector<SceneLoader::LoadedNode>&& nodes);
|
||||
std::unique_ptr<SceneLoader::LoadedCamera> loadCamera(const ghoul::Dictionary& dictionary);
|
||||
|
||||
AssetLoader* _assetLoader;
|
||||
};
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_CORE___SCENEMANAGER___H__
|
||||
#define __OPENSPACE_CORE___SCENEMANAGER___H__
|
||||
|
||||
#include <openspace/scene/assetloader.h>
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class Scene;
|
||||
|
||||
class SceneManager {
|
||||
public:
|
||||
SceneManager(std::string assetRoot, std::string syncRoot);
|
||||
~SceneManager() = default;
|
||||
Scene* loadScene(const std::string& path);
|
||||
void unloadScene(Scene& scene);
|
||||
void unloadAll();
|
||||
private:
|
||||
std::vector<std::unique_ptr<Scene>> _scenes;
|
||||
AssetLoader _assetLoader;
|
||||
SceneLoader _sceneLoader;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __OPENSPACE_CORE___SCENEMANAGER___H__
|
||||
@@ -71,6 +71,7 @@ public:
|
||||
void deinitialize();
|
||||
|
||||
void initializeLuaState(lua_State* state);
|
||||
ghoul::lua::LuaState* luaState();
|
||||
|
||||
void addLibrary(LuaLibrary library);
|
||||
bool hasLibrary(const std::string& name);
|
||||
|
||||
@@ -128,7 +128,6 @@ set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene_doc.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scene/sceneloader.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenemanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode_doc.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scripting/lualibrary.cpp
|
||||
@@ -275,7 +274,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/sceneloader.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenemanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenegraphnode.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/lualibrary.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/script_helper.h
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
#include <openspace/scene/rotation.h>
|
||||
#include <openspace/scene/scale.h>
|
||||
#include <openspace/scene/translation.h>
|
||||
#include <openspace/scene/scenemanager.h>
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
#include <openspace/scene/assetloader.h>
|
||||
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <openspace/util/task.h>
|
||||
@@ -122,7 +123,7 @@ OpenSpaceEngine* OpenSpaceEngine::_engine = nullptr;
|
||||
OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
std::unique_ptr<WindowWrapper> windowWrapper)
|
||||
: _configurationManager(new ConfigurationManager)
|
||||
, _sceneManager(nullptr)
|
||||
, _scene(new Scene)
|
||||
, _downloadManager(nullptr)
|
||||
, _console(new LuaConsole)
|
||||
, _moduleEngine(new ModuleEngine)
|
||||
@@ -377,8 +378,10 @@ void OpenSpaceEngine::create(int argc, char** argv,
|
||||
sgctArguments.insert(sgctArguments.begin() + 1, SgctConfigArgumentCommand);
|
||||
sgctArguments.insert(sgctArguments.begin() + 2, absPath(sgctConfigurationPath));
|
||||
|
||||
// Set up scene manager
|
||||
_engine->_sceneManager = std::make_unique<SceneManager>("${ASSETS}", "${SYNC}");
|
||||
// Set up asset loader and scene loader
|
||||
_engine->_assetLoader = std::make_unique<AssetLoader>(
|
||||
OsEng.scriptEngine().luaState(), "${ASSETS}", "${SYNC}");
|
||||
_engine->_sceneLoader = std::make_unique<SceneLoader>(_engine->_assetLoader.get());
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::destroy() {
|
||||
@@ -402,7 +405,7 @@ void OpenSpaceEngine::destroy() {
|
||||
_engine->_console->deinitialize();
|
||||
|
||||
_engine->_scriptEngine->deinitialize();
|
||||
_engine->_sceneManager->unloadAll();
|
||||
_engine->_scene = nullptr;
|
||||
|
||||
delete _engine;
|
||||
FactoryManager::deinitialize();
|
||||
@@ -552,7 +555,7 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
}
|
||||
);
|
||||
|
||||
Scene* scene = nullptr;
|
||||
|
||||
if (scenePath != "") {
|
||||
// Run start up scripts
|
||||
try {
|
||||
@@ -563,7 +566,17 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
}
|
||||
// Load the scene
|
||||
try {
|
||||
scene = _sceneManager->loadScene(scenePath);
|
||||
if (_scene) {
|
||||
_syncEngine->removeSyncables(_timeManager->getSyncables());
|
||||
_syncEngine->removeSyncables(_renderEngine->getSyncables());
|
||||
_renderEngine->setScene(nullptr);
|
||||
_renderEngine->setCamera(nullptr);
|
||||
_interactionHandler->setCamera(nullptr);
|
||||
}
|
||||
|
||||
_scene = std::make_unique<Scene>();
|
||||
_renderEngine->setScene(_scene.get());
|
||||
_sceneLoader->loadScene(_scene.get(), scenePath);
|
||||
}
|
||||
catch (const ghoul::FileNotFoundError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
@@ -587,26 +600,16 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
}
|
||||
}
|
||||
|
||||
Scene* previousScene = _renderEngine->scene();
|
||||
if (previousScene) {
|
||||
_syncEngine->removeSyncables(_timeManager->getSyncables());
|
||||
_syncEngine->removeSyncables(_renderEngine->getSyncables());
|
||||
|
||||
_renderEngine->setScene(nullptr);
|
||||
_renderEngine->setCamera(nullptr);
|
||||
_interactionHandler->setCamera(nullptr);
|
||||
_sceneManager->unloadScene(*previousScene);
|
||||
}
|
||||
|
||||
|
||||
// Initialize the RenderEngine
|
||||
_renderEngine->setScene(scene);
|
||||
|
||||
_renderEngine->setGlobalBlackOutFactor(0.0);
|
||||
_renderEngine->startFading(1, 3.0);
|
||||
|
||||
if (scene) {
|
||||
_renderEngine->setCamera(scene->camera());
|
||||
scene->initialize();
|
||||
_interactionHandler->setCamera(scene->camera());
|
||||
if (_scene) {
|
||||
_renderEngine->setCamera(_scene->camera());
|
||||
_interactionHandler->setCamera(_scene->camera());
|
||||
try {
|
||||
runPostInitializationScripts(scenePath);
|
||||
} catch (const ghoul::RuntimeError& e) {
|
||||
@@ -624,7 +627,7 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
|
||||
// If a PropertyDocumentationFile was specified, generate it now.
|
||||
if (configurationManager().hasKey(ConfigurationManager::KeyPropertyDocumentation)) {
|
||||
scene->writeDocumentation(
|
||||
_scene->writeDocumentation(
|
||||
absPath(configurationManager().value<std::string>(
|
||||
ConfigurationManager::KeyPropertyDocumentation
|
||||
))
|
||||
|
||||
@@ -33,13 +33,17 @@
|
||||
|
||||
namespace {
|
||||
const char* AssetFileSuffix = "asset";
|
||||
const char* AssetGlobalVariableName = "asset";
|
||||
|
||||
const char* ImportFunctionName = "import";
|
||||
const char* ExportFunctionName = "export";
|
||||
const char* SyncedResourceFunctionName = "syncedResource";
|
||||
const char* LocalResourceFunctionName = "localResource";
|
||||
const char* _loggerCat = "AssetLoader";
|
||||
const char* OnDeinitializeFunctionName = "onDeinitialize";
|
||||
|
||||
const char* AssetsTableName = "_assets";
|
||||
const char* KeySceneGraphNodes = "SceneGraphNodes";
|
||||
|
||||
const char* _loggerCat = "AssetLoader";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
@@ -50,11 +54,6 @@ int importAsset(lua_State* state) {
|
||||
return assetLoader->importAssetLua();
|
||||
}
|
||||
|
||||
int exportAsset(lua_State* state) {
|
||||
AssetLoader::Asset* asset = (AssetLoader::Asset*)lua_touserdata(state, lua_upvalueindex(1));
|
||||
return asset->exportAssetLua();
|
||||
}
|
||||
|
||||
int resolveLocalResource(lua_State* state) {
|
||||
AssetLoader::Asset* asset = (AssetLoader::Asset*)lua_touserdata(state, lua_upvalueindex(1));
|
||||
return asset->resolveLocalResourceLua();
|
||||
@@ -65,22 +64,23 @@ int resolveSyncedResource(lua_State* state) {
|
||||
return asset->resolveSyncedResourceLua();
|
||||
}
|
||||
|
||||
int noOperation(lua_State* state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AssetLoader::AssetLoader(std::string assetRoot, std::string syncRoot)
|
||||
: _rootAsset(std::make_unique<Asset>(this, std::move(assetRoot)))
|
||||
, _syncRoot(std::move(syncRoot))
|
||||
|
||||
}
|
||||
|
||||
AssetLoader::AssetLoader(ghoul::lua::LuaState* luaState, std::string assetRoot, std::string syncRoot)
|
||||
: _luaState(luaState)
|
||||
, _rootAsset(std::make_unique<Asset>(this, std::move(assetRoot)))
|
||||
, _syncRoot(std::move(syncRoot))
|
||||
{
|
||||
_assetStack.push_back(_rootAsset.get());
|
||||
|
||||
// Create _assets table.
|
||||
lua_newtable(_luaState);
|
||||
lua_setglobal(_luaState, AssetsTableName);
|
||||
|
||||
// Register import function
|
||||
lua_pushlightuserdata(_luaState, this);
|
||||
lua_pushcclosure(_luaState, &assetloader::importAsset, 1);
|
||||
lua_setglobal(_luaState, ImportFunctionName);
|
||||
lua_newtable(*_luaState);
|
||||
lua_setglobal(*_luaState, AssetsTableName);
|
||||
}
|
||||
|
||||
AssetLoader::Asset* AssetLoader::loadAsset(const std::string& name) {
|
||||
@@ -105,7 +105,7 @@ AssetLoader::Asset* AssetLoader::loadAsset(const std::string& name) {
|
||||
});
|
||||
|
||||
try {
|
||||
ghoul::lua::runScriptFile(_luaState, asset->assetFilepath());
|
||||
ghoul::lua::runScriptFile(*_luaState, asset->assetFilepath());
|
||||
} catch (const ghoul::lua::LuaRuntimeException& e) {
|
||||
LERROR(e.message << ": " << e.component);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ ghoul::filesystem::Directory AssetLoader::currentDirectory() {
|
||||
return _assetStack.back()->directory();
|
||||
}
|
||||
|
||||
ghoul::lua::LuaState& AssetLoader::luaState() {
|
||||
ghoul::lua::LuaState* AssetLoader::luaState() {
|
||||
return _luaState;
|
||||
}
|
||||
|
||||
@@ -132,16 +132,55 @@ const std::string& AssetLoader::syncRoot() {
|
||||
|
||||
void AssetLoader::pushAsset(Asset* asset) {
|
||||
_assetStack.push_back(asset);
|
||||
updateGlobalLuaFunctions();
|
||||
|
||||
// Push the global asset table to the lua stack.
|
||||
lua_getglobal(*_luaState, AssetsTableName);
|
||||
int globalTableIndex = lua_gettop(*_luaState);
|
||||
|
||||
// Create table for the current asset.
|
||||
lua_newtable(*_luaState);
|
||||
int assetTableIndex = lua_gettop(*_luaState);
|
||||
|
||||
// Register local resource function
|
||||
lua_pushlightuserdata(*_luaState, asset);
|
||||
lua_pushcclosure(*_luaState, &assetloader::resolveLocalResource, 1);
|
||||
lua_setfield(*_luaState, assetTableIndex, LocalResourceFunctionName);
|
||||
|
||||
// Register synced resource function
|
||||
lua_pushlightuserdata(*_luaState, asset);
|
||||
lua_pushcclosure(*_luaState, &assetloader::resolveSyncedResource, 1);
|
||||
lua_setfield(*_luaState, assetTableIndex, SyncedResourceFunctionName);
|
||||
|
||||
// Register import function
|
||||
lua_pushlightuserdata(*_luaState, asset->loader());
|
||||
lua_pushcclosure(*_luaState, &assetloader::importAsset, 1);
|
||||
lua_setfield(*_luaState, assetTableIndex, ImportFunctionName);
|
||||
|
||||
// Register default onDeinitialize function
|
||||
lua_pushcfunction(*_luaState, &assetloader::noOperation);
|
||||
lua_setfield(*_luaState, assetTableIndex, OnDeinitializeFunctionName);
|
||||
|
||||
// Extend global asset table (pushed to the lua stack earlier) with this asset
|
||||
lua_setfield(*_luaState, globalTableIndex, asset->id().c_str());
|
||||
|
||||
// Update lua globals
|
||||
updateLuaGlobals();
|
||||
}
|
||||
|
||||
void AssetLoader::popAsset() {
|
||||
_assetStack.pop_back();
|
||||
updateGlobalLuaFunctions();
|
||||
updateLuaGlobals();
|
||||
}
|
||||
|
||||
void AssetLoader::updateGlobalLuaFunctions() {
|
||||
void AssetLoader::updateLuaGlobals() {
|
||||
Asset* asset = _assetStack.back();
|
||||
// Set `asset` lua global to point to the current asset table
|
||||
lua_getglobal(*_luaState, AssetsTableName);
|
||||
lua_getfield(*_luaState, -1, asset->id().c_str());
|
||||
lua_setglobal(*_luaState, AssetGlobalVariableName);
|
||||
}
|
||||
|
||||
/*void AssetLoader::updateGlobalLuaFunctions() {
|
||||
Asset* asset = _assetStack.size() > 0 ? _assetStack.back() : nullptr;
|
||||
|
||||
// Register resolve functions
|
||||
@@ -157,47 +196,25 @@ void AssetLoader::updateGlobalLuaFunctions() {
|
||||
lua_pushlightuserdata(_luaState, asset);
|
||||
lua_pushcclosure(_luaState, &assetloader::exportAsset, 1);
|
||||
lua_setglobal(_luaState, ExportFunctionName);
|
||||
}
|
||||
}*/
|
||||
|
||||
int openspace::AssetLoader::importAssetLua() {
|
||||
std::string assetName = luaL_checkstring(_luaState, -1);
|
||||
int nArguments = lua_gettop(*_luaState);
|
||||
if (nArguments != 1)
|
||||
return luaL_error(*_luaState, "Expected %i arguments, got %i", 1, nArguments);
|
||||
|
||||
std::string assetName = luaL_checkstring(*_luaState, -1);
|
||||
|
||||
Asset* asset = loadAsset(assetName);
|
||||
if (!asset) {
|
||||
return luaL_error(_luaState, "Asset '%s' not found", assetName.c_str());
|
||||
return luaL_error(*_luaState, "Asset '%s' not found", assetName.c_str());
|
||||
}
|
||||
const std::string assetId = asset->id();
|
||||
lua_getglobal(_luaState, AssetsTableName);
|
||||
lua_getfield(_luaState, -1, assetId.c_str());
|
||||
lua_getglobal(*_luaState, AssetsTableName);
|
||||
lua_getfield(*_luaState, -1, assetId.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AssetLoader::Asset::exportAssetLua() {
|
||||
lua_State* state = _loader->luaState();
|
||||
|
||||
int nArguments = lua_gettop(state);
|
||||
if (nArguments != 1)
|
||||
return luaL_error(state, "Expected %i arguments, got %i", 1, nArguments);
|
||||
|
||||
const int type = lua_type(state, -1);
|
||||
if (type != LUA_TTABLE)
|
||||
return luaL_error(state, "Expected table, got %i", type);
|
||||
|
||||
// Extend this asset with resource methods
|
||||
lua_getglobal(state, SyncedResourceFunctionName);
|
||||
lua_setfield(state, -2, SyncedResourceFunctionName);
|
||||
|
||||
lua_getglobal(state, LocalResourceFunctionName);
|
||||
lua_setfield(state, -2, LocalResourceFunctionName);
|
||||
|
||||
// Extend global asset table with this asset
|
||||
lua_getglobal(state, AssetsTableName);
|
||||
lua_insert(state, -2);
|
||||
lua_setfield(state, -2, id().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Asset methods.
|
||||
|
||||
std::string AssetLoader::Asset::resolveLocalResource(std::string resourceName) {
|
||||
@@ -218,36 +235,36 @@ std::string AssetLoader::Asset::resolveSyncedResource(std::string resourceName)
|
||||
}
|
||||
|
||||
int AssetLoader::Asset::resolveLocalResourceLua() {
|
||||
ghoul::lua::LuaState& state = loader()->luaState();
|
||||
int nArguments = lua_gettop(state);
|
||||
ghoul::lua::LuaState* state = loader()->luaState();
|
||||
int nArguments = lua_gettop(*state);
|
||||
if (nArguments != 1)
|
||||
return luaL_error(state, "Expected %i arguments, got %i", 1, nArguments);
|
||||
return luaL_error(*state, "Expected %i arguments, got %i", 1, nArguments);
|
||||
|
||||
const int type = lua_type(state, -1);
|
||||
const int type = lua_type(*state, -1);
|
||||
if (type != LUA_TSTRING)
|
||||
return luaL_error(state, "Expected string, got %i", type);
|
||||
return luaL_error(*state, "Expected string, got %i", type);
|
||||
|
||||
std::string resourceName = luaL_checkstring(state, -1);
|
||||
std::string resourceName = luaL_checkstring(*state, -1);
|
||||
std::string resolved = resolveLocalResource(resourceName);
|
||||
|
||||
lua_pushstring(state, resolved.c_str());
|
||||
lua_pushstring(*state, resolved.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AssetLoader::Asset::resolveSyncedResourceLua() {
|
||||
ghoul::lua::LuaState& state = loader()->luaState();
|
||||
int nArguments = lua_gettop(state);
|
||||
ghoul::lua::LuaState* state = loader()->luaState();
|
||||
int nArguments = lua_gettop(*state);
|
||||
if (nArguments != 1)
|
||||
return luaL_error(state, "Expected %i arguments, got %i", 1, nArguments);
|
||||
return luaL_error(*state, "Expected %i arguments, got %i", 1, nArguments);
|
||||
|
||||
const int type = lua_type(state, -1);
|
||||
const int type = lua_type(*state, -1);
|
||||
if (type != LUA_TSTRING)
|
||||
return luaL_error(state, "Expected string, got %i", type);
|
||||
return luaL_error(*state, "Expected string, got %i", type);
|
||||
|
||||
std::string resourceName = luaL_checkstring(state, -1);
|
||||
std::string resourceName = luaL_checkstring(*state, -1);
|
||||
std::string resolved = resolveSyncedResource(resourceName);
|
||||
|
||||
lua_pushstring(state, resolved.c_str());
|
||||
lua_pushstring(*state, resolved.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -295,27 +312,27 @@ std::string AssetLoader::Asset::id() {
|
||||
|
||||
ghoul::Dictionary AssetLoader::Asset::dictionary() {
|
||||
AssetLoader* assetLoader = loader();
|
||||
ghoul::lua::LuaState& state = assetLoader->luaState();
|
||||
ghoul::lua::LuaState* state = assetLoader->luaState();
|
||||
ghoul::Dictionary dictionary;
|
||||
lua_getglobal(state, AssetsTableName);
|
||||
lua_getfield(state, -1, id().c_str());
|
||||
lua_getglobal(*state, AssetsTableName);
|
||||
lua_getfield(*state, -1, id().c_str());
|
||||
|
||||
|
||||
if (lua_type(state, -1) != LUA_TTABLE) {
|
||||
if (lua_type(*state, -1) != LUA_TTABLE) {
|
||||
// The asset did not export anything.
|
||||
// Return an empty dictionary.
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
lua_getfield(state, -1, KeySceneGraphNodes);
|
||||
lua_getfield(*state, -1, KeySceneGraphNodes);
|
||||
|
||||
if (lua_type(state, -1) != LUA_TTABLE) {
|
||||
if (lua_type(*state, -1) != LUA_TTABLE) {
|
||||
// The asset did not export any SceneGraphNodes.
|
||||
// Return an empty dictionary.
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
ghoul::lua::luaDictionaryFromState(state, dictionary);
|
||||
ghoul::lua::luaDictionaryFromState(*state, dictionary);
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
#include <openspace/scene/nodeloader.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/scripting/script_helper.h>
|
||||
#include <openspace/util/time.h>
|
||||
@@ -71,6 +71,9 @@ namespace {
|
||||
const char* KeyPositionObject = "Position";
|
||||
const char* KeyViewOffset = "Offset";
|
||||
|
||||
const std::string KeyName = "Name";
|
||||
const std::string KeyParentName = "Parent";
|
||||
|
||||
const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/properties/main.hbs";
|
||||
const char* PropertyOwnerTemplateFilename = "${OPENSPACE_DATA}/web/properties/propertyowner.hbs";
|
||||
const char* PropertyTemplateFilename = "${OPENSPACE_DATA}/web/properties/property.hbs";
|
||||
@@ -90,7 +93,11 @@ Scene::Scene()
|
||||
},
|
||||
JsFilename
|
||||
)
|
||||
{}
|
||||
{
|
||||
std::unique_ptr<SceneGraphNode> rootNode = std::make_unique<SceneGraphNode>();
|
||||
rootNode->setName(SceneGraphNode::RootNodeName);
|
||||
setRoot(std::move(rootNode));
|
||||
}
|
||||
|
||||
Scene::~Scene(){
|
||||
}
|
||||
@@ -209,21 +216,6 @@ void Scene::sortTopologically() {
|
||||
_topologicallySortedNodes = nodes;
|
||||
}
|
||||
|
||||
void Scene::initialize() {
|
||||
for (SceneGraphNode* node : _topologicallySortedNodes) {
|
||||
try {
|
||||
bool success = node->initialize();
|
||||
if (success)
|
||||
LDEBUG(node->name() << " initialized successfully!");
|
||||
else
|
||||
LWARNING(node->name() << " not initialized.");
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(std::string(_loggerCat) + "(" + e.component + ")", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::update(const UpdateData& data) {
|
||||
for (SceneGraphNode* node : _topologicallySortedNodes) {
|
||||
try {
|
||||
@@ -275,6 +267,56 @@ const std::vector<SceneGraphNode*>& Scene::allSceneGraphNodes() const {
|
||||
return _topologicallySortedNodes;
|
||||
}
|
||||
|
||||
|
||||
SceneGraphNode* Scene::loadNode(const ghoul::Dictionary& dict) {
|
||||
std::vector<std::string> dependencyNames;
|
||||
|
||||
std::string nodeName = dict.value<std::string>(KeyName);
|
||||
std::string parentName = dict.value<std::string>(KeyParentName);
|
||||
std::unique_ptr<SceneGraphNode> node = SceneGraphNode::createFromDictionary(dict);
|
||||
|
||||
if (dict.hasKey(SceneGraphNode::KeyDependencies)) {
|
||||
if (!dict.hasValue<ghoul::Dictionary>(SceneGraphNode::KeyDependencies)) {
|
||||
LERROR("Dependencies did not have the corrent type");
|
||||
}
|
||||
ghoul::Dictionary nodeDependencies;
|
||||
dict.getValue(SceneGraphNode::KeyDependencies, nodeDependencies);
|
||||
|
||||
std::vector<std::string> keys = nodeDependencies.keys();
|
||||
for (const std::string& key : keys) {
|
||||
std::string value = nodeDependencies.value<std::string>(key);
|
||||
dependencyNames.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
SceneGraphNode* parent = sceneGraphNode(parentName);
|
||||
if (!parent) {
|
||||
LERROR("Could not find parent '" + parentName + "' for '" + nodeName + "'");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> dependencies;
|
||||
bool foundAllDeps = true;
|
||||
for (const auto& depName : dependencyNames) {
|
||||
SceneGraphNode* dep = sceneGraphNode(depName);
|
||||
if (!dep) {
|
||||
LERROR("Could not find dependency '" + depName + "' for '" + nodeName + "'");
|
||||
foundAllDeps = false;
|
||||
continue;
|
||||
}
|
||||
dependencies.push_back(dep);
|
||||
}
|
||||
|
||||
if (!foundAllDeps) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SceneGraphNode* rawNodePointer = node.get();
|
||||
node->setDependencies(dependencies, SceneGraphNode::UpdateScene::No);
|
||||
parent->attachChild(std::move(node));
|
||||
return rawNodePointer;
|
||||
}
|
||||
|
||||
std::string Scene::generateJson() const {
|
||||
std::function<std::string(properties::PropertyOwner*)> createJson =
|
||||
[&createJson](properties::PropertyOwner* owner) -> std::string
|
||||
|
||||
@@ -356,13 +356,14 @@ int addSceneGraphNode(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Temporarily disabled.
|
||||
SceneGraphNode* node = OsEng.renderEngine().scene()->loadNode(d);
|
||||
if (!node) {
|
||||
LERRORC("addSceneGraphNode", "Could not load node");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//SceneLoader loader;
|
||||
//SceneGraphNode* importedNode = loader.importNodeDictionary(*OsEng.renderEngine().scene(), d);
|
||||
//importedNode->initialize();
|
||||
|
||||
//return 1;
|
||||
node->initialize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int removeSceneGraphNode(lua_State* L) {
|
||||
|
||||
@@ -375,6 +375,7 @@ void SceneGraphNode::setParent(SceneGraphNode& parent, UpdateScene updateScene)
|
||||
}
|
||||
|
||||
void SceneGraphNode::attachChild(std::unique_ptr<SceneGraphNode> child, UpdateScene updateScene) {
|
||||
ghoul_assert(child != nullptr, "Child may not be null");
|
||||
ghoul_assert(child->parent() == nullptr, "Child may not already have a parent");
|
||||
|
||||
child->_parent = this;
|
||||
@@ -382,10 +383,11 @@ void SceneGraphNode::attachChild(std::unique_ptr<SceneGraphNode> child, UpdateSc
|
||||
child->setScene(_scene);
|
||||
}
|
||||
|
||||
SceneGraphNode* childRaw = child.get();
|
||||
_children.push_back(std::move(child));
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->addNode(child.get());
|
||||
_scene->addNode(childRaw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,6 @@ namespace {
|
||||
const std::string AssetExtension = ".asset";
|
||||
|
||||
const std::string RootNodeName = "Root";
|
||||
const std::string KeyName = "Name";
|
||||
const std::string KeyParentName = "Parent";
|
||||
const std::string KeyDependencies = "Dependencies";
|
||||
const std::string KeyCamera = "Camera";
|
||||
const std::string KeyCameraFocus = "Focus";
|
||||
@@ -57,7 +55,7 @@ SceneLoader::SceneLoader(AssetLoader* assetLoader)
|
||||
: _assetLoader(assetLoader)
|
||||
{}
|
||||
|
||||
std::unique_ptr<Scene> SceneLoader::loadScene(const std::string& path) {
|
||||
void SceneLoader::loadScene(Scene* scene, const std::string& path) {
|
||||
// Set up lua state.
|
||||
lua_State* state = ghoul::lua::createNewLuaState();
|
||||
OnExit(
|
||||
@@ -91,74 +89,30 @@ std::unique_ptr<Scene> SceneLoader::loadScene(const std::string& path) {
|
||||
std::vector<std::string> keys = assetDictionary.keys();
|
||||
//ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory();
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> allNodes;
|
||||
|
||||
for (const std::string& key : keys) {
|
||||
std::string fullAssetName = assetDictionary.value<std::string>(key);
|
||||
std::replace(fullAssetName.begin(), fullAssetName.end(), '/', FileSys.PathSeparator);
|
||||
std::string assetPath = FileSys.pathByAppendingComponent(assetsPath, fullAssetName);
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> nodes = loadDirectory(assetPath, state);
|
||||
std::move(nodes.begin(), nodes.end(), std::back_inserter(allNodes));
|
||||
std::string assetName = assetDictionary.value<std::string>(key);
|
||||
_assetLoader->loadAsset(assetName);
|
||||
}
|
||||
|
||||
//FileSys.setCurrentDirectory(oldDirectory);
|
||||
|
||||
std::unique_ptr<Scene> scene = std::make_unique<Scene>();
|
||||
|
||||
std::unique_ptr<SceneGraphNode> rootNode = std::make_unique<SceneGraphNode>();
|
||||
rootNode->setName(SceneGraphNode::RootNodeName);
|
||||
scene->setRoot(std::move(rootNode));
|
||||
|
||||
addLoadedNodes(*scene, std::move(allNodes));
|
||||
|
||||
ghoul::Dictionary cameraDictionary;
|
||||
sceneDictionary.getValue(KeyCamera, cameraDictionary);
|
||||
LoadedCamera loadedCamera = loadCamera(cameraDictionary);
|
||||
std::unique_ptr<LoadedCamera> loadedCamera = loadCamera(cameraDictionary);
|
||||
|
||||
auto& nodeMap = scene->nodesByName();
|
||||
auto it = nodeMap.find(loadedCamera.parent);
|
||||
auto it = nodeMap.find(loadedCamera->parent);
|
||||
if (it != nodeMap.end()) {
|
||||
loadedCamera.camera->setParent(it->second);
|
||||
loadedCamera->camera->setParent(it->second);
|
||||
} else {
|
||||
LWARNING(
|
||||
"Could not find the camera parent '" + loadedCamera.parent +
|
||||
"Could not find the camera parent '" + loadedCamera->parent +
|
||||
"'. Attaching camera to root node.");
|
||||
loadedCamera.camera->setParent(scene->root());
|
||||
loadedCamera->camera->setParent(scene->root());
|
||||
}
|
||||
|
||||
scene->setCamera(std::move(loadedCamera.camera));
|
||||
|
||||
return scene;
|
||||
scene->setCamera(std::move(loadedCamera->camera));
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> SceneLoader::importDirectory(Scene& scene, const std::string& path) {
|
||||
lua_State* state = ghoul::lua::createNewLuaState();
|
||||
OnExit(
|
||||
// Delete the Lua state at the end of the scope, no matter what.
|
||||
[state]() {ghoul::lua::destroyLuaState(state); }
|
||||
);
|
||||
OsEng.scriptEngine().initializeLuaState(state);
|
||||
|
||||
std::string absDirectoryPath = absPath(path);
|
||||
|
||||
//ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory();
|
||||
std::vector<SceneLoader::LoadedNode> nodes = loadDirectory(path, state);
|
||||
//FileSys.setCurrentDirectory(oldDirectory);
|
||||
return addLoadedNodes(scene, std::move(nodes));
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneLoader::importNodeDictionary(Scene& scene, const ghoul::Dictionary& dict) {
|
||||
std::vector<SceneLoader::LoadedNode> loadedNodes;
|
||||
loadedNodes.push_back(loadNode(dict));
|
||||
std::vector<SceneGraphNode*> nodes = addLoadedNodes(scene, std::move(loadedNodes));
|
||||
if (nodes.size() == 1) {
|
||||
return nodes[0];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SceneLoader::LoadedCamera SceneLoader::loadCamera(const ghoul::Dictionary& cameraDict) {
|
||||
std::unique_ptr<SceneLoader::LoadedCamera> SceneLoader::loadCamera(const ghoul::Dictionary& cameraDict) {
|
||||
std::string focus;
|
||||
glm::vec3 cameraPosition;
|
||||
glm::vec4 cameraRotation;
|
||||
@@ -174,7 +128,7 @@ SceneLoader::LoadedCamera SceneLoader::loadCamera(const ghoul::Dictionary& camer
|
||||
camera->setRotation(glm::dquat(
|
||||
cameraRotation.x, cameraRotation.y, cameraRotation.z, cameraRotation.w));
|
||||
|
||||
LoadedCamera loadedCamera(focus, std::move(camera));
|
||||
std::unique_ptr<LoadedCamera> loadedCamera = std::make_unique<LoadedCamera>(focus, std::move(camera));
|
||||
|
||||
if (!readSuccessful) {
|
||||
throw Scene::InvalidSceneError(
|
||||
@@ -184,208 +138,4 @@ SceneLoader::LoadedCamera SceneLoader::loadCamera(const ghoul::Dictionary& camer
|
||||
return loadedCamera;
|
||||
}
|
||||
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> SceneLoader::loadDirectory(
|
||||
const std::string& path,
|
||||
lua_State* luaState)
|
||||
{
|
||||
std::string::size_type pos = path.find_last_of(FileSys.PathSeparator);
|
||||
if (pos == std::string::npos) {
|
||||
LERROR("Error parsing directory name '" << path << "'");
|
||||
return std::vector<SceneLoader::LoadedNode>();
|
||||
}
|
||||
std::string assetName = path.substr(pos + 1);
|
||||
std::string assetFile = FileSys.pathByAppendingComponent(path, assetName) + AssetExtension;
|
||||
|
||||
if (FileSys.fileExists(assetFile)) {
|
||||
// TODO: Get rid of changing the working directory (global state is bad) -- emiax
|
||||
// This requires refactoring all renderables to not use relative paths in constructors.
|
||||
FileSys.setCurrentDirectory(ghoul::filesystem::Directory(path));
|
||||
|
||||
// We have a asset file, so it is a direct include.
|
||||
return loadAsset(assetName, luaState);
|
||||
} else {
|
||||
std::vector<SceneLoader::LoadedNode> allLoadedNodes;
|
||||
// If we do not have a asset file, we have to include all subdirectories.
|
||||
using ghoul::filesystem::Directory;
|
||||
using std::string;
|
||||
|
||||
const Directory directory(path);
|
||||
const std::string directoryPath = directory.path();
|
||||
|
||||
if (!FileSys.directoryExists(directoryPath)) {
|
||||
LERROR("The directory " << directoryPath << " does not exist.");
|
||||
return std::vector<SceneLoader::LoadedNode>();
|
||||
}
|
||||
|
||||
for (const string& subdirectory : directory.readDirectories()) {
|
||||
std::vector<SceneLoader::LoadedNode> loadedNodes = loadDirectory(subdirectory, luaState);
|
||||
std::move(loadedNodes.begin(), loadedNodes.end(), std::back_inserter(allLoadedNodes));
|
||||
}
|
||||
return allLoadedNodes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SceneLoader::LoadedNode SceneLoader::loadNode(const ghoul::Dictionary& dictionary) {
|
||||
std::vector<std::string> dependencies;
|
||||
|
||||
std::string nodeName = dictionary.value<std::string>(KeyName);
|
||||
std::string parentName = dictionary.value<std::string>(KeyParentName);
|
||||
std::unique_ptr<SceneGraphNode> node = SceneGraphNode::createFromDictionary(dictionary);
|
||||
|
||||
if (dictionary.hasKey(SceneGraphNode::KeyDependencies)) {
|
||||
if (!dictionary.hasValue<ghoul::Dictionary>(SceneGraphNode::KeyDependencies)) {
|
||||
LERROR("Dependencies did not have the corrent type");
|
||||
}
|
||||
ghoul::Dictionary nodeDependencies;
|
||||
dictionary.getValue(SceneGraphNode::KeyDependencies, nodeDependencies);
|
||||
|
||||
std::vector<std::string> keys = nodeDependencies.keys();
|
||||
for (const std::string& key : keys) {
|
||||
std::string value = nodeDependencies.value<std::string>(key);
|
||||
dependencies.push_back(value);
|
||||
}
|
||||
}
|
||||
return SceneLoader::LoadedNode(nodeName, parentName, dependencies, std::move(node));
|
||||
}
|
||||
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> SceneLoader::loadAsset(const std::string& assetName, lua_State* luaState) {
|
||||
AssetLoader::Asset* asset = _assetLoader->loadAsset(assetName);
|
||||
const ghoul::Dictionary& assetDictionary = asset->dictionary();
|
||||
std::vector<LoadedNode> loadedNodes;
|
||||
|
||||
std::vector<std::string> keys = assetDictionary.keys();
|
||||
for (const std::string& key : keys) {
|
||||
ghoul::Dictionary nodeDictionary;
|
||||
if (!assetDictionary.getValue(key, nodeDictionary)) {
|
||||
LERROR("Node dictionary did not have the corrent type");
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
loadedNodes.push_back(loadNode(nodeDictionary));
|
||||
} catch (ghoul::RuntimeError& e) {
|
||||
LERROR("Failed loading node from " << assetName << ": " << e.message << ", " << e.component);
|
||||
}
|
||||
}
|
||||
return loadedNodes;
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> SceneLoader::addLoadedNodes(Scene& scene, std::vector<SceneLoader::LoadedNode>&& loadedNodes) {
|
||||
std::map<std::string, SceneGraphNode*> existingNodes = scene.nodesByName();
|
||||
std::map<std::string, SceneGraphNode*> addedNodes;
|
||||
|
||||
// Populate map of nodes to be added.
|
||||
// Also track new branches of nodes that are attached
|
||||
// to allow for recovery in case an invalid scene is generated.
|
||||
for (auto& loadedNode : loadedNodes) {
|
||||
std::string name = loadedNode.name;
|
||||
if (existingNodes.count(name) > 0) {
|
||||
LERROR("Node with name '" + name + "' already exists in scene");
|
||||
continue;
|
||||
}
|
||||
if (addedNodes.count(name) > 0) {
|
||||
LERROR("Duplicate node names '" + name + "' among loaded nodes");
|
||||
}
|
||||
|
||||
SceneGraphNode* node = loadedNode.node.get();
|
||||
addedNodes[name] = node;
|
||||
}
|
||||
|
||||
// Find a node by name among the exising nodes and the added nodes.
|
||||
auto findNode = [&existingNodes, &addedNodes](const std::string name) {
|
||||
std::map<std::string, SceneGraphNode*>::iterator it;
|
||||
if ((it = existingNodes.find(name)) != existingNodes.end()) {
|
||||
return it->second;
|
||||
}
|
||||
if ((it = addedNodes.find(name)) != addedNodes.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return static_cast<SceneGraphNode*>(nullptr);
|
||||
};
|
||||
|
||||
std::vector<SceneGraphNode*> attachedBranches;
|
||||
std::vector<std::unique_ptr<SceneGraphNode>> badNodes;
|
||||
|
||||
// Attach each node to its parent and set up dependencies.
|
||||
for (auto& loadedNode : loadedNodes) {
|
||||
std::string parentName = loadedNode.parent;
|
||||
std::vector<std::string> dependencyNames = loadedNode.dependencies;
|
||||
|
||||
SceneGraphNode* parent = findNode(parentName);
|
||||
if (!parent) {
|
||||
LERROR("Could not find parent '" + parentName + "' for '" + loadedNode.name + "'");
|
||||
badNodes.push_back(std::move(loadedNode.node));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> dependencies;
|
||||
bool foundAllDeps = true;
|
||||
for (const auto& depName : dependencyNames) {
|
||||
SceneGraphNode* dep = findNode(depName);
|
||||
if (!dep) {
|
||||
LERROR("Could not find dependency '" + depName + "' for '" + loadedNode.name + "'");
|
||||
foundAllDeps = false;
|
||||
continue;
|
||||
}
|
||||
dependencies.push_back(dep);
|
||||
}
|
||||
|
||||
if (!foundAllDeps) {
|
||||
badNodes.push_back(std::move(loadedNode.node));
|
||||
continue;
|
||||
}
|
||||
|
||||
SceneGraphNode* child = loadedNode.node.get();
|
||||
parent->attachChild(std::move(loadedNode.node), SceneGraphNode::UpdateScene::No);
|
||||
child->setDependencies(dependencies, SceneGraphNode::UpdateScene::No);
|
||||
|
||||
if (existingNodes.find(parentName) != existingNodes.end()) {
|
||||
attachedBranches.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all bad nodes (parent or deps missing) and all their children and dependent nodes.
|
||||
// Use unsorted set `visited` to avoid infinite loop in case of circular deps.
|
||||
std::unordered_set<SceneGraphNode*> visited;
|
||||
for (size_t i = 0; i < badNodes.size(); i++) {
|
||||
auto& badNode = badNodes[i];
|
||||
for (auto c : badNode->children()) {
|
||||
visited.insert(c);
|
||||
badNodes.push_back(badNode->detachChild(*c, SceneGraphNode::UpdateScene::No));
|
||||
}
|
||||
for (auto& d : badNode->dependentNodes()) {
|
||||
SceneGraphNode* parent = d->parent();
|
||||
if (visited.count(d) == 0) {
|
||||
visited.insert(d);
|
||||
if (parent) {
|
||||
badNodes.push_back(parent->detachChild(*d, SceneGraphNode::UpdateScene::No));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Warn for nodes that lack connection to the root.
|
||||
for (auto& node : addedNodes) {
|
||||
if (!node.second->scene()) {
|
||||
LWARNING("Node '" << node.first << "' is not connected to the root and will not be added to the scene");
|
||||
}
|
||||
}
|
||||
|
||||
// Add the nodes to the scene.
|
||||
for (auto& node : attachedBranches) {
|
||||
scene.addNode(node, Scene::UpdateDependencies::No);
|
||||
}
|
||||
|
||||
// Update dependencies: sort nodes topologically.
|
||||
scene.updateDependencies();
|
||||
|
||||
// Return a vector of all added nodes.
|
||||
std::vector<SceneGraphNode*> addedNodesVector;
|
||||
std::transform(addedNodes.begin(), addedNodes.end(), std::back_inserter(addedNodesVector), [] (auto& pair) {
|
||||
return pair.second;
|
||||
});
|
||||
|
||||
return addedNodesVector;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
#include <openspace/scene/scenemanager.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
SceneManager::SceneManager(std::string assetRoot, std::string syncRoot)
|
||||
: _assetLoader(assetRoot, syncRoot)
|
||||
, _sceneLoader(&_assetLoader)
|
||||
{}
|
||||
|
||||
Scene* SceneManager::loadScene(const std::string& path) {
|
||||
std::unique_ptr<Scene> scene = _sceneLoader.loadScene(path);
|
||||
Scene* s = scene.get();
|
||||
if (s) {
|
||||
_scenes.push_back(std::move(scene));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void SceneManager::unloadScene(Scene& scene) {
|
||||
_scenes.erase(std::remove_if(
|
||||
_scenes.begin(), _scenes.end(), [&scene] (auto& s) {
|
||||
return s.get() == &scene;
|
||||
}), _scenes.end()
|
||||
);
|
||||
}
|
||||
|
||||
void SceneManager::unloadAll() {
|
||||
_scenes.clear();
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,10 @@ void ScriptEngine::initializeLuaState(lua_State* state) {
|
||||
}
|
||||
}
|
||||
|
||||
ghoul::lua::LuaState * ScriptEngine::luaState() {
|
||||
return &_state;
|
||||
}
|
||||
|
||||
void ScriptEngine::addLibrary(LuaLibrary library) {
|
||||
auto sortFunc = [](const LuaLibrary::Function& lhs, const LuaLibrary::Function& rhs)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user