From 5a2c1b8c739dbcf043862fdc66cc748476765c6d Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 8 Apr 2015 14:47:09 +0200 Subject: [PATCH] More work on SceneGraphLoader --- src/engine/openspaceengine.cpp | 4 +- src/scenegraph/scenegraphloader.cpp | 174 +++++++++++++++++- .../circular-dependency.mod | 10 + .../test06-location.scene | 9 + tests/ScenegraphLoaderTest/test06.scene | 9 + tests/main.cpp | 32 ++-- tests/test_scenegraphloader.inl | 25 +++ 7 files changed, 244 insertions(+), 19 deletions(-) create mode 100644 tests/ScenegraphLoaderTest/circular-dependency/circular-dependency.mod create mode 100644 tests/ScenegraphLoaderTest/test06-location.scene create mode 100644 tests/ScenegraphLoaderTest/test06.scene diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index d0943d82bc..6c4e3c707d 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -121,7 +121,7 @@ OpenSpaceEngine::~OpenSpaceEngine() { } OpenSpaceEngine& OpenSpaceEngine::ref() { - assert(_engine); + ghoul_assert(_engine, "OpenSpaceEngine not created"); return *_engine; } @@ -130,7 +130,7 @@ bool OpenSpaceEngine::create( std::vector& sgctArguments, std::string& openGlVersion) { - assert(_engine == nullptr); + ghoul_assert(!_engine, "OpenSpaceEngine was already created"); // Initialize the LogManager and add the console log as this will be used every time // and we need a fall back if something goes wrong between here and when we add the diff --git a/src/scenegraph/scenegraphloader.cpp b/src/scenegraph/scenegraphloader.cpp index f35aa51075..3cb425b733 100644 --- a/src/scenegraph/scenegraphloader.cpp +++ b/src/scenegraph/scenegraphloader.cpp @@ -24,24 +24,192 @@ #include +#include #include +#include + #include +#include #include +#include namespace { const std::string _loggerCat = "SceneGraphLoader"; + const std::string _moduleExtension = ".mod"; + const std::string _commonModuleToken = "${COMMON_MODULE}"; } namespace openspace { bool SceneGraphLoader::load(const std::string& sceneDescription, std::vector& nodes) { - LINFO("Loading SceneGraph from file '" << absPath(sceneDescription) << "'"); + nodes.clear(); + std::string absSceneFile = absPath(sceneDescription); + + // See if scene file exists + if (!FileSys.fileExists(absSceneFile, true)) { + LERROR("Could not load scene file '" << absSceneFile << "'. " << + "File not found"); + return false; + } + LINFO("Loading SceneGraph from file '" << absSceneFile << "'"); + + // Load dictionary + ghoul::Dictionary sceneDictionary; + bool success = ghoul::lua::loadDictionaryFromFile(absSceneFile, sceneDictionary); + if (!success) + return false; + + std::string sceneDescriptionDirectory = + ghoul::filesystem::File(absSceneFile, true).directoryName(); + std::string sceneDirectory("."); + sceneDictionary.getValue(constants::scenegraph::keyPathScene, sceneDirectory); + + // The scene path could either be an absolute or relative path to the description + // paths directory + std::string relativeCandidate = sceneDescriptionDirectory + + ghoul::filesystem::FileSystem::PathSeparator + sceneDirectory; + std::string absoluteCandidate = absPath(sceneDirectory); + + if (FileSys.directoryExists(relativeCandidate)) + sceneDirectory = relativeCandidate; + else if (FileSys.directoryExists(absoluteCandidate)) + sceneDirectory = absoluteCandidate; + else { + LERROR("The '" << constants::scenegraph::keyPathScene << "' pointed to a " + "path '" << sceneDirectory << "' that did not exist"); + return false; + } + + struct SceneGraphNodeInformation { + std::string parent; + std::string module; + std::string modulePath; + ghoul::Dictionary dictionary; + }; + std::map nodeInformation; + + using constants::scenegraph::keyModules; + ghoul::Dictionary moduleDictionary; + success = sceneDictionary.getValue(keyModules, moduleDictionary); + if (!success) + // There are no modules that are loaded + return true; + + lua_State* state = ghoul::lua::createNewLuaState(); + OsEng.scriptEngine()->initializeLuaState(state); + + std::vector keys = moduleDictionary.keys(); + + // Get the common directory + using constants::scenegraph::keyCommonFolder; + bool commonFolderSpecified = sceneDictionary.hasKey(keyCommonFolder); + bool commonFolderCorrectType = sceneDictionary.hasKeyAndValue(keyCommonFolder); + + if (commonFolderSpecified) { + if (commonFolderCorrectType) { + std::string commonFolder = sceneDictionary.value(keyCommonFolder); + if (!FileSys.directoryExists(commonFolder)) + LERROR("Specified common folder '" << commonFolder << "' did not exist"); + else { + if (!commonFolder.empty()) { + FileSys.registerPathToken(_commonModuleToken, commonFolder); + keys.push_back(commonFolder); + } + } + } + else + LERROR("Specification for 'common' folder has invalid type"); + } + + + std::sort(keys.begin(), keys.end()); + for (const std::string& key : keys) { + std::string moduleName = moduleDictionary.value(key); + std::string modulePath = FileSys.pathByAppendingComponent(sceneDirectory, moduleName); + + if (!FileSys.directoryExists(modulePath)) { + LERROR("Could not load module '" << moduleName << "'. Directory did not exist"); + continue; + } + + std::string moduleFile = FileSys.pathByAppendingComponent( + modulePath, + moduleName + _moduleExtension + ); + + if (!FileSys.fileExists(moduleFile)) { + LERROR("Could not load module file '" << moduleFile << "'. File did not exist"); + continue; + } + + ghoul::Dictionary moduleDictionary; + bool s = ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state); + if (!s) + continue; + + std::vector keys = moduleDictionary.keys(); + for (const std::string& key : keys) { + if (!moduleDictionary.hasValue(key)) { + LERROR("SceneGraphNode '" << key << "' is not a table in module '" + << moduleFile << "'"); + continue; + } + + ghoul::Dictionary element; + std::string nodeName; + std::string parentName; + + moduleDictionary.getValue(key, element); + element.setValue(constants::scenegraph::keyPathModule, modulePath); + + element.getValue(constants::scenegraphnode::keyName, nodeName); + element.getValue(constants::scenegraphnode::keyParentName, parentName); + + nodeInformation[nodeName] = { + parentName, + moduleName, + modulePath, + element + }; + } + } + + // Check map for circular dependencies + + // Checks if n1 is dependent on n2 + std::function nodeDependency; + nodeDependency = [nodeInformation, nodeDependency](const std::string& n1, const std::string& n2) { + const SceneGraphNodeInformation& n1Info = nodeInformation[n1]; + const std::string& parentName = n1Info.parent; + + if (parentName == SceneGraphNode::RootNodeName) + return false; + if (parentName == n2) + return true; + return nodeDependency(parentName, n2); + } + + + // Add Root node to the list of nodes + SceneGraphNode* root = new SceneGraphNode(); + root->setName(SceneGraphNode::RootNodeName); + nodes.push_back(root); + + + + + auto dependentNodes = [nodeInformation](const std::string& name) { + + }; + + - // Check if file exists // Check ScenePath variable (absolute/relative path) // Convert Modules dictionary into vector - // Determine dependencies between modules + // Determine dependencies between modules (-> store in map) + // Check map for circular dependencies + // Traverse map from Root by determining it's direct dependencies // Rearrange vector based on dependencies // Create scenegraph nodes in order checking if dependencies have been fulfilled diff --git a/tests/ScenegraphLoaderTest/circular-dependency/circular-dependency.mod b/tests/ScenegraphLoaderTest/circular-dependency/circular-dependency.mod new file mode 100644 index 0000000000..901da062d3 --- /dev/null +++ b/tests/ScenegraphLoaderTest/circular-dependency/circular-dependency.mod @@ -0,0 +1,10 @@ +return { + { + Name = "CircularDependency1", + Parent = "CircularDependency2" + }, + { + Name = "CircularDependency2", + Parent = "CircularDependency1" + } +} diff --git a/tests/ScenegraphLoaderTest/test06-location.scene b/tests/ScenegraphLoaderTest/test06-location.scene new file mode 100644 index 0000000000..f3af92d9de --- /dev/null +++ b/tests/ScenegraphLoaderTest/test06-location.scene @@ -0,0 +1,9 @@ +-- Circular Dependencies in a different folder +return { + ScenePath = "scene-folder", + Modules = { + "common", + "circular-dependency" + } +} + diff --git a/tests/ScenegraphLoaderTest/test06.scene b/tests/ScenegraphLoaderTest/test06.scene new file mode 100644 index 0000000000..524a44010e --- /dev/null +++ b/tests/ScenegraphLoaderTest/test06.scene @@ -0,0 +1,9 @@ +-- Circular Dependencies +return { + ScenePath = ".", + Modules = { + "common", + "circular-dependency" + } +} + diff --git a/tests/main.cpp b/tests/main.cpp index 57078ea2d7..3205c6717e 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -52,22 +52,26 @@ namespace { } int main(int argc, char** argv) { - LogManager::initialize(LogManager::LogLevel::Debug); - LogMgr.addLog(new ConsoleLog); + openspace::OpenSpaceEngine::create(argc, argv, std::vector(), std::string()); - FileSystem::initialize(); - std::string configurationFilePath = ""; - LDEBUG("Finding configuration"); - if( ! openspace::OpenSpaceEngine::findConfiguration(configurationFilePath)) { - LFATAL("Could not find OpenSpace configuration file!"); - assert(false); - } - LINFO("Configuration file found: " << FileSys.absolutePath(configurationFilePath)); - - openspace::ConfigurationManager manager; - manager.loadFromFile(configurationFilePath); - openspace::FactoryManager::initialize(); + //LogManager::initialize(LogManager::LogLevel::Debug); + //LogMgr.addLog(new ConsoleLog); + + //FileSystem::initialize(); + //std::string configurationFilePath = ""; + //LDEBUG("Finding configuration"); + //if (!openspace::OpenSpaceEngine::findConfiguration(configurationFilePath)) { + // LFATAL("Could not find OpenSpace configuration file!"); + // assert(false); + //} + ////LINFO("Configuration file found: " << FileSys.absolutePath(configurationFilePath)); + + //openspace::ConfigurationManager manager; + //manager.loadFromFile(configurationFilePath); + + + //openspace::FactoryManager::initialize(); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/tests/test_scenegraphloader.inl b/tests/test_scenegraphloader.inl index 56de42598d..670de354d9 100644 --- a/tests/test_scenegraphloader.inl +++ b/tests/test_scenegraphloader.inl @@ -279,6 +279,31 @@ TEST_F(SceneGraphLoaderTest, Test05Location) { EXPECT_TRUE(found) << "Correct node loaded"; } +TEST_F(SceneGraphLoaderTest, Test06) { + const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test06.scene"); + + std::vector nodes; + bool success = openspace::SceneGraphLoader::load(file, nodes); + + ASSERT_FALSE(success) << "Successful loading"; + ASSERT_TRUE(nodes.empty()) << "Correct number of nodes"; +} + +TEST_F(SceneGraphLoaderTest, Test06Location) { + const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test06-location.scene"); + + std::vector nodes; + bool success = openspace::SceneGraphLoader::load(file, nodes); + + ASSERT_TRUE(success) << "Successful loading"; + ASSERT_TRUE(nodes.size() == 4) << "Correct number of nodes"; + bool found = false; + for (openspace::SceneGraphNode* n : nodes) + if (n->name() == "MultipleDependencies") + found = true; + + EXPECT_TRUE(found) << "No scenegraph nodes loaded"; +} // //