diff --git a/modules/onscreengui/onscreenguimodule.cpp b/modules/onscreengui/onscreenguimodule.cpp index 53a547e294..5e5c8cf91e 100644 --- a/modules/onscreengui/onscreenguimodule.cpp +++ b/modules/onscreengui/onscreenguimodule.cpp @@ -88,8 +88,10 @@ OnScreenGUIModule::OnScreenGUIModule() gui._property.setSource( []() { - const std::vector& nodes = - OsEng.renderEngine().scene()->allSceneGraphNodes(); + const Scene* scene = OsEng.renderEngine().scene(); + const std::vector& nodes = scene ? + scene->allSceneGraphNodes() : + std::vector(); return std::vector(nodes.begin(), nodes.end()); } ); diff --git a/modules/onscreengui/src/guiorigincomponent.cpp b/modules/onscreengui/src/guiorigincomponent.cpp index 7c732583a8..4a24232c05 100644 --- a/modules/onscreengui/src/guiorigincomponent.cpp +++ b/modules/onscreengui/src/guiorigincomponent.cpp @@ -44,8 +44,10 @@ GuiOriginComponent::GuiOriginComponent() void GuiOriginComponent::render() { SceneGraphNode* currentFocus = OsEng.interactionHandler().focusNode(); - std::vector nodes = - OsEng.renderEngine().scene()->allSceneGraphNodes(); + Scene* scene = OsEng.renderEngine().scene(); + std::vector nodes = scene ? + scene->allSceneGraphNodes() : + std::vector(); std::sort( nodes.begin(), diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 34ad268eb3..226f5d4dd5 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -181,6 +181,8 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, SpiceManager::initialize(); TransformationManager::initialize(); + + _syncEngine->addSyncable(_scriptEngine.get()); } OpenSpaceEngine& OpenSpaceEngine::ref() { @@ -392,7 +394,6 @@ void OpenSpaceEngine::destroy() { _engine->_syncEngine->removeSyncables(_engine->timeManager().getSyncables()); _engine->_syncEngine->removeSyncables(_engine->_renderEngine->getSyncables()); - _engine->_syncEngine->removeSyncable(_engine->_scriptEngine.get()); _engine->_moduleEngine->deinitialize(); _engine->_console->deinitialize(); @@ -543,84 +544,88 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) { } ); - // Run start up scripts - try { - runPreInitializationScripts(scenePath); - } - catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - } - - Scene* scene; - try { - scene = _sceneManager->loadScene(scenePath); - } catch (const ghoul::FileNotFoundError& e) { - LERRORC(e.component, e.message); - return; - } catch (const Scene::InvalidSceneError& e) { - LERRORC(e.component, e.message); - return; - } catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - return; - } - catch (const std::exception& e) { - LERROR(e.what()); - return; - } - catch (...) { - LERROR("Unknown error loading the scene"); - return; + Scene* scene = nullptr; + if (scenePath != "") { + // Run start up scripts + try { + runPreInitializationScripts(scenePath); + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + // Load the scene + try { + scene = _sceneManager->loadScene(scenePath); + } + catch (const ghoul::FileNotFoundError& e) { + LERRORC(e.component, e.message); + return; + } + catch (const Scene::InvalidSceneError& e) { + LERRORC(e.component, e.message); + return; + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + return; + } + catch (const std::exception& e) { + LERROR(e.what()); + return; + } + catch (...) { + LERROR("Unknown error loading the scene"); + return; + } } Scene* previousScene = _renderEngine->scene(); if (previousScene) { _syncEngine->removeSyncables(_timeManager->getSyncables()); _syncEngine->removeSyncables(_renderEngine->getSyncables()); - _syncEngine->removeSyncable(_scriptEngine.get()); _renderEngine->setScene(nullptr); _renderEngine->setCamera(nullptr); + _interactionHandler->setCamera(nullptr); _sceneManager->unloadScene(*previousScene); } // Initialize the RenderEngine _renderEngine->setScene(scene); - _renderEngine->setCamera(scene->camera()); _renderEngine->setGlobalBlackOutFactor(0.0); _renderEngine->startFading(1, 3.0); - scene->initialize(); - _interactionHandler->setCamera(scene->camera()); + if (scene) { + _renderEngine->setCamera(scene->camera()); + scene->initialize(); + _interactionHandler->setCamera(scene->camera()); + try { + runPostInitializationScripts(scenePath); + } catch (const ghoul::RuntimeError& e) { + LFATALC(e.component, e.message); + } + + // Write keyboard documentation. + if (configurationManager().hasKey(ConfigurationManager::KeyKeyboardShortcuts)) { + interactionHandler().writeDocumentation( + absPath(configurationManager().value( + ConfigurationManager::KeyKeyboardShortcuts + )) + ); + } - try { - runPostInitializationScripts(scenePath); - } - catch (const ghoul::RuntimeError& e) { - LFATALC(e.component, e.message); - } - - // Write keyboard documentation. - if (configurationManager().hasKey(ConfigurationManager::KeyKeyboardShortcuts)) { - interactionHandler().writeDocumentation( - absPath(configurationManager().value( - ConfigurationManager::KeyKeyboardShortcuts - )) - ); - } - - // If a PropertyDocumentationFile was specified, generate it now. - if (configurationManager().hasKey(ConfigurationManager::KeyPropertyDocumentation)) { - scene->writeDocumentation( - absPath(configurationManager().value( - ConfigurationManager::KeyPropertyDocumentation - )) - ); + // If a PropertyDocumentationFile was specified, generate it now. + if (configurationManager().hasKey(ConfigurationManager::KeyPropertyDocumentation)) { + scene->writeDocumentation( + absPath(configurationManager().value( + ConfigurationManager::KeyPropertyDocumentation + )) + ); + } } _syncEngine->addSyncables(_timeManager->getSyncables()); _syncEngine->addSyncables(_renderEngine->getSyncables()); - _syncEngine->addSyncable(_scriptEngine.get()); LTRACE("OpenSpaceEngine::loadScene(end)"); } @@ -1025,13 +1030,14 @@ void OpenSpaceEngine::preSynchronization() { *it, ScriptEngine::RemoteScripting::Yes ); } - _interactionHandler->updateInputStates(dt); - _renderEngine->updateScene(); - _interactionHandler->updateCamera(dt); - _renderEngine->camera()->invalidateCache(); + Camera* camera = _renderEngine->camera(); + if (camera) { + _interactionHandler->updateCamera(dt); + _renderEngine->camera()->invalidateCache(); + } _parallelConnection->preSynchronization(); } diff --git a/src/engine/settingsengine.cpp b/src/engine/settingsengine.cpp index 999ac1d61e..ff89157d1a 100644 --- a/src/engine/settingsengine.cpp +++ b/src/engine/settingsengine.cpp @@ -65,18 +65,24 @@ void SettingsEngine::initialize() { // TODO: match regex with either with new ghoul readFiles or local code const std::string sceneDir = "${SCENE}"; const std::vector scenes = ghoul::filesystem::Directory(sceneDir).readFiles(); + const size_t nScenes = scenes.size(); - for (std::size_t i = 0; i < scenes.size(); ++i) { + for (std::size_t i = 0; i < nScenes; ++i) { const std::size_t found = scenes[i].find_last_of("/\\"); _scenes.addOption(static_cast(i), scenes[i].substr(found + 1)); } + _scenes.addOption(scenes.size(), "None"); // Set interaction to change ConfigurationManager and schedule the load - _scenes.onChange([this, sceneDir]() { - std::string sceneFile = _scenes.getDescriptionByValue(_scenes); - OsEng.configurationManager().setValue( - ConfigurationManager::KeyConfigScene, sceneFile); - OsEng.scheduleLoadScene(sceneDir + "/" + sceneFile); + _scenes.onChange([this, nScenes, sceneDir]() { + if (_scenes == nScenes) { + OsEng.scheduleLoadScene(""); + } else { + std::string sceneFile = _scenes.getDescriptionByValue(_scenes); + OsEng.configurationManager().setValue( + ConfigurationManager::KeyConfigScene, sceneFile); + OsEng.scheduleLoadScene(sceneDir + "/" + sceneFile); + } } ); } diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 76b9817bd7..12bea7f7c9 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -194,7 +194,7 @@ void InteractionHandler::setFocusNode(SceneGraphNode* node) { void InteractionHandler::setCamera(Camera* camera) { _camera = camera; - setFocusNode(_camera->parent()); + setFocusNode(camera ? _camera->parent() : nullptr); } void InteractionHandler::resetCameraDirection() { @@ -250,7 +250,6 @@ void InteractionHandler::unlockControls() { void InteractionHandler::updateInputStates(double timeSinceLastUpdate) { ghoul_assert(_inputState != nullptr, "InputState cannot be null!"); - ghoul_assert(_camera != nullptr, "Camera cannot be null!"); _currentInteractionMode->updateMouseStatesFromInput(*_inputState, timeSinceLastUpdate); } diff --git a/src/interaction/interactionmode.cpp b/src/interaction/interactionmode.cpp index cfb871bdf5..fdb04ffb2e 100644 --- a/src/interaction/interactionmode.cpp +++ b/src/interaction/interactionmode.cpp @@ -511,8 +511,10 @@ GlobeBrowsingInteractionMode::~GlobeBrowsingInteractionMode() { void GlobeBrowsingInteractionMode::setFocusNode(SceneGraphNode* focusNode) { InteractionMode::setFocusNode(focusNode); - #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED + if (!_focusNode) { + return; + } Renderable* baseRenderable = _focusNode->renderable(); if (globebrowsing::RenderableGlobe* globe = dynamic_cast(baseRenderable)) { _globe = globe; diff --git a/src/query/query.cpp b/src/query/query.cpp index dadc2bc922..c54eb48652 100644 --- a/src/query/query.cpp +++ b/src/query/query.cpp @@ -120,15 +120,17 @@ std::vector allProperties() { ); const Scene* graph = sceneGraph(); - std::vector nodes = graph->allSceneGraphNodes(); + if (graph) { + std::vector nodes = graph->allSceneGraphNodes(); - for (SceneGraphNode* n : nodes) { - std::vector props = n->propertiesRecursive(); - properties.insert( - properties.end(), - props.begin(), - props.end() - ); + for (SceneGraphNode* n : nodes) { + std::vector props = n->propertiesRecursive(); + properties.insert( + properties.end(), + props.begin(), + props.end() + ); + } } return properties; diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 51daf34c9d..e37a913406 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -308,6 +308,8 @@ void RenderEngine::deinitialize() { } void RenderEngine::updateScene() { + if (!_scene) return; + const Time& currentTime = OsEng.timeManager().time(); _scene->update({ { glm::dvec3(0), glm::dmat3(1), 1.0 }, @@ -418,15 +420,15 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat { LTRACE("RenderEngine::render(begin)"); WindowWrapper& wrapper = OsEng.windowWrapper(); - - if (_disableSceneTranslationOnMaster && wrapper.isMaster()) { - _camera->sgctInternal.setViewMatrix(viewMatrix); + if (_camera) { + if (_disableSceneTranslationOnMaster && wrapper.isMaster()) { + _camera->sgctInternal.setViewMatrix(viewMatrix); + } + else { + _camera->sgctInternal.setViewMatrix(viewMatrix * sceneMatrix); + } + _camera->sgctInternal.setProjectionMatrix(projectionMatrix); } - else { - _camera->sgctInternal.setViewMatrix(viewMatrix * sceneMatrix); - } - _camera->sgctInternal.setProjectionMatrix(projectionMatrix); - if (!(wrapper.isMaster() && _disableMasterRendering) && !wrapper.isGuiWindow()) { _renderer->render(_globalBlackOutFactor, _performanceManager != nullptr); @@ -934,7 +936,7 @@ void RenderEngine::renderInformation() { #ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED - bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons"); + bool hasNewHorizons = scene() && scene()->sceneGraphNode("NewHorizons"); double currentTime = OsEng.timeManager().time().j2000Seconds(); if (MissionManager::ref().hasCurrentMission()) { diff --git a/src/scene/scenemanager.cpp b/src/scene/scenemanager.cpp index 2c76a58974..ffe9acb171 100644 --- a/src/scene/scenemanager.cpp +++ b/src/scene/scenemanager.cpp @@ -42,9 +42,11 @@ Scene* SceneManager::loadScene(const std::string& path) { } void SceneManager::unloadScene(Scene& scene) { - std::remove_if(_scenes.begin(), _scenes.end(), [&scene] (auto& s) { - return s.get() == &scene; - }); + _scenes.erase(std::remove_if( + _scenes.begin(), _scenes.end(), [&scene] (auto& s) { + return s.get() == &scene; + }), _scenes.end() + ); } void SceneManager::unloadAll() { diff --git a/src/util/time.cpp b/src/util/time.cpp index b7e0f51b4b..12729b314f 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -111,7 +111,11 @@ void Time::setTime(std::string time, bool requireJump) { } std::string Time::UTC() const { - return SpiceManager::ref().dateFromEphemerisTime(_time); + try { + return SpiceManager::ref().dateFromEphemerisTime(_time); + } catch (const SpiceManager::SpiceException& c) { + return "0000 JAN 00 T00:00:00.00"; + } } std::string Time::ISO8601() const {