From 12ddfae3376d9564ede35c0626628488d1027ac7 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 30 Nov 2017 21:17:18 -0500 Subject: [PATCH 1/8] Compile fix in TimeConversion Reenable display of shutdown timer Add prompt informing the user of ability to abort --- src/engine/openspaceengine.cpp | 4 ++++ src/rendering/renderengine.cpp | 9 +++++++++ src/util/timeconversion.cpp | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 9eeacc42e8..9d0809cf5a 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -1319,6 +1319,10 @@ void OpenSpaceEngine::drawOverlays() { // and we won't need this if we are shutting down _renderEngine->renderCameraInformation(); } + else { + // If we are in shutdown mode, we can display the remaining time + _renderEngine->renderShutdownInformation(_shutdown.timer, _shutdown.waitTime); + } _console->render(); } diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 6515c36ef7..c641cd24f1 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -598,6 +598,15 @@ void RenderEngine::renderShutdownInformation(float timer, float fullTime) { timer, fullTime ); + + RenderFontCr( + *_fontDate, + penPosition, + "%s", + // Important: length of this string is the same as the shutdown time text + // to make them align + "Press ESC again to abort" + ); } void RenderEngine::postDraw() { diff --git a/src/util/timeconversion.cpp b/src/util/timeconversion.cpp index ec3647c2bb..badd95a2c2 100644 --- a/src/util/timeconversion.cpp +++ b/src/util/timeconversion.cpp @@ -24,6 +24,8 @@ #include +#include + #include namespace { @@ -43,7 +45,7 @@ namespace { namespace openspace { std::pair simplifyTime(double seconds) { - double secondsVal = abs(seconds); + double secondsVal = glm::abs(seconds); if (secondsVal > 1e-3 && secondsVal < SecondsPerMinute) { return { seconds, seconds == 1.0 ? "second" : "seconds" }; From 87b4ec03ebc9c4126fde393adbad71c4eaf2f2a7 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 30 Nov 2017 21:48:21 -0500 Subject: [PATCH 2/8] Display error message on loading screen in case of catastrophic scene loading (closes #423) --- include/openspace/rendering/loadingscreen.h | 6 +- src/engine/openspaceengine.cpp | 112 +++++++++++--------- src/rendering/loadingscreen.cpp | 13 ++- 3 files changed, 74 insertions(+), 57 deletions(-) diff --git a/include/openspace/rendering/loadingscreen.h b/include/openspace/rendering/loadingscreen.h index 1ae6525a85..8870f9ac59 100644 --- a/include/openspace/rendering/loadingscreen.h +++ b/include/openspace/rendering/loadingscreen.h @@ -51,6 +51,7 @@ public: using ShowMessage = ghoul::Boolean; using ShowNodeNames = ghoul::Boolean; using ShowProgressbar = ghoul::Boolean; + using CatastrophicError = ghoul::Boolean; LoadingScreen(ShowMessage showMessage, ShowNodeNames showNodeNames, ShowProgressbar showProgressbar); @@ -59,6 +60,7 @@ public: void render(); void postMessage(std::string message); + void setCatastrophicError(CatastrophicError catastrophicError); void finalize(); @@ -110,6 +112,7 @@ private: GLuint vboBox; } _progressbar; + bool _hasCatastrophicErrorOccurred; std::string _message; std::mutex _messageMutex; @@ -118,9 +121,6 @@ private: ItemStatus status; bool hasLocation; -#ifdef LOADINGSCREEN_DEBUGGING - bool exhaustedSearch; -#endif // LOADINGSCREEN_DEBUGGING glm::vec2 ll; glm::vec2 ur; diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 9d0809cf5a..47267f22f9 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -576,12 +576,14 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) { } ); + bool errorWithPreInit = false; // Run start up scripts try { runPreInitializationScripts(scenePath); } catch (const ghoul::RuntimeError& e) { LERRORC(e.component, e.message); + errorWithPreInit = true; } Scene* scene; @@ -622,60 +624,68 @@ void OpenSpaceEngine::loadScene(const std::string& scenePath) { // an OpenGL context std::atomic_bool initializeFinished(false); bool errorWhileLoading = false; - std::thread t([&scene, scenePath, &initializeFinished, &errorWhileLoading, this]() { - _loadingScreen->postMessage("Creating scene..."); - _loadingScreen->setPhase(LoadingScreen::Phase::Construction); - try { - scene = _sceneManager->loadScene(scenePath); - } - catch (const ghoul::FileNotFoundError& e) { - LERRORC(e.component, e.message); - errorWhileLoading = true; - return; - } - catch (const Scene::InvalidSceneError& e) { - LERRORC(e.component, e.message); - errorWhileLoading = true; - return; - } - catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - errorWhileLoading = true; - return; - } - catch (const std::exception& e) { - LERROR(e.what()); - errorWhileLoading = true; - return; - } - catch (...) { - LERROR("Unknown error loading the scene"); - errorWhileLoading = true; - return; + std::thread t([&scene, scenePath, &initializeFinished, &errorWhileLoading, + &errorWithPreInit, this]() + { + if (errorWithPreInit) { + _loadingScreen->postMessage("Failed loading scene '" + scenePath + "'"); + _loadingScreen->setCatastrophicError(LoadingScreen::CatastrophicError::Yes); } + else { + _loadingScreen->postMessage("Creating scene..."); + _loadingScreen->setPhase(LoadingScreen::Phase::Construction); + try { + scene = _sceneManager->loadScene(scenePath); + } + catch (const ghoul::FileNotFoundError& e) { + LERRORC(e.component, e.message); + errorWhileLoading = true; + return; + } + catch (const Scene::InvalidSceneError& e) { + LERRORC(e.component, e.message); + errorWhileLoading = true; + return; + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + errorWhileLoading = true; + return; + } + catch (const std::exception& e) { + LERROR(e.what()); + errorWhileLoading = true; + return; + } + catch (...) { + LERROR("Unknown error loading the scene"); + errorWhileLoading = true; + return; + } - Scene* previousScene = _renderEngine->scene(); - if (previousScene) { - _syncEngine->removeSyncables(_timeManager->getSyncables()); - _syncEngine->removeSyncables(_renderEngine->getSyncables()); - _syncEngine->removeSyncable(_scriptEngine.get()); + Scene* previousScene = _renderEngine->scene(); + if (previousScene) { + _syncEngine->removeSyncables(_timeManager->getSyncables()); + _syncEngine->removeSyncables(_renderEngine->getSyncables()); + _syncEngine->removeSyncable(_scriptEngine.get()); - _renderEngine->setScene(nullptr); - _renderEngine->setCamera(nullptr); - _sceneManager->unloadScene(*previousScene); + _renderEngine->setScene(nullptr); + _renderEngine->setCamera(nullptr); + _sceneManager->unloadScene(*previousScene); + } + + // Initialize the RenderEngine + _renderEngine->setScene(scene); + _renderEngine->setCamera(scene->camera()); + _renderEngine->setGlobalBlackOutFactor(0.0); + _renderEngine->startFading(1, 3.0); + + _loadingScreen->setPhase(LoadingScreen::Phase::Initialization); + + scene->initialize(); + _loadingScreen->postMessage("Finished initializing"); + initializeFinished = true; } - - // Initialize the RenderEngine - _renderEngine->setScene(scene); - _renderEngine->setCamera(scene->camera()); - _renderEngine->setGlobalBlackOutFactor(0.0); - _renderEngine->startFading(1, 3.0); - - _loadingScreen->setPhase(LoadingScreen::Phase::Initialization); - - scene->initialize(); - _loadingScreen->postMessage("Finished initializing"); - initializeFinished = true; }); // While the SceneGraphNodes initialize themselves, we can hand over control to the @@ -1433,12 +1443,10 @@ void OpenSpaceEngine::externalControlCallback(const char* receivedChars, int siz void OpenSpaceEngine::toggleShutdownMode() { if (_shutdown.inShutdown) { // If we are already in shutdown mode, we want to disable it - LINFO("Disabled shutdown mode"); _shutdown.inShutdown = false; } else { // Else, we have to enable it - LINFO("Shutting down OpenSpace"); _shutdown.timer = _shutdown.waitTime; _shutdown.inShutdown = true; } diff --git a/src/rendering/loadingscreen.cpp b/src/rendering/loadingscreen.cpp index 077b0a7f5d..fb6c11b4d1 100644 --- a/src/rendering/loadingscreen.cpp +++ b/src/rendering/loadingscreen.cpp @@ -412,12 +412,17 @@ void LoadingScreen::render() { using FR = ghoul::fontrendering::FontRenderer; FR& renderer = FR::defaultRenderer(); + + std::string headline = + _hasCatastrophicErrorOccurred ? + "Failure": + "Loading..."; // We use "Loading" to center the text, but render "Loading..." to make it look more // pleasing FR::BoundingBoxInformation bbox = renderer.boundingBox( *_loadingFont, "%s", - "Loading." + headline.substr(0, headline.size() - 2).c_str() ); glm::vec2 loadingLl = glm::vec2( @@ -431,7 +436,7 @@ void LoadingScreen::render() { loadingLl, glm::vec4(1.f, 1.f, 1.f, 1.f), "%s", - "Loading..." + headline.c_str() ); glm::vec2 messageLl; @@ -620,6 +625,10 @@ void LoadingScreen::postMessage(std::string message) { _message = std::move(message); } +void LoadingScreen::setCatastrophicError(CatastrophicError catastrophicError) { + _hasCatastrophicErrorOccurred = catastrophicError; +} + void LoadingScreen::finalize() { _items.erase( std::remove_if( From 6be6149e02fa14bc2cea42e7996ed5458fbdad69 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 6 Dec 2017 17:00:50 -0500 Subject: [PATCH 3/8] Remove deprecation warning from camera functions Fix compile warning --- ext/ghoul | 2 +- include/openspace/util/camera.h | 16 ++++++++-------- src/rendering/renderengine.cpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index d7aec4688b..032aec5848 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit d7aec4688b9673d61e8885f3ce7a0d569b54b614 +Subproject commit 032aec58486a18b64bdfa297dc34091d3fa0badb diff --git a/include/openspace/util/camera.h b/include/openspace/util/camera.h index ccd767ad2d..06ad1bb247 100644 --- a/include/openspace/util/camera.h +++ b/include/openspace/util/camera.h @@ -157,22 +157,22 @@ public: } sgctInternal; // Deprecated - [[deprecated("Replaced by Camera::setPositionVec3()")]] + // [[deprecated("Replaced by Camera::setPositionVec3()")]] void setPosition(psc pos); - [[deprecated("Replaced by Camera::setFocusPositionVec3()")]] + // [[deprecated("Replaced by Camera::setFocusPositionVec3()")]] void setFocusPosition(psc pos); - [[deprecated("Replaced by Camera::positionVec3()")]] + // [[deprecated("Replaced by Camera::positionVec3()")]] psc position() const; - [[deprecated("Replaced by Camera::unsynchedPositionVec3()")]] + // [[deprecated("Replaced by Camera::unsynchedPositionVec3()")]] psc unsynchedPosition() const; - [[deprecated("Replaced by Camera::focusPositionVec3()")]] + // [[deprecated("Replaced by Camera::focusPositionVec3()")]] psc focusPosition() const; // @TODO use Camera::SgctInternal interface instead - [[deprecated("Replaced by Camera::SgctInternal::viewMatrix()")]] + // [[deprecated("Replaced by Camera::SgctInternal::viewMatrix()")]] const glm::mat4& viewMatrix() const; - [[deprecated("Replaced by Camera::SgctInternal::projectionMatrix()")]] + // [[deprecated("Replaced by Camera::SgctInternal::projectionMatrix()")]] const glm::mat4& projectionMatrix() const; - [[deprecated("Replaced by Camera::SgctInternal::viewProjectionMatrix()")]] + // [[deprecated("Replaced by Camera::SgctInternal::viewProjectionMatrix()")]] const glm::mat4& viewProjectionMatrix() const; diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index c641cd24f1..e78c58d83d 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -46,7 +46,7 @@ #include #include #include -#include > +#include #include #include #include From be98c3d784bb7037684dc626f3a9df5611261785 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 6 Dec 2017 17:04:10 -0500 Subject: [PATCH 4/8] Add TemplateProperty> as StringListProperty Add default gui sorting to all scenes --- data/scene/atmosphereearth.scene | 2 + data/scene/dawn.scene | 2 + data/scene/default.scene | 2 + data/scene/fieldlines.scene | 2 + data/scene/juno.scene | 2 + data/scene/newhorizons.scene | 1 + data/scene/osirisrex.scene | 2 + data/scene/rosetta.scene | 2 + data/scene/volumetricmilkyway.scene | 2 + data/scene/voyager.scene | 2 + .../openspace/properties/stringlistproperty.h | 39 ++++++ modules/imgui/include/guipropertycomponent.h | 4 + modules/imgui/include/renderproperties.h | 4 + modules/imgui/src/guipropertycomponent.cpp | 57 ++++++++- modules/imgui/src/renderproperties.cpp | 52 ++++++++ scripts/scene_helper.lua | 9 ++ src/CMakeLists.txt | 2 + src/properties/stringlistproperty.cpp | 120 ++++++++++++++++++ 18 files changed, 302 insertions(+), 4 deletions(-) create mode 100644 include/openspace/properties/stringlistproperty.h create mode 100644 src/properties/stringlistproperty.cpp diff --git a/data/scene/atmosphereearth.scene b/data/scene/atmosphereearth.scene index bbfaf10dd1..4bfbb611d8 100644 --- a/data/scene/atmosphereearth.scene +++ b/data/scene/atmosphereearth.scene @@ -19,6 +19,8 @@ function postInitialization() created and initialized, but before the first render call. This is the place to set graphical settings for the renderables. ]]-- + set_default_gui_sorting() + openspace.printInfo("Setting default values") openspace.setPropertyValue("Sun.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", true) diff --git a/data/scene/dawn.scene b/data/scene/dawn.scene index 6dddbc93fd..17af47aae4 100644 --- a/data/scene/dawn.scene +++ b/data/scene/dawn.scene @@ -19,6 +19,8 @@ function postInitialization() created and initialized, but before the first render call. This is the place to set graphical settings for the renderables. ]]-- + set_default_gui_sorting() + openspace.printInfo("Setting default values") openspace.setPropertyValue("Sun.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", true) diff --git a/data/scene/default.scene b/data/scene/default.scene index 682f817249..4e28cbb9a4 100644 --- a/data/scene/default.scene +++ b/data/scene/default.scene @@ -74,6 +74,8 @@ function preInitialization() end function postInitialization() + set_default_gui_sorting() + openspace.addVirtualProperty( "BoolProperty", "Show Trails", diff --git a/data/scene/fieldlines.scene b/data/scene/fieldlines.scene index 2a9da28b7c..f83e512809 100644 --- a/data/scene/fieldlines.scene +++ b/data/scene/fieldlines.scene @@ -19,6 +19,8 @@ function postInitialization() created and initialized, but before the first render call. This is the place to set graphical settings for the renderables. ]]-- + set_default_gui_sorting() + openspace.printInfo("Setting default values") openspace.setPropertyValue("Sun.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", false) diff --git a/data/scene/juno.scene b/data/scene/juno.scene index 89b3c8374a..1a9a1a3924 100755 --- a/data/scene/juno.scene +++ b/data/scene/juno.scene @@ -27,6 +27,8 @@ function postInitialization() created and initialized, but before the first render call. This is the place to set graphical settings for the renderables. ]]-- + set_default_gui_sorting() + openspace.printInfo("Setting default values") openspace.setPropertyValue("Sun.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", true) diff --git a/data/scene/newhorizons.scene b/data/scene/newhorizons.scene index ee57e63c69..0dd32ec865 100644 --- a/data/scene/newhorizons.scene +++ b/data/scene/newhorizons.scene @@ -28,6 +28,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + set_default_gui_sorting() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/osirisrex.scene b/data/scene/osirisrex.scene index 946582269a..a1b21a8e3c 100644 --- a/data/scene/osirisrex.scene +++ b/data/scene/osirisrex.scene @@ -83,6 +83,8 @@ function postInitialization() created and initialized, but before the first render call. This is the place to set graphical settings for the renderables. ]]-- + set_default_gui_sorting() + openspace.printInfo("Setting default values") openspace.setPropertyValue("Sun.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", false) diff --git a/data/scene/rosetta.scene b/data/scene/rosetta.scene index 3341deb7af..213ec20465 100644 --- a/data/scene/rosetta.scene +++ b/data/scene/rosetta.scene @@ -93,6 +93,8 @@ function postInitialization() created and initialized, but before the first render call. This is the place to set graphical settings for the renderables. ]]-- + set_default_gui_sorting() + openspace.printInfo("Setting default values") openspace.setPropertyValue("Sun.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", true) diff --git a/data/scene/volumetricmilkyway.scene b/data/scene/volumetricmilkyway.scene index 7a0708ea32..4b2b5ecabf 100644 --- a/data/scene/volumetricmilkyway.scene +++ b/data/scene/volumetricmilkyway.scene @@ -19,6 +19,8 @@ function postInitialization() created and initialized, but before the first render call. This is the place to set graphical settings for the renderables. ]]-- + set_default_gui_sorting() + openspace.printInfo("Setting default values") openspace.setPropertyValue("Sun.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", true) diff --git a/data/scene/voyager.scene b/data/scene/voyager.scene index 7d6b0430e1..4b3d77c7fc 100644 --- a/data/scene/voyager.scene +++ b/data/scene/voyager.scene @@ -19,6 +19,8 @@ end function postInitialization() openspace.printInfo("Setting default values") + set_default_gui_sorting() + openspace.setPropertyValueSingle("Global Properties.GlobeBrowsing.GdalWrapper.LogGdalErrors", false) openspace.setPropertyValueSingle("Earth.RenderableGlobe.Debug.LevelByProjectedAreaElseDistance", false) diff --git a/include/openspace/properties/stringlistproperty.h b/include/openspace/properties/stringlistproperty.h new file mode 100644 index 0000000000..0d45ae5c82 --- /dev/null +++ b/include/openspace/properties/stringlistproperty.h @@ -0,0 +1,39 @@ +/***************************************************************************************** + * * + * 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___STRINGLISTPROPERTY___H__ +#define __OPENSPACE_CORE___STRINGLISTPROPERTY___H__ + +#include + +#include +#include + +namespace openspace::properties { + +REGISTER_TEMPLATEPROPERTY_HEADER(StringListProperty, std::vector) + +} // namespace openspace::properties + +#endif // __OPENSPACE_CORE___STRINGLISTPROPERTY___H__ diff --git a/modules/imgui/include/guipropertycomponent.h b/modules/imgui/include/guipropertycomponent.h index 1a7078d898..860499a69a 100644 --- a/modules/imgui/include/guipropertycomponent.h +++ b/modules/imgui/include/guipropertycomponent.h @@ -28,6 +28,7 @@ #include #include +#include #include @@ -76,6 +77,9 @@ protected: bool _hasOnlyRegularProperties = false; UseTreeLayout _useTreeLayout; bool _currentUseTreeLayout; + + properties::StringListProperty _treeOrdering; + IsTopLevelWindow _isTopLevel; bool _showHelpTooltip; }; diff --git a/modules/imgui/include/renderproperties.h b/modules/imgui/include/renderproperties.h index 497209b318..ee61492052 100644 --- a/modules/imgui/include/renderproperties.h +++ b/modules/imgui/include/renderproperties.h @@ -57,6 +57,10 @@ void renderStringProperty(properties::Property* prop, const std::string& ownerNa IsRegularProperty isRegular = IsRegularProperty::Yes, ShowToolTip showTooltip = ShowToolTip::Yes); +void renderStringListProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes, + ShowToolTip showTooltip = ShowToolTip::Yes); + void renderDoubleProperty(properties::Property* prop, const std::string& ownerName, IsRegularProperty isRegular = IsRegularProperty::Yes, ShowToolTip showTooltip = ShowToolTip::Yes); diff --git a/modules/imgui/src/guipropertycomponent.cpp b/modules/imgui/src/guipropertycomponent.cpp index 7886957175..cb087eb80b 100644 --- a/modules/imgui/src/guipropertycomponent.cpp +++ b/modules/imgui/src/guipropertycomponent.cpp @@ -37,6 +37,14 @@ namespace { const ImVec2 size = ImVec2(350, 500); + static const openspace::properties::Property::PropertyInfo OrderingInfo = { + "Ordering", + "Tree Ordering", + "This list determines the order of the first tree layer if it is used. Elements " + "present in this list will be shown first, with an alphabetical ordering for " + "elements not listed." + }; + int nVisibleProperties(const std::vector& props, openspace::properties::Property::Visibility visibility) { @@ -151,8 +159,11 @@ GuiPropertyComponent::GuiPropertyComponent(std::string name, UseTreeLayout useTr : GuiComponent(std::move(name)) , _useTreeLayout(useTree) , _currentUseTreeLayout(useTree) + , _treeOrdering(OrderingInfo) , _isTopLevel(topLevel) -{} +{ + addProperty(_treeOrdering); +} void GuiPropertyComponent::setSource(SourceFunction function) { _function = std::move(function); @@ -236,6 +247,8 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) } void GuiPropertyComponent::render() { + using namespace properties; + if (_isTopLevel) { ImGui::Begin(name().c_str(), nullptr, size, 0.75f); } @@ -271,12 +284,14 @@ void GuiPropertyComponent::render() { } // Sort: - // if guigrouping, sort by name and shortest first + // if guigrouping, sort by name and shortest first, but respect the user + // specified ordering // then all w/o guigroup + const std::vector& ordering = _treeOrdering; std::stable_sort( owners.begin(), owners.end(), - [](properties::PropertyOwner* lhs, properties::PropertyOwner* rhs) { + [&ordering](PropertyOwner* lhs, PropertyOwner* rhs) { std::string lhsGroup = static_cast(lhs)->guiPath(); std::string rhsGroup = static_cast(rhs)->guiPath(); @@ -286,7 +301,40 @@ void GuiPropertyComponent::render() { if (rhsGroup.empty()) { return true; } - return lhsGroup < rhsGroup; + + if (ordering.empty()) { + return lhsGroup < rhsGroup; + } + + std::vector lhsToken = ghoul::tokenizeString( + lhsGroup, + '/' + ); + // The first token is always empty + auto lhsIt = std::find(ordering.begin(), ordering.end(), lhsToken[1]); + + std::vector rhsToken = ghoul::tokenizeString( + rhsGroup, + '/' + ); + // The first token is always empty + auto rhsIt = std::find(ordering.begin(), ordering.end(), rhsToken[1]); + + if (lhsIt != ordering.end() && rhsIt != ordering.end()) { + // If both top-level groups are in the ordering list, the order + // of the iterators gives us the order of the groups + return lhsIt < rhsIt; + } + else if (lhsIt != ordering.end() && rhsIt == ordering.end()) { + // If only one of them is in the list, we have a sorting + return true; + } + else if (lhsIt == ordering.end() && rhsIt != ordering.end()) { + return false; + } + else { + return lhsGroup < rhsGroup; + } } ); } @@ -398,6 +446,7 @@ void GuiPropertyComponent::renderProperty(properties::Property* prop, { "DMat3Property", &renderDMat3Property }, { "DMat4Property", &renderDMat4Property }, { "StringProperty", &renderStringProperty }, + { "StringListProperty", &renderStringListProperty }, { "OptionProperty", &renderOptionProperty }, { "TriggerProperty", &renderTriggerProperty }, { "SelectionProperty", &renderSelectionProperty } diff --git a/modules/imgui/src/renderproperties.cpp b/modules/imgui/src/renderproperties.cpp index 9900b9e06e..2751d54af0 100644 --- a/modules/imgui/src/renderproperties.cpp +++ b/modules/imgui/src/renderproperties.cpp @@ -32,10 +32,12 @@ #include #include #include +#include #include #include #include +#include namespace openspace { @@ -244,6 +246,56 @@ void renderStringProperty(Property* prop, const std::string& ownerName, ImGui::PopID(); } +void renderStringListProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular, ShowToolTip showTooltip) +{ + ghoul_assert(prop, "prop must not be nullptr"); + StringListProperty* p = static_cast(prop); + std::string name = p->guiName(); + ImGui::PushID((ownerName + "." + name).c_str()); + + std::string value; + p->getStringValue(value); + // const std::string value = p->value(); + + static const int bufferSize = 512; + static char buffer[bufferSize]; +#ifdef _MSC_VER + strcpy_s(buffer, value.length() + 1, value.c_str()); +#else + strcpy(buffer, value.c_str()); +#endif + bool hasNewValue = ImGui::InputText( + name.c_str(), + buffer, + bufferSize, + ImGuiInputTextFlags_EnterReturnsTrue + ); + if (showTooltip) { + renderTooltip(prop); + } + + if (hasNewValue) { + std::vector tokens = ghoul::tokenizeString(std::string(buffer), ','); + std::string script = "{"; + for (std::string& token : tokens) { + if (!token.empty()) { + ghoul::trimWhitespace(token); + script += "[[" + token + "]],"; + } + } + script += "}"; + + executeScript( + p->fullyQualifiedIdentifier(), + std::move(script), + isRegular + ); + } + + ImGui::PopID(); +} + void renderDoubleProperty(properties::Property* prop, const std::string& ownerName, IsRegularProperty isRegular, ShowToolTip showTooltip) { diff --git a/scripts/scene_helper.lua b/scripts/scene_helper.lua index b97a32d37c..ce611a7df9 100644 --- a/scripts/scene_helper.lua +++ b/scripts/scene_helper.lua @@ -5,3 +5,12 @@ mark_interesting_nodes = function(nodes) end end end + +set_default_gui_sorting = function() + openspace.setPropertyValueSingle( + 'Global Properties.ImGUI.Main.Properties.Ordering', + { + "Solar System", "Milky Way", "Universe", "Other" + } + ) +end \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8d0b2872fd..1970212ed7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,6 +67,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/properties/propertyowner.cpp ${OPENSPACE_BASE_DIR}/src/properties/selectionproperty.cpp ${OPENSPACE_BASE_DIR}/src/properties/stringproperty.cpp + ${OPENSPACE_BASE_DIR}/src/properties/stringlistproperty.cpp ${OPENSPACE_BASE_DIR}/src/properties/triggerproperty.cpp ${OPENSPACE_BASE_DIR}/src/properties/matrix/dmat2property.cpp ${OPENSPACE_BASE_DIR}/src/properties/matrix/dmat2x3property.cpp @@ -229,6 +230,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/properties/scalarproperty.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/selectionproperty.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/stringproperty.h + ${OPENSPACE_BASE_DIR}/include/openspace/properties/stringlistproperty.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/templateproperty.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/templateproperty.inl ${OPENSPACE_BASE_DIR}/include/openspace/properties/triggerproperty.h diff --git a/src/properties/stringlistproperty.cpp b/src/properties/stringlistproperty.cpp new file mode 100644 index 0000000000..ef137f585f --- /dev/null +++ b/src/properties/stringlistproperty.cpp @@ -0,0 +1,120 @@ +/***************************************************************************************** + * * + * 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 + +#include +#include + +#include + +namespace { + +std::vector fromLuaConversion(lua_State* state, bool& success) { + if (!lua_istable(state, -1)) { + success = false; + return {}; + } + + std::vector result; + lua_pushnil(state); + while (lua_next(state, -2) != 0) { + if (lua_isstring(state, -1)) { + result.push_back(lua_tostring(state, -1)); + } + else { + success = false; + return {}; + } + lua_pop(state, 1); + } + success = true; + return result; +} + +bool toLuaConversion(lua_State* state, std::vector val) { + lua_createtable(state, static_cast(val.size()), 0); + + int i = 1; + for (std::string& v : val) { + lua_pushstring(state, std::to_string(i).c_str()); + lua_pushstring(state, v.c_str()); + lua_settable(state, -3); + } + + return true; +} + +std::vector fromStringConversion(std::string val, bool& success) { + std::vector tokens = ghoul::tokenizeString(val, ','); + for (std::string& token : tokens) { + // Each incoming string is of the form "value" + // so we want to remove the leading and trailing " characters + if (token.size() > 2 && (token[0] == '"' && token[token.size() - 1] == '"')) { + token = token.substr(1, token.size() - 2); + } + } + + success = true; + return tokens; +} + +bool toStringConversion(std::string& outValue, std::vector inValue) { + outValue = ""; + for (const std::string& v : inValue) { + if (&v != &*inValue.cbegin()) { + outValue += ", " + v; + } + else { + outValue += v; + } + } + + // outValue = std::accumulate( + // inValue.begin(), + // inValue.end(), + // std::string(""), + // [](std::string lhs, std::string rhs) { + // return lhs + "," + "\"" + rhs + "\""; + // } + // ); + return true; +} + +} // namespace + +namespace openspace::properties { + +REGISTER_TEMPLATEPROPERTY_SOURCE( + StringListProperty, + std::vector, + std::vector(), + fromLuaConversion, + toLuaConversion, + fromStringConversion, + toStringConversion, + LUA_TTABLE +) + +} // namespace openspace::properties From 32da94262f78f92bafb5522b4b5e2bee2a64e6dd Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 6 Dec 2017 17:29:14 -0500 Subject: [PATCH 5/8] Fix uninitialized member variable in Loading screen --- src/rendering/loadingscreen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rendering/loadingscreen.cpp b/src/rendering/loadingscreen.cpp index fb6c11b4d1..9a34ec9cd0 100644 --- a/src/rendering/loadingscreen.cpp +++ b/src/rendering/loadingscreen.cpp @@ -108,6 +108,7 @@ LoadingScreen::LoadingScreen(ShowMessage showMessage, ShowNodeNames showNodeName , _loadingFont(nullptr) , _messageFont(nullptr) , _itemFont(nullptr) + , _hasCatastrophicErrorOccurred(false) , _logo{ 0, 0 } , _progressbar{ 0, 0, 0, 0 } , _randomEngine(_randomDevice()) From 11b054b0071c85502671daf439cce97e9d8466a5 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 6 Dec 2017 18:40:54 -0500 Subject: [PATCH 6/8] Move selection of Tree layout into GuiPropertyComponent property --- ext/ghoul | 2 +- modules/imgui/include/guipropertycomponent.h | 4 ++-- modules/imgui/src/guipropertycomponent.cpp | 21 +++++++++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index 032aec5848..347e2bba03 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 032aec58486a18b64bdfa297dc34091d3fa0badb +Subproject commit 347e2bba03d2788b3ec6ea2031b05675a9dd8dcb diff --git a/modules/imgui/include/guipropertycomponent.h b/modules/imgui/include/guipropertycomponent.h index 860499a69a..e42b048650 100644 --- a/modules/imgui/include/guipropertycomponent.h +++ b/modules/imgui/include/guipropertycomponent.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -75,9 +76,8 @@ protected: /// are regular, i.e., not containing wildcards, regex, or groups /// This variable only has an impact on which \c setPropertyValue function is called bool _hasOnlyRegularProperties = false; - UseTreeLayout _useTreeLayout; - bool _currentUseTreeLayout; + properties::BoolProperty _useTreeLayout; properties::StringListProperty _treeOrdering; IsTopLevelWindow _isTopLevel; diff --git a/modules/imgui/src/guipropertycomponent.cpp b/modules/imgui/src/guipropertycomponent.cpp index cb087eb80b..b336a4b719 100644 --- a/modules/imgui/src/guipropertycomponent.cpp +++ b/modules/imgui/src/guipropertycomponent.cpp @@ -37,6 +37,14 @@ namespace { const ImVec2 size = ImVec2(350, 500); + static const openspace::properties::Property::PropertyInfo UseTreeInfo = { + "TreeLayout", + "Use Tree Layout", + "If this value is checked, this component will display the properties using a " + "tree layout, rather than using a flat map. This value should only be set on " + "property windows that display SceneGraphNodes, or the application might crash." + }; + static const openspace::properties::Property::PropertyInfo OrderingInfo = { "Ordering", "Tree Ordering", @@ -157,11 +165,11 @@ namespace openspace::gui { GuiPropertyComponent::GuiPropertyComponent(std::string name, UseTreeLayout useTree, IsTopLevelWindow topLevel) : GuiComponent(std::move(name)) - , _useTreeLayout(useTree) - , _currentUseTreeLayout(useTree) + , _useTreeLayout(UseTreeInfo, useTree) , _treeOrdering(OrderingInfo) , _isTopLevel(topLevel) { + addProperty(_useTreeLayout); addProperty(_treeOrdering); } @@ -259,11 +267,6 @@ void GuiPropertyComponent::render() { } if (_function) { - if (_useTreeLayout) { - ImGui::Checkbox("Use Tree layout", &_currentUseTreeLayout); - } - - std::vector owners = _function(); std::sort( @@ -274,7 +277,7 @@ void GuiPropertyComponent::render() { } ); - if (_currentUseTreeLayout) { + if (_useTreeLayout) { for (properties::PropertyOwner* owner : owners) { ghoul_assert( dynamic_cast(owner), @@ -377,7 +380,7 @@ void GuiPropertyComponent::render() { } }; - if (!_currentUseTreeLayout || noGuiGroups) { + if (!_useTreeLayout || noGuiGroups) { std::for_each(owners.begin(), owners.end(), renderProp); } else { // _useTreeLayout && gui groups exist From 2044371719be7f9adf44bc62f57f428b11bb4f77 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 6 Dec 2017 18:50:59 -0500 Subject: [PATCH 7/8] Update Ghoul --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 032aec5848..347e2bba03 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 032aec58486a18b64bdfa297dc34091d3fa0badb +Subproject commit 347e2bba03d2788b3ec6ea2031b05675a9dd8dcb From 20bdb7b2b4132d1f61b91aac7dc52c7c1b4b4d20 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 7 Dec 2017 01:05:03 -0500 Subject: [PATCH 8/8] Use the 4K milkyway texture on default for better performance Make featured properties and space/time widget easy to disable Add setting for setting the bounds of the delta time slider Add exponent to all numerical properties and use where appropriate Add properties to Guicomponents that collapse the title bar Add new F2 key to only display the main property window --- .../digitaluniverse/digitaluniverse.mod | 2 +- .../openspace/properties/numericalproperty.h | 10 +++ .../properties/numericalproperty.inl | 54 ++++++++++++++-- modules/imgui/imguimodule.cpp | 20 ++++-- modules/imgui/include/gui.h | 2 + modules/imgui/include/guicomponent.h | 3 + modules/imgui/include/guipropertycomponent.h | 5 +- modules/imgui/include/guispacetimecomponent.h | 6 ++ modules/imgui/src/gui.cpp | 51 ++++++++++++--- modules/imgui/src/guicomponent.cpp | 8 +++ modules/imgui/src/guifilepathcomponent.cpp | 3 + .../imgui/src/guiglobebrowsingcomponent.cpp | 3 + modules/imgui/src/guihelpcomponent.cpp | 3 + modules/imgui/src/guiiswacomponent.cpp | 5 +- modules/imgui/src/guimissioncomponent.cpp | 3 + modules/imgui/src/guiparallelcomponent.cpp | 2 + modules/imgui/src/guiperformancecomponent.cpp | 3 + modules/imgui/src/guipropertycomponent.cpp | 19 +++--- modules/imgui/src/guispacetimecomponent.cpp | 64 ++++++++++--------- modules/imgui/src/renderproperties.cpp | 40 +++++++----- scripts/common.lua | 25 +++++++- 21 files changed, 246 insertions(+), 85 deletions(-) diff --git a/data/scene/milkyway/digitaluniverse/digitaluniverse.mod b/data/scene/milkyway/digitaluniverse/digitaluniverse.mod index 93bf016369..70ffc8c5e0 100644 --- a/data/scene/milkyway/digitaluniverse/digitaluniverse.mod +++ b/data/scene/milkyway/digitaluniverse/digitaluniverse.mod @@ -7,7 +7,7 @@ return { Size = 9.2E20, Segments = 40, Alpha = 0.4, - Texture = "textures/DarkUniverse_mellinger_8k.jpg", + Texture = "textures/DarkUniverse_mellinger_4k.jpg", Orientation = "Inside/Outside", FadeOutThreshould = 0.01 }, diff --git a/include/openspace/properties/numericalproperty.h b/include/openspace/properties/numericalproperty.h index 9bf680556c..16f3bee541 100644 --- a/include/openspace/properties/numericalproperty.h +++ b/include/openspace/properties/numericalproperty.h @@ -38,6 +38,8 @@ public: T maximumValue); NumericalProperty(Property::PropertyInfo info, T value, T minimumValue, T maximumValue, T steppingValue); + NumericalProperty(Property::PropertyInfo info, T value, T minimumValue, + T maximumValue, T steppingValue, float exponent); bool getLuaValue(lua_State* state) const override; bool setLuaValue(lua_State* state) override; @@ -52,6 +54,12 @@ public: T maxValue() const; void setMaxValue(T value); + T steppingValue() const; + void setSteppingValue(T value); + + float exponent() const; + void setExponent(float exponent); + virtual std::string className() const override; using TemplateProperty::operator=; @@ -60,12 +68,14 @@ protected: static const std::string MinimumValueKey; static const std::string MaximumValueKey; static const std::string SteppingValueKey; + static const std::string ExponentValueKey; std::string generateAdditionalDescription() const override; T _minimumValue; T _maximumValue; T _stepping; + float _exponent; }; } // namespace openspace::properties diff --git a/include/openspace/properties/numericalproperty.inl b/include/openspace/properties/numericalproperty.inl index 95b027b692..671e2e7fd2 100644 --- a/include/openspace/properties/numericalproperty.inl +++ b/include/openspace/properties/numericalproperty.inl @@ -229,6 +229,9 @@ const std::string NumericalProperty::MaximumValueKey = "MaximumValue"; template const std::string NumericalProperty::SteppingValueKey = "SteppingValue"; +template +const std::string NumericalProperty::ExponentValueKey = "Exponent"; + // Delegating constructors are necessary; automatic template deduction cannot // deduce template argument for 'U' if 'default' methods are used as default values in // a single constructor @@ -240,7 +243,8 @@ NumericalProperty::NumericalProperty(Property::PropertyInfo info) PropertyDelegate>::template defaultValue(), PropertyDelegate>::template defaultMinimumValue(), PropertyDelegate>::template defaultMaximumValue(), - PropertyDelegate>::template defaultSteppingValue() + PropertyDelegate>::template defaultSteppingValue(), + 1.f ) {} @@ -251,7 +255,8 @@ NumericalProperty::NumericalProperty(Property::PropertyInfo info, T value) std::move(value), PropertyDelegate>::template defaultMinimumValue(), PropertyDelegate>::template defaultMaximumValue(), - PropertyDelegate>::template defaultSteppingValue() + PropertyDelegate>::template defaultSteppingValue(), + 1.f ) {} @@ -260,18 +265,36 @@ NumericalProperty::NumericalProperty(Property::PropertyInfo info, T value, T minimumValue, T maximumValue) : NumericalProperty( std::move(info), - std::move(value), std::move(minimumValue), std::move(maximumValue), - PropertyDelegate>::template defaultSteppingValue() + std::move(value), + std::move(minimumValue), + std::move(maximumValue), + PropertyDelegate>::template defaultSteppingValue(), + 1.f ) {} template NumericalProperty::NumericalProperty(Property::PropertyInfo info, T value, T minimumValue, T maximumValue, T steppingValue) + : NumericalProperty( + std::move(info), + std::move(value), + std::move(minimumValue), + std::move(maximumValue), + std::move(steppingValue), + 1.f + ) +{} + +template +NumericalProperty::NumericalProperty(Property::PropertyInfo info, T value, + T minimumValue, T maximumValue, T steppingValue, + float exponent) : TemplateProperty(std::move(info), std::move(value)) , _minimumValue(std::move(minimumValue)) , _maximumValue(std::move(maximumValue)) , _stepping(std::move(steppingValue)) + , _exponent(exponent) {} template @@ -342,12 +365,33 @@ void NumericalProperty::setMaxValue(T value) { _maximumValue = std::move(value); } +template +T NumericalProperty::steppingValue() const { + return _steppingValue; +} + +template +void NumericalProperty::setSteppingValue(T value) { + _steppingValue = std::move(value); +} + +template +float NumericalProperty::exponent() const { + return _exponent; +} + +template +void NumericalProperty::setExponent(float exponent) { + _exponent = exponent; +} + template std::string NumericalProperty::generateAdditionalDescription() const { std::string result; result += MinimumValueKey + " = " + std::to_string(_minimumValue) + ","; result += MaximumValueKey + " = " + std::to_string(_maximumValue) + ","; - result += SteppingValueKey + " = " + std::to_string(_stepping); + result += SteppingValueKey + " = " + std::to_string(_stepping) + ","; + result += ExponentValueKey + " = " + std::to_string(_exponent); return result; } diff --git a/modules/imgui/imguimodule.cpp b/modules/imgui/imguimodule.cpp index c76772e64f..10c0d1360b 100644 --- a/modules/imgui/imguimodule.cpp +++ b/modules/imgui/imguimodule.cpp @@ -189,7 +189,10 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) { OsEng.registerModuleKeyboardCallback( [&](Key key, KeyModifier mod, KeyAction action) -> bool { - if (gui.isEnabled() || gui._performance.isEnabled()) { + // A list of all the windows that can show up by themselves + if (gui.isEnabled() || gui._performance.isEnabled() || + gui._property.isEnabled()) + { return gui.keyCallback(key, mod, action); } else { @@ -200,7 +203,10 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) { OsEng.registerModuleCharCallback( [&](unsigned int codepoint, KeyModifier modifier) -> bool { - if (gui.isEnabled() || gui._performance.isEnabled()) { + // A list of all the windows that can show up by themselves + if (gui.isEnabled() || gui._performance.isEnabled() || + gui._property.isEnabled()) + { return gui.charCallback(codepoint, modifier); } else { @@ -211,7 +217,10 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) { OsEng.registerModuleMouseButtonCallback( [&](MouseButton button, MouseAction action) -> bool { - if (gui.isEnabled() || gui._performance.isEnabled()) { + // A list of all the windows that can show up by themselves + if (gui.isEnabled() || gui._performance.isEnabled() || + gui._property.isEnabled()) + { return gui.mouseButtonCallback(button, action); } else { @@ -222,7 +231,10 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) { OsEng.registerModuleMouseScrollWheelCallback( [&](double, double posY) -> bool { - if (gui.isEnabled() || gui._performance.isEnabled()) { + // A list of all the windows that can show up by themselves + if (gui.isEnabled() || gui._performance.isEnabled() || + gui._property.isEnabled()) + { return gui.mouseWheelCallback(posY); } else { diff --git a/modules/imgui/include/gui.h b/modules/imgui/include/gui.h index 7d89e05550..13d15626f5 100644 --- a/modules/imgui/include/gui.h +++ b/modules/imgui/include/gui.h @@ -94,6 +94,8 @@ private: properties::Property::Visibility _currentVisibility; + properties::BoolProperty _allHidden; + std::vector _contexts; }; diff --git a/modules/imgui/include/guicomponent.h b/modules/imgui/include/guicomponent.h index 1821957e4b..9d6e16a998 100644 --- a/modules/imgui/include/guicomponent.h +++ b/modules/imgui/include/guicomponent.h @@ -72,6 +72,9 @@ public: protected: /// true if this component is enabled and visible on the screen properties::BoolProperty _isEnabled; + /// if true this window is currently collapsed. This setting mirrors the + /// ImGui internal state of the window + properties::BoolProperty _isCollapsed; }; } // namespace openspace::gui diff --git a/modules/imgui/include/guipropertycomponent.h b/modules/imgui/include/guipropertycomponent.h index 1a7078d898..47847267f8 100644 --- a/modules/imgui/include/guipropertycomponent.h +++ b/modules/imgui/include/guipropertycomponent.h @@ -47,11 +47,9 @@ public: using SourceFunction = std::function()>; using UseTreeLayout = ghoul::Boolean; - using IsTopLevelWindow = ghoul::Boolean; - GuiPropertyComponent(std::string name, UseTreeLayout useTree = UseTreeLayout::No, - IsTopLevelWindow isTopLevel = IsTopLevelWindow::No); + GuiPropertyComponent(std::string name, UseTreeLayout useTree = UseTreeLayout::No); // This is the function that evaluates to the list of Propertyowners that this // component should render @@ -76,7 +74,6 @@ protected: bool _hasOnlyRegularProperties = false; UseTreeLayout _useTreeLayout; bool _currentUseTreeLayout; - IsTopLevelWindow _isTopLevel; bool _showHelpTooltip; }; diff --git a/modules/imgui/include/guispacetimecomponent.h b/modules/imgui/include/guispacetimecomponent.h index 726cea870c..872b2bb4c7 100644 --- a/modules/imgui/include/guispacetimecomponent.h +++ b/modules/imgui/include/guispacetimecomponent.h @@ -27,6 +27,8 @@ #include +#include + namespace openspace::gui { class GuiSpaceTimeComponent : public GuiComponent { @@ -34,6 +36,10 @@ public: GuiSpaceTimeComponent(); void render() override; + +private: + properties::FloatProperty _minMaxDeltaTime; + float _localMinMaxDeltatime; // We don't want the default display inside the component }; } // namespace openspace::gui diff --git a/modules/imgui/src/gui.cpp b/modules/imgui/src/gui.cpp index 49541bce94..f10b5a93ae 100644 --- a/modules/imgui/src/gui.cpp +++ b/modules/imgui/src/gui.cpp @@ -253,6 +253,13 @@ static const openspace::properties::Property::PropertyInfo ShowHelpInfo = { "explaining what impact they have on the visuals." }; +static const openspace::properties::Property::PropertyInfo HiddenInfo = { + "IsHidden", + "Is Hidden", + "If this value is true, all GUI items will not be rendered, regardless of their " + "status" +}; + } // namespace namespace openspace::gui { @@ -272,23 +279,25 @@ GUI::GUI() ) , _screenSpaceProperty("ScreenSpace Properties") , _virtualProperty("Virtual Properties") - , _featuredProperties("Featured Properties", - GuiPropertyComponent::UseTreeLayout::No, - GuiPropertyComponent::IsTopLevelWindow::Yes) + , _featuredProperties("Featured Properties", GuiPropertyComponent::UseTreeLayout::No) , _showInternals(false) , _showHelpText(ShowHelpInfo, true) , _currentVisibility(properties::Property::Visibility::Developer) + , _allHidden(HiddenInfo, true) { addPropertySubOwner(_help); addPropertySubOwner(_performance); addPropertySubOwner(_globalProperty); addPropertySubOwner(_property); addPropertySubOwner(_screenSpaceProperty); + _featuredProperties.setEnabled(true); + addPropertySubOwner(_featuredProperties); addPropertySubOwner(_virtualProperty); #ifdef GLOBEBROWSING_USE_GDAL addPropertySubOwner(_globeBrowsing); #endif // GLOBEBROWSING_USE_GDAL addPropertySubOwner(_filePath); + _spaceTime.setEnabled(true); addPropertySubOwner(_spaceTime); addPropertySubOwner(_mission); #ifdef OPENSPACE_MODULE_ISWA_ENABLED @@ -302,6 +311,8 @@ GUI::GUI() _screenSpaceProperty.setShowHelpTooltip(_showHelpText); _virtualProperty.setShowHelpTooltip(_showHelpText); }); + + addProperty(_allHidden); } void GUI::initialize() { @@ -615,6 +626,11 @@ void GUI::startFrame(float deltaTime, const glm::vec2& windowSize, } void GUI::endFrame() { + LINFOC("Enabled", _isEnabled); + LINFOC("Collapsed", _isCollapsed); + LINFOC("Hidden", _allHidden); + + if (_program->isDirty()) { _program->rebuildFromFile(); } @@ -626,8 +642,11 @@ void GUI::endFrame() { _performance.render(); } - if (_isEnabled) { - render(); + if (!_allHidden) { + + if (_isEnabled) { + render(); + } if (_globalProperty.isEnabled()) { _globalProperty.render(); @@ -666,11 +685,13 @@ void GUI::endFrame() { _mission.render(); } - // We always want to render the Space/Time component - _spaceTime.render(); + if (_spaceTime.isEnabled()) { + _spaceTime.render(); + } - // We always want to render the featured properties component - _featuredProperties.render(); + if (_featuredProperties.isEnabled()) { + _featuredProperties.render(); + } } ImGui::Render(); @@ -744,7 +765,11 @@ bool GUI::charCallback(unsigned int character, KeyModifier) { } void GUI::render() { + ImGui::SetNextWindowCollapsed(_isCollapsed); + ImGui::Begin("OpenSpace GUI", nullptr); + + _isCollapsed = ImGui::IsWindowCollapsed(); bool property = _property.isEnabled(); ImGui::Checkbox("Scene Graph Properties", &property); @@ -754,10 +779,18 @@ void GUI::render() { ImGui::Checkbox("ScreenSpace Properties", &screenSpaceProperty); _screenSpaceProperty.setEnabled(screenSpaceProperty); + bool featuredProperties = _featuredProperties.isEnabled(); + ImGui::Checkbox("Featured Properties", &featuredProperties); + _featuredProperties.setEnabled(featuredProperties); + bool globalProperty = _globalProperty.isEnabled(); ImGui::Checkbox("Global Properties", &globalProperty); _globalProperty.setEnabled(globalProperty); + bool spacetime = _spaceTime.isEnabled(); + ImGui::Checkbox("Space/Time", &spacetime); + _spaceTime.setEnabled(spacetime); + bool parallel = _parallel.isEnabled(); ImGui::Checkbox("Parallel Connection", ¶llel); _parallel.setEnabled(parallel); diff --git a/modules/imgui/src/guicomponent.cpp b/modules/imgui/src/guicomponent.cpp index 98ea884383..eab952eb7d 100644 --- a/modules/imgui/src/guicomponent.cpp +++ b/modules/imgui/src/guicomponent.cpp @@ -30,6 +30,12 @@ namespace { "Is Enabled", "This setting determines whether this object will be visible or not." }; + + static const openspace::properties::Property::PropertyInfo CollapsedInfo = { + "Collapsed", + "Is Collapsed", + "This setting determines whether this window is collapsed or not." + }; } // namespace namespace openspace::gui { @@ -37,8 +43,10 @@ namespace openspace::gui { GuiComponent::GuiComponent(std::string name) : properties::PropertyOwner({ std::move(name) }) , _isEnabled(EnabledInfo, false) + , _isCollapsed(CollapsedInfo, false) { addProperty(_isEnabled); + addProperty(_isCollapsed); } bool GuiComponent::isEnabled() const { diff --git a/modules/imgui/src/guifilepathcomponent.cpp b/modules/imgui/src/guifilepathcomponent.cpp index 84fdef894f..d137fde5e2 100644 --- a/modules/imgui/src/guifilepathcomponent.cpp +++ b/modules/imgui/src/guifilepathcomponent.cpp @@ -35,8 +35,11 @@ GuiFilePathComponent::GuiFilePathComponent() {} void GuiFilePathComponent::render() { + ImGui::SetNextWindowCollapsed(_isCollapsed); + bool v = _isEnabled; ImGui::Begin("File Path", &v); + _isCollapsed = ImGui::IsWindowCollapsed(); ImGui::Text( "%s", diff --git a/modules/imgui/src/guiglobebrowsingcomponent.cpp b/modules/imgui/src/guiglobebrowsingcomponent.cpp index cee66900d8..4bfe79cd19 100644 --- a/modules/imgui/src/guiglobebrowsingcomponent.cpp +++ b/modules/imgui/src/guiglobebrowsingcomponent.cpp @@ -63,10 +63,13 @@ void GuiGlobeBrowsingComponent::render() { using Capabilities = GlobeBrowsingModule::Capabilities; using Layer = GlobeBrowsingModule::Layer; + ImGui::SetNextWindowCollapsed(_isCollapsed); + bool e = _isEnabled; ImGui::Begin("Globe Browsing", &e, WindowSize, 0.5f); _isEnabled = e; + _isCollapsed = ImGui::IsWindowCollapsed(); OnExit([]() {ImGui::End(); }); // We escape early from this function in a few places diff --git a/modules/imgui/src/guihelpcomponent.cpp b/modules/imgui/src/guihelpcomponent.cpp index 997ab5cb1b..ba979d78dc 100644 --- a/modules/imgui/src/guihelpcomponent.cpp +++ b/modules/imgui/src/guihelpcomponent.cpp @@ -37,9 +37,12 @@ GuiHelpComponent::GuiHelpComponent() {} void GuiHelpComponent::render() { + ImGui::SetNextWindowCollapsed(_isCollapsed); + bool v = _isEnabled; ImGui::Begin("Help", &v, size, 0.5f); _isEnabled = v; + _isCollapsed = ImGui::IsWindowCollapsed(); ImGui::ShowUserGuide(); ImGui::End(); } diff --git a/modules/imgui/src/guiiswacomponent.cpp b/modules/imgui/src/guiiswacomponent.cpp index ef742966b6..bf363a4c1a 100644 --- a/modules/imgui/src/guiiswacomponent.cpp +++ b/modules/imgui/src/guiiswacomponent.cpp @@ -54,11 +54,12 @@ void GuiIswaComponent::render() { bool oldGmImageValue = _gmImage; bool oldIonDataValue = _ionData; + ImGui::SetNextWindowCollapsed(_isCollapsed); + bool e = _isEnabled; - ImGui::Begin("ISWA", &e, WindowSize, 0.5f); - _isEnabled = e; + _isCollapsed = ImGui::IsWindowCollapsed(); ImGui::Text("Global Magnetosphere"); ImGui::Checkbox("Gm From Data", &_gmData); ImGui::SameLine(); diff --git a/modules/imgui/src/guimissioncomponent.cpp b/modules/imgui/src/guimissioncomponent.cpp index 1d64832502..263311dab8 100644 --- a/modules/imgui/src/guimissioncomponent.cpp +++ b/modules/imgui/src/guimissioncomponent.cpp @@ -98,9 +98,12 @@ namespace openspace::gui { GuiMissionComponent::GuiMissionComponent() : GuiComponent("Mission Information") {} void GuiMissionComponent::render() { + ImGui::SetNextWindowCollapsed(_isCollapsed); bool v = _isEnabled; ImGui::Begin(name().c_str(), &v, Size, 0.75f); _isEnabled = v; + + _isCollapsed = ImGui::IsWindowCollapsed(); ghoul_assert( MissionManager::ref().hasCurrentMission(), diff --git a/modules/imgui/src/guiparallelcomponent.cpp b/modules/imgui/src/guiparallelcomponent.cpp index 25b21479cb..25f599f0b0 100644 --- a/modules/imgui/src/guiparallelcomponent.cpp +++ b/modules/imgui/src/guiparallelcomponent.cpp @@ -159,9 +159,11 @@ void GuiParallelComponent::renderHost() { void GuiParallelComponent::render() { + ImGui::SetNextWindowCollapsed(_isCollapsed); bool v = _isEnabled; ImGui::Begin("Parallel Connection", &v); _isEnabled = v; + _isCollapsed = ImGui::IsWindowCollapsed(); ParallelConnection::Status status = OsEng.parallelConnection().status(); diff --git a/modules/imgui/src/guiperformancecomponent.cpp b/modules/imgui/src/guiperformancecomponent.cpp index 26cee553c2..68211ae965 100644 --- a/modules/imgui/src/guiperformancecomponent.cpp +++ b/modules/imgui/src/guiperformancecomponent.cpp @@ -97,9 +97,12 @@ void GuiPerformanceComponent::render() { using ghoul::SharedMemory; using namespace performance; + ImGui::SetNextWindowCollapsed(_isCollapsed); bool v = _isEnabled; ImGui::Begin("Performance", &v); _isEnabled = v; + _isCollapsed = ImGui::IsWindowCollapsed(); + RenderEngine& re = OsEng.renderEngine(); PerformanceLayout* layout = re.performanceManager()->performanceData(); diff --git a/modules/imgui/src/guipropertycomponent.cpp b/modules/imgui/src/guipropertycomponent.cpp index 7886957175..fac6fa9526 100644 --- a/modules/imgui/src/guipropertycomponent.cpp +++ b/modules/imgui/src/guipropertycomponent.cpp @@ -146,12 +146,10 @@ namespace { namespace openspace::gui { -GuiPropertyComponent::GuiPropertyComponent(std::string name, UseTreeLayout useTree, - IsTopLevelWindow topLevel) +GuiPropertyComponent::GuiPropertyComponent(std::string name, UseTreeLayout useTree) : GuiComponent(std::move(name)) , _useTreeLayout(useTree) , _currentUseTreeLayout(useTree) - , _isTopLevel(topLevel) {} void GuiPropertyComponent::setSource(SourceFunction function) { @@ -236,14 +234,13 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) } void GuiPropertyComponent::render() { - if (_isTopLevel) { - ImGui::Begin(name().c_str(), nullptr, size, 0.75f); - } - else { - bool v = _isEnabled; - ImGui::Begin(name().c_str(), &v, size, 0.75f); - _isEnabled = v; - } + ImGui::SetNextWindowCollapsed(_isCollapsed); + + bool v = _isEnabled; + ImGui::Begin(name().c_str(), &v, size, 0.75f); + _isEnabled = v; + + _isCollapsed = ImGui::IsWindowCollapsed(); if (_function) { if (_useTreeLayout) { diff --git a/modules/imgui/src/guispacetimecomponent.cpp b/modules/imgui/src/guispacetimecomponent.cpp index edd3f16057..3106d43a24 100644 --- a/modules/imgui/src/guispacetimecomponent.cpp +++ b/modules/imgui/src/guispacetimecomponent.cpp @@ -38,14 +38,34 @@ namespace { static const ImVec2 Size = ImVec2(350, 500); + + static const openspace::properties::Property::PropertyInfo MinMaxInfo = { + "MinMax", + "Minimum/Maximum value for delta time", + "This value determines the minimum and maximum value for the delta time slider." + }; + } // namespace namespace openspace::gui { -GuiSpaceTimeComponent::GuiSpaceTimeComponent() : GuiComponent("Space/Time") {} +GuiSpaceTimeComponent::GuiSpaceTimeComponent() + : GuiComponent("Space/Time") + , _minMaxDeltaTime(MinMaxInfo, 100000.f, 0.f, 1e8f, 1.f, 5.f) + , _localMinMaxDeltatime(100000.f) +{ + _minMaxDeltaTime.onChange([this]() { + _localMinMaxDeltatime = _minMaxDeltaTime; + }); + addProperty(_minMaxDeltaTime); +} void GuiSpaceTimeComponent::render() { - ImGui::Begin(name().c_str(), nullptr, Size, 0.5f, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::SetNextWindowCollapsed(_isCollapsed); + bool v = _isEnabled; + ImGui::Begin(name().c_str(), &v, Size, 0.5f, ImGuiWindowFlags_AlwaysAutoResize); + _isEnabled = v; + _isCollapsed = ImGui::IsWindowCollapsed(); std::vector nodes = OsEng.renderEngine().scene()->allSceneGraphNodes(); @@ -58,15 +78,6 @@ void GuiSpaceTimeComponent::render() { } ); - ImGui::BeginGroup(); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip( - "%s", - "These buttons and the dropdown menu determine the focus object in the scene " - "that is the center of all camera movement" - ); - } - CaptionText("Focus Selection"); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.f); @@ -117,8 +128,6 @@ void GuiSpaceTimeComponent::render() { ); } - ImGui::EndGroup(); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 20.f); ImGui::Separator(); @@ -127,15 +136,6 @@ void GuiSpaceTimeComponent::render() { ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 20.f); - - ImGui::BeginGroup(); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip( - "%s", - "These elements determine the simulation time inside OpenSpace." - ); - } - CaptionText("Time Controls"); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.f); @@ -253,17 +253,24 @@ void GuiSpaceTimeComponent::render() { ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 20.f); + bool minMaxChanged = ImGui::InputFloat( + "Time slider range", + &_localMinMaxDeltatime + ); + if (minMaxChanged) { + _minMaxDeltaTime = _localMinMaxDeltatime; + } float deltaTime = static_cast(OsEng.timeManager().time().deltaTime()); - bool changed = ImGui::SliderFloat( + bool deltaChanged = ImGui::SliderFloat( "Delta Time", &deltaTime, - -100000.f, - 100000.f, - "%.3f", + -_minMaxDeltaTime, + _minMaxDeltaTime, + "%.6f", 5.f ); - if (changed) { + if (deltaChanged) { OsEng.scriptEngine().queueScript( "openspace.time.setDeltaTime(" + std::to_string(deltaTime) + ")", scripting::ScriptEngine::RemoteScripting::Yes @@ -373,9 +380,6 @@ void GuiSpaceTimeComponent::render() { } ImGui::SameLine(); - - ImGui::EndGroup(); - ImGui::End(); } diff --git a/modules/imgui/src/renderproperties.cpp b/modules/imgui/src/renderproperties.cpp index 9900b9e06e..4684981387 100644 --- a/modules/imgui/src/renderproperties.cpp +++ b/modules/imgui/src/renderproperties.cpp @@ -256,7 +256,7 @@ void renderDoubleProperty(properties::Property* prop, const std::string& ownerNa float min = static_cast(p->minValue()); float max = static_cast(p->maxValue()); - ImGui::SliderFloat(name.c_str(), &value, min, max, "%.5f"); + ImGui::SliderFloat(name.c_str(), &value, min, max, "%.5f", p->exponent()); if (showTooltip) { renderTooltip(prop); } @@ -399,7 +399,7 @@ void renderFloatProperty(Property* prop, const std::string& ownerName, FloatProperty::ValueType value = *p; float min = p->minValue(); float max = p->maxValue(); - ImGui::SliderFloat(name.c_str(), &value, min, max, "%.5f"); + ImGui::SliderFloat(name.c_str(), &value, min, max, "%.5f", p->exponent()); if (showTooltip) { renderTooltip(prop); } @@ -428,7 +428,8 @@ void renderVec2Property(Property* prop, const std::string& ownerName, &value.x, min, max, - "%.5f" + "%.5f", + p->exponent() ); if (showTooltip) { renderTooltip(prop); @@ -469,7 +470,8 @@ void renderVec3Property(Property* prop, const std::string& ownerName, glm::value_ptr(value), min, max, - "%.5f" + "%.5f", + p->exponent() ); } if (showTooltip) { @@ -511,7 +513,8 @@ void renderVec4Property(Property* prop, const std::string& ownerName, glm::value_ptr(value), min, max, - "%.5f" + "%.5f", + p->exponent() ); } if (showTooltip) { @@ -545,7 +548,8 @@ void renderDVec2Property(Property* prop, const std::string& ownerName, &value.x, min, max, - "%.5f" + "%.5f", + p->exponent() ); if (showTooltip) { renderTooltip(prop); @@ -579,7 +583,8 @@ void renderDVec3Property(Property* prop, const std::string& ownerName, glm::value_ptr(value), min, max, - "%.5f" + "%.5f", + p->exponent() ); if (showTooltip) { renderTooltip(prop); @@ -613,7 +618,8 @@ void renderDVec4Property(Property* prop, const std::string& ownerName, &value.x, min, max, - "%.5f" + "%.5f", + p->exponent() ); if (showTooltip) { renderTooltip(prop); @@ -653,8 +659,8 @@ void renderDMat2Property(Property* prop, const std::string& ownerName, }; float max = static_cast(glm::compMax(maxValues)); - ImGui::SliderFloat2("[0]", glm::value_ptr(value[0]), min, max); - ImGui::SliderFloat2("[1]", glm::value_ptr(value[1]), min, max); + ImGui::SliderFloat2("[0]", glm::value_ptr(value[0]), min, max, "%.5f", p->exponent()); + ImGui::SliderFloat2("[1]", glm::value_ptr(value[1]), min, max, "%.5f", p->exponent()); if (showTooltip) { renderTooltip(prop); @@ -697,9 +703,9 @@ void renderDMat3Property(Property* prop, const std::string& ownerName, float max = static_cast(glm::compMax(maxValues)); - ImGui::SliderFloat3("[0]", glm::value_ptr(value[0]), min, max); - ImGui::SliderFloat3("[1]", glm::value_ptr(value[1]), min, max); - ImGui::SliderFloat3("[2]", glm::value_ptr(value[2]), min, max); + ImGui::SliderFloat3("[0]", glm::value_ptr(value[0]), min, max, "%.5f", p->exponent()); + ImGui::SliderFloat3("[1]", glm::value_ptr(value[1]), min, max, "%.5f", p->exponent()); + ImGui::SliderFloat3("[2]", glm::value_ptr(value[2]), min, max, "%.5f", p->exponent()); if (showTooltip) { renderTooltip(prop); @@ -744,10 +750,10 @@ void renderDMat4Property(Property* prop, const std::string& ownerName, float max = static_cast(glm::compMax(maxValues)); - ImGui::SliderFloat4("[0]", glm::value_ptr(value[0]), min, max); - ImGui::SliderFloat4("[1]", glm::value_ptr(value[1]), min, max); - ImGui::SliderFloat4("[2]", glm::value_ptr(value[2]), min, max); - ImGui::SliderFloat4("[3]", glm::value_ptr(value[3]), min, max); + ImGui::SliderFloat4("[0]", glm::value_ptr(value[0]), min, max, "%.5f", p->exponent()); + ImGui::SliderFloat4("[1]", glm::value_ptr(value[1]), min, max, "%.5f", p->exponent()); + ImGui::SliderFloat4("[2]", glm::value_ptr(value[2]), min, max, "%.5f", p->exponent()); + ImGui::SliderFloat4("[3]", glm::value_ptr(value[3]), min, max, "%.5f", p->exponent()); if (showTooltip) { renderTooltip(prop); diff --git a/scripts/common.lua b/scripts/common.lua index 90519ff352..bec249a5ba 100644 --- a/scripts/common.lua +++ b/scripts/common.lua @@ -14,11 +14,32 @@ helper.scheduledScript.reversible = {} helper.setCommonKeys = function() openspace.bindKeyLocal( "F1", - helper.property.invert('Global Properties.ImGUI.Main.Enabled'), - "Toggles the visibility of the on-screen GUI." + [[local b = openspace.getPropertyValue('Global Properties.ImGUI.Main.Enabled'); + openspace.setPropertyValueSingle('Global Properties.ImGUI.Main.Enabled', not b); + openspace.setPropertyValueSingle('Global Properties.ImGUI.Main.IsHidden', b);]], + "Shows or hides the entire user interface" ) + openspace.bindKeyLocal( "F2", + [[local b = openspace.getPropertyValue('Global Properties.ImGUI.Main.Properties.Enabled'); + local c = openspace.getPropertyValue('Global Properties.ImGUI.Main.IsHidden'); + openspace.setPropertyValue('Global Properties.ImGUI.*.Enabled', false); + if b and c then + -- This can happen if the main properties window is enabled, the main gui is enabled + -- and then closed again. So the main properties window is enabled, but also all + -- windows are hidden + openspace.setPropertyValueSingle('Global Properties.ImGUI.Main.IsHidden', false); + openspace.setPropertyValueSingle('Global Properties.ImGUI.Main.Properties.Enabled', true); + else + openspace.setPropertyValueSingle('Global Properties.ImGUI.Main.Properties.Enabled', not b); + openspace.setPropertyValueSingle('Global Properties.ImGUI.Main.IsHidden', b); + end]], + "Shows or hides the properties window" + ) + + openspace.bindKeyLocal( + "F3", helper.property.invert("RenderEngine.PerformanceMeasurements"), "Toogles performance measurements that shows rendering time informations." )