diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 89bc1a28f7..83b6209b01 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -25,6 +25,9 @@ #ifndef __OPENSPACE_CORE___OPENSPACEENGINE___H__ #define __OPENSPACE_CORE___OPENSPACEENGINE___H__ +#include +#include +#include #include #include #include @@ -63,7 +66,7 @@ struct CommandlineArguments { std::string configurationOverride; }; -class OpenSpaceEngine { +class OpenSpaceEngine : public properties::PropertyOwner { public: // A mode that specifies which part of the system is currently in control. // The mode can be used to limit certain features, like setting time, navigation @@ -101,6 +104,8 @@ public: std::vector encode(); void decode(std::vector data); + properties::Property::Visibility visibility() const; + bool showHiddenSceneGraphNodes() const; void toggleShutdownMode(); Mode currentMode() const; @@ -136,6 +141,8 @@ private: void resetPropertyChangeFlagsOfSubowners(openspace::properties::PropertyOwner* po); properties::BoolProperty _printEvents; + properties::OptionProperty _visibility; + properties::BoolProperty _showHiddenSceneGraphNodes; std::unique_ptr _scene; std::unique_ptr _assetManager; diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index c5967a2aeb..6e9303a271 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -62,13 +62,15 @@ class Property { public: /** * The visibility classes for Property%s. The classes are strictly ordered as - * All > Developer > User > Hidden + * Hidden > Developer > AdvancedUser > User > NoviceUser > Always */ enum class Visibility { - Hidden = 3, ///< Never visible - Developer = 2, ///< Visible in Developer mode - User = 1, ///< Visible in User mode - All = 0, ///< Visible for all types, no matter what + Hidden = 5, ///< Never visible + Developer = 4, ///< Visible in Developer mode + AdvancedUser = 3, ///< Visible in Advanced User mode + User = 2, ///< Visible in User mode + NoviceUser = 1, ///< Visible in Novice User mode + Always = 0, ///< Visible for all types, no matter what }; /** @@ -99,7 +101,7 @@ public: /// The user facing description of this Property const char* description; /// Determines the visibility of this Property in the user interface - Visibility visibility = Visibility::All; + Visibility visibility = Visibility::Always; }; /// An OnChangeHandle is returned by the onChange method to uniquely identify an @@ -119,7 +121,7 @@ public: * necessary information for this Property. #PropertyInfo::identifier needs to be * unique for each PropertyOwner. The #PropertyInfo::guiName will be stored in the * metaData to be accessed by the GUI elements using the #PropertyInfo::guiName key. - * The default visibility settings is Visibility::All, whereas the default read-only + * The default visibility settings is Visibility::Always, whereas the default read-only * state is \c false. * * \param info The PropertyInfo structure that contains all the required static diff --git a/modules/base/dashboard/dashboarditemangle.cpp b/modules/base/dashboard/dashboarditemangle.cpp index 914968f575..73c311e386 100644 --- a/modules/base/dashboard/dashboarditemangle.cpp +++ b/modules/base/dashboard/dashboarditemangle.cpp @@ -168,11 +168,6 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) { Type::Focus, "Focus" }, { Type::Camera, "Camera" } }); - _source.type.onChange([this]() { - _source.nodeName.setVisibility( - properties::Property::Visibility(_source.type == Type::Node) - ); - }); if (p.sourceType.has_value()) { _source.type = codegen::map(*p.sourceType); } @@ -201,11 +196,6 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) { Type::Focus, "Focus" }, { Type::Camera, "Camera" } }); - _reference.type.onChange([this]() { - _reference.nodeName.setVisibility( - properties::Property::Visibility(_reference.type == Type::Node) - ); - }); _reference.type = codegen::map(p.referenceType); addProperty(_reference.type); @@ -228,11 +218,6 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) { Type::Focus, "Focus" }, { Type::Camera, "Camera" } }); - _destination.type.onChange([this]() { - _destination.nodeName.setVisibility( - properties::Property::Visibility(_source.type == Type::Node) - ); - }); if (p.destinationType.has_value()) { _destination.type = codegen::map(*p.destinationType); } diff --git a/modules/imgui/imguimodule.cpp b/modules/imgui/imguimodule.cpp index f9132d9488..3019c97bb7 100644 --- a/modules/imgui/imguimodule.cpp +++ b/modules/imgui/imguimodule.cpp @@ -490,18 +490,6 @@ void ImGUIModule::renderFrame(float deltaTime, const glm::vec2& windowSize, comp->setEnabled(enabled); } - // Render and Update property visibility - // Fragile! Keep this in sync with properties::Property::Visibility - using V = properties::Property::Visibility; - int t = static_cast>(_currentVisibility); - - // Array is sorted by importance - std::array items = { "User", "Developer", "Hidden", "All" }; - ImGui::Combo("PropertyVisibility", &t, items.data(), static_cast(items.size())); - - _currentVisibility = static_cast(t); - _property.setVisibility(_currentVisibility); - #ifdef SHOW_IMGUI_HELPERS ImGui::Checkbox("ImGUI Internals", &_showInternals); if (_showInternals) { diff --git a/modules/imgui/imguimodule.h b/modules/imgui/imguimodule.h index 8c94675f2e..89dfb427f7 100644 --- a/modules/imgui/imguimodule.h +++ b/modules/imgui/imguimodule.h @@ -124,9 +124,6 @@ private: UniformCache(tex, ortho) _uniformCache; std::unique_ptr _fontTexture; - properties::Property::Visibility _currentVisibility = - properties::Property::Visibility::Developer; - std::vector _contexts; std::vector _validTouchStates; diff --git a/modules/imgui/include/guipropertycomponent.h b/modules/imgui/include/guipropertycomponent.h index fcdc5a013f..506110b00f 100644 --- a/modules/imgui/include/guipropertycomponent.h +++ b/modules/imgui/include/guipropertycomponent.h @@ -52,22 +52,17 @@ public: void setPropertyOwnerFunction( std::function()> func); - void setVisibility(properties::Property::Visibility visibility); - void render() override; protected: void renderPropertyOwner(properties::PropertyOwner* owner); void renderProperty(properties::Property* prop, properties::PropertyOwner* owner); - properties::Property::Visibility _visibility = properties::Property::Visibility::User; - std::vector _propertyOwners; std::function()> _propertyOwnerFunction; properties::BoolProperty _useTreeLayout; properties::StringListProperty _treeOrdering; - properties::BoolProperty _ignoreHiddenHint; }; } // namespace openspace::gui diff --git a/modules/imgui/src/guiparallelcomponent.cpp b/modules/imgui/src/guiparallelcomponent.cpp index 31c90bff88..07389f3e2d 100644 --- a/modules/imgui/src/guiparallelcomponent.cpp +++ b/modules/imgui/src/guiparallelcomponent.cpp @@ -42,7 +42,6 @@ namespace openspace::gui { GuiParallelComponent::GuiParallelComponent() : GuiPropertyComponent("Parallel", "Parallel Connection") { - setVisibility(properties::Property::Visibility::All); } void GuiParallelComponent::renderDisconnected() { diff --git a/modules/imgui/src/guipropertycomponent.cpp b/modules/imgui/src/guipropertycomponent.cpp index 7ccec97ed4..acc38646f0 100644 --- a/modules/imgui/src/guipropertycomponent.cpp +++ b/modules/imgui/src/guipropertycomponent.cpp @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include #include @@ -59,15 +61,17 @@ namespace { "the hidden hints are followed." }; - int nVisibleProperties(const std::vector& props, - openspace::properties::Property::Visibility visibility) + int nVisibleProperties(const std::vector& props) { + using Visibility = openspace::properties::Property::Visibility; + Visibility visibilityFilter = openspace::global::openSpaceEngine->visibility(); + return static_cast(std::count_if( props.begin(), props.end(), - [visibility](openspace::properties::Property* p) { + [visibilityFilter](openspace::properties::Property* p) { using V = openspace::properties::Property::Visibility; - return static_cast>(visibility) >= + return static_cast>(visibilityFilter) >= static_cast>(p->visibility()); } )); @@ -187,11 +191,9 @@ GuiPropertyComponent::GuiPropertyComponent(std::string identifier, std::string g : GuiComponent(std::move(identifier), std::move(guiName)) , _useTreeLayout(UseTreeInfo, useTree) , _treeOrdering(OrderingInfo) - , _ignoreHiddenHint(IgnoreHiddenInfo) { addProperty(_useTreeLayout); addProperty(_treeOrdering); - addProperty(_ignoreHiddenHint); } void GuiPropertyComponent::setPropertyOwners( @@ -206,10 +208,6 @@ void GuiPropertyComponent::setPropertyOwnerFunction( _propertyOwnerFunction = std::move(func); } -void GuiPropertyComponent::setVisibility(properties::Property::Visibility visibility) { - _visibility = visibility; -} - void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) { using namespace properties; @@ -217,12 +215,12 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) return; } - const int nThisProperty = nVisibleProperties(owner->properties(), _visibility); + const int nThisProperty = nVisibleProperties(owner->properties()); ImGui::PushID(owner->identifier().c_str()); const std::vector& subOwners = owner->propertySubOwners(); for (PropertyOwner* subOwner : subOwners) { const std::vector& properties = subOwner->propertiesRecursive(); - int count = nVisibleProperties(properties, _visibility); + int count = nVisibleProperties(properties); if (count == 0) { continue; } @@ -286,6 +284,7 @@ void GuiPropertyComponent::render() { ImGui::SetNextWindowBgAlpha(0.75f); ImGui::Begin(guiName().c_str(), &v); _isEnabled = v; + bool showHiddenNode = openspace::global::openSpaceEngine->showHiddenSceneGraphNodes(); _isCollapsed = ImGui::IsWindowCollapsed(); using namespace properties; @@ -373,12 +372,14 @@ void GuiPropertyComponent::render() { dynamic_cast(*owners.begin())->guiPath().empty()); auto renderProp = [&](properties::PropertyOwner* pOwner) { - const int count = nVisibleProperties(pOwner->propertiesRecursive(), _visibility); + const int count = nVisibleProperties(pOwner->propertiesRecursive()); if (count == 0) { return; } + + auto header = [&]() -> bool { if (owners.size() > 1) { // Create a header in case we have multiple owners @@ -402,7 +403,7 @@ void GuiPropertyComponent::render() { }; if (!_useTreeLayout || noGuiGroups) { - if (!_ignoreHiddenHint) { + if (!showHiddenNode) { // Remove all of the nodes that we want hidden first owners.erase( std::remove_if( @@ -424,7 +425,7 @@ void GuiPropertyComponent::render() { for (properties::PropertyOwner* pOwner : owners) { // We checked above that pOwner is a SceneGraphNode SceneGraphNode* nOwner = static_cast(pOwner); - if (!_ignoreHiddenHint && nOwner->hasGuiHintHidden()) { + if (!showHiddenNode && nOwner->hasGuiHintHidden()) { continue; } const std::string gui = nOwner->guiPath(); @@ -491,7 +492,9 @@ void GuiPropertyComponent::renderProperty(properties::Property* prop, // Check if the visibility of the property is high enough to be displayed using V = properties::Property::Visibility; - const auto v = static_cast>(_visibility); + using Visibility = openspace::properties::Property::Visibility; + Visibility visibilityFilter = openspace::global::openSpaceEngine->visibility(); + const auto v = static_cast>(visibilityFilter); const auto propV = static_cast>(prop->visibility()); if (v >= propV) { auto it = FunctionMapping.find(prop->className()); diff --git a/modules/iswa/rendering/dataplane.cpp b/modules/iswa/rendering/dataplane.cpp index fdabcae90f..6f2120092c 100644 --- a/modules/iswa/rendering/dataplane.cpp +++ b/modules/iswa/rendering/dataplane.cpp @@ -63,7 +63,7 @@ void DataPlane::initializeGL() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); } }); } diff --git a/modules/iswa/rendering/datasphere.cpp b/modules/iswa/rendering/datasphere.cpp index 7fadb45dcb..82aa3a96cf 100644 --- a/modules/iswa/rendering/datasphere.cpp +++ b/modules/iswa/rendering/datasphere.cpp @@ -74,7 +74,7 @@ void DataSphere::initializeGL() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); //_backgroundValues.setVisible(true); } }); diff --git a/modules/iswa/rendering/iswadatagroup.cpp b/modules/iswa/rendering/iswadatagroup.cpp index 846b62531b..191f2491bc 100644 --- a/modules/iswa/rendering/iswadatagroup.cpp +++ b/modules/iswa/rendering/iswadatagroup.cpp @@ -134,7 +134,7 @@ void IswaDataGroup::registerProperties() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); //_backgroundValues.setVisible(true); } ghoul::Dictionary d; diff --git a/modules/iswa/rendering/kameleonplane.cpp b/modules/iswa/rendering/kameleonplane.cpp index 3763103b3c..2e60c7276e 100644 --- a/modules/iswa/rendering/kameleonplane.cpp +++ b/modules/iswa/rendering/kameleonplane.cpp @@ -151,7 +151,7 @@ void KameleonPlane::initializeGL() { // else if autofilter is turned off, register backgroundValues } else { - _backgroundValues.setVisibility(properties::Property::Visibility::All); + _backgroundValues.setVisibility(properties::Property::Visibility::Always); //_backgroundValues.setVisible(true); } }); diff --git a/scripts/developer_settings.lua b/scripts/developer_settings.lua new file mode 100644 index 0000000000..8957cd3911 --- /dev/null +++ b/scripts/developer_settings.lua @@ -0,0 +1,4 @@ +if os.getenv("OPENSPACE_DEVELOPER") +then + openspace.setPropertyValueSingle('OpenSpaceEngine.PropertyVisibility', 4) +end diff --git a/src/engine/globals.cpp b/src/engine/globals.cpp index 2589c92acf..f3d5b37ada 100644 --- a/src/engine/globals.cpp +++ b/src/engine/globals.cpp @@ -399,6 +399,7 @@ void initialize() { rootPropertyOwner->addPropertySubOwner(global::dashboard); rootPropertyOwner->addPropertySubOwner(global::userPropertyOwner); + rootPropertyOwner->addPropertySubOwner(global::openSpaceEngine); syncEngine->addSyncable(global::scriptEngine); } diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index fda036956b..131e681f2b 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -118,12 +118,25 @@ namespace { } } - openspace::properties::Property::PropertyInfo PrintEventsInfo = { + constexpr openspace::properties::Property::PropertyInfo PrintEventsInfo = { "PrintEvents", "Print Events", "If this is enabled, all events that are propagated through the system are " "printed to the log." }; + + constexpr openspace::properties::Property::PropertyInfo VisibilityInfo = { + "PropertyVisibility", + "Property Visibility", + "Hides or displays different settings in the GUI depending on how advanced they " + "are." + }; + + constexpr openspace::properties::Property::PropertyInfo ShowHiddenSceneInfo = { + "ShowHiddenSceneGraphNodes", + "Show Hidden Scene Graph Nodes", + "If checked, hidden scene graph nodes are visible in the UI" + }; } // namespace namespace openspace { @@ -131,7 +144,10 @@ namespace openspace { class Scene; OpenSpaceEngine::OpenSpaceEngine() - : _printEvents(PrintEventsInfo, false) + : properties::PropertyOwner({ "OpenSpaceEngine" }) + , _printEvents(PrintEventsInfo, false) + , _visibility(VisibilityInfo) + , _showHiddenSceneGraphNodes(ShowHiddenSceneInfo, false) { FactoryManager::initialize(); FactoryManager::ref().addFactory("Renderable"); @@ -146,6 +162,19 @@ OpenSpaceEngine::OpenSpaceEngine() SpiceManager::initialize(); TransformationManager::initialize(); + + addProperty(_printEvents); + addProperty(_visibility); + addProperty(_showHiddenSceneGraphNodes); + + using Visibility = openspace::properties::Property::Visibility; + _visibility.addOptions({ + { static_cast(Visibility::NoviceUser), "Novice User" }, + { static_cast(Visibility::User), "User" }, + { static_cast(Visibility::AdvancedUser), "Advanced User" }, + { static_cast(Visibility::Developer), "Developer" }, + { static_cast(Visibility::Hidden), "Everything" }, + }); } OpenSpaceEngine::~OpenSpaceEngine() {} // NOLINT @@ -1192,6 +1221,8 @@ void OpenSpaceEngine::preSynchronization() { if (_isRenderingFirstFrame) { setCameraFromProfile(*global::profile); setAdditionalScriptsFromProfile(*global::profile); + + global::scriptEngine->runScriptFile(absPath("${SCRIPTS}/developer_settings.lua")); } // Handle callback(s) for change in engine mode @@ -1582,6 +1613,14 @@ void OpenSpaceEngine::decode(std::vector data) { global::syncEngine->decodeSyncables(std::move(data)); } +properties::Property::Visibility openspace::OpenSpaceEngine::visibility() const { + return static_cast(_visibility.value()); +} + +bool openspace::OpenSpaceEngine::showHiddenSceneGraphNodes() const { + return _showHiddenSceneGraphNodes; +} + void OpenSpaceEngine::toggleShutdownMode() { if (_shutdown.inShutdown) { // If we are already in shutdown mode, we want to disable it diff --git a/src/properties/optionproperty.cpp b/src/properties/optionproperty.cpp index 1c04f60191..41fb74aeb6 100644 --- a/src/properties/optionproperty.cpp +++ b/src/properties/optionproperty.cpp @@ -72,6 +72,8 @@ void OptionProperty::addOption(int value, std::string desc) { } } _options.push_back(std::move(option)); + // Set default value to option added first + NumericalProperty::setValue(_options[0].value); } void OptionProperty::addOptions(std::vector> options) { @@ -100,7 +102,7 @@ void OptionProperty::setValue(int value) { // @TODO(abock): This should be setValue(value) instead or otherwise the // stored indices and option values start to drift if the // operator T of the OptionProperty is used - NumericalProperty::setValue(static_cast(i)); + NumericalProperty::setValue(static_cast(value)); return; } } @@ -110,12 +112,26 @@ void OptionProperty::setValue(int value) { } bool OptionProperty::hasOption() const { - return value() >= 0 && value() < static_cast(_options.size()); + auto it = std::find_if( + _options.begin(), + _options.end(), + [setValue = value()](const Option& option) { + return option.value == setValue; + } + ); + return it !=_options.end(); } const OptionProperty::Option& OptionProperty::option() const { - return _options[value()]; + auto it = std::find_if( + _options.begin(), + _options.end(), + [setValue = value()](const Option& option) { + return option.value == setValue; + } + ); + return *it; } std::string OptionProperty::getDescriptionByValue(int value) { diff --git a/src/properties/property.cpp b/src/properties/property.cpp index cc6adf7b3d..573666e9ef 100644 --- a/src/properties/property.cpp +++ b/src/properties/property.cpp @@ -339,9 +339,11 @@ std::string Property::generateBaseJsonDescription() const { std::string Property::generateMetaDataJsonDescription() const { static const std::map VisibilityConverter = { - { Visibility::All, "All" }, - { Visibility::Developer, "Developer" }, + { Visibility::Always, "Always" }, + { Visibility::NoviceUser, "NoviceUser" }, { Visibility::User, "User" }, + { Visibility::AdvancedUser, "AdvancedUser" }, + { Visibility::Developer, "Developer" }, { Visibility::Hidden, "Hidden" } }; Visibility visibility = static_cast(