diff --git a/data/scene/default.scene b/data/scene/default.scene index b28458aa52..3714385858 100644 --- a/data/scene/default.scene +++ b/data/scene/default.scene @@ -11,7 +11,6 @@ function preInitialization() openspace.time.setTime(openspace.time.currentWallTime()) dofile(openspace.absPath('${SCRIPTS}/bind_common_keys.lua')) - end function postInitialization() @@ -28,6 +27,8 @@ function postInitialization() openspace.setPropertyValue("MilkyWay.renderable.transparency", 0.55) openspace.setPropertyValue("MilkyWay.renderable.segments", 50) + openspace.addVirtualProperty("BoolProperty", "Show Trails", "*Trail.renderable.enabled", true, nil, nil) + openspace.resetCameraDirection() openspace.printInfo("Done setting default values") diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 9390a09c87..b13bc94b6e 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -56,6 +56,7 @@ class ParallelConnection; class RenderEngine; class SettingsEngine; class SceneManager; +class VirtualPropertyManager; class SyncEngine; class TimeManager; @@ -124,6 +125,7 @@ public: properties::PropertyOwner& globalPropertyOwner(); scripting::ScriptEngine& scriptEngine(); scripting::ScriptScheduler& scriptScheduler(); + VirtualPropertyManager& virtualPropertyManager(); // This method is only to be called from Modules @@ -169,7 +171,6 @@ public: private: OpenSpaceEngine(std::string programName, std::unique_ptr windowWrapper); - ~OpenSpaceEngine() = default; void loadScene(const std::string& scenePath); void gatherCommandlineArguments(); @@ -195,6 +196,7 @@ private: std::unique_ptr _interactionHandler; std::unique_ptr _scriptEngine; std::unique_ptr _scriptScheduler; + std::unique_ptr _virtualPropertyManager; // Others std::unique_ptr _globalPropertyNamespace; diff --git a/include/openspace/engine/virtualpropertymanager.h b/include/openspace/engine/virtualpropertymanager.h new file mode 100644 index 0000000000..5c1192ede0 --- /dev/null +++ b/include/openspace/engine/virtualpropertymanager.h @@ -0,0 +1,50 @@ +/***************************************************************************************** + * * + * 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___VIRTUALPROPERTYMANAGER___H__ +#define __OPENSPACE_CORE___VIRTUALPROPERTYMANAGER___H__ + +#include + +#include + +#include +#include + +namespace openspace { + +class VirtualPropertyManager : public properties::PropertyOwner { +public: + VirtualPropertyManager(); + + void addProperty(std::unique_ptr prop); + void removeProperty(properties::Property* prop); + +private: + std::vector> _properties; +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___VIRTUALPROPERTYMANAGER___H__ diff --git a/modules/onscreengui/include/gui.h b/modules/onscreengui/include/gui.h index e1b3b45484..36401a7f8d 100644 --- a/modules/onscreengui/include/gui.h +++ b/modules/onscreengui/include/gui.h @@ -69,6 +69,7 @@ public: GuiPropertyComponent _globalProperty; GuiPropertyComponent _property; GuiPropertyComponent _screenSpaceProperty; + GuiPropertyComponent _virtualProperty; GuiTimeComponent _time; GuiIswaComponent _iswa; diff --git a/modules/onscreengui/include/guipropertycomponent.h b/modules/onscreengui/include/guipropertycomponent.h index 4fc0bb83ea..2ab3802f96 100644 --- a/modules/onscreengui/include/guipropertycomponent.h +++ b/modules/onscreengui/include/guipropertycomponent.h @@ -53,6 +53,7 @@ public: void setSource(SourceFunction func); void setVisibility(properties::Property::Visibility visibility); + void setHasRegularProperties(bool hasOnlyRegularProperties); void render(); @@ -63,6 +64,10 @@ protected: properties::Property::Visibility _visibility; SourceFunction _function; + /// This is set to \c true if all properties contained in this GUIPropertyComponent + /// 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; }; } // namespace gui diff --git a/modules/onscreengui/include/renderproperties.h b/modules/onscreengui/include/renderproperties.h index 8f6cb2de88..69a951bea1 100644 --- a/modules/onscreengui/include/renderproperties.h +++ b/modules/onscreengui/include/renderproperties.h @@ -25,32 +25,71 @@ #ifndef __OPENSPACE_MODULE_ONSCREENGUI___RENDERPROPERTIES___H__ #define __OPENSPACE_MODULE_ONSCREENGUI___RENDERPROPERTIES___H__ +#include + #include namespace openspace { namespace properties { class Property; -} +} // namespace properties -void executeScript(const std::string& id, const std::string& value); -void renderBoolProperty(properties::Property* prop, const std::string& ownerName); -void renderOptionProperty(properties::Property* prop, const std::string& ownerName); -void renderSelectionProperty(properties::Property* prop, const std::string& ownerName); -void renderStringProperty(properties::Property* prop, const std::string& ownerName); -void renderDoubleProperty(properties::Property* prop, const std::string& ownerName); -void renderIntProperty(properties::Property* prop, const std::string& ownerName); -void renderIVec2Property(properties::Property* prop, const std::string& ownerName); -void renderIVec3Property(properties::Property* prop, const std::string& ownerName); -void renderIVec4Property(properties::Property* prop, const std::string& ownerName); -void renderFloatProperty(properties::Property* prop, const std::string& ownerName); -void renderVec2Property(properties::Property* prop, const std::string& ownerName); -void renderVec3Property(properties::Property* prop, const std::string& ownerName); -void renderVec4Property(properties::Property* prop, const std::string& ownerName); -void renderDVec2Property(properties::Property* prop, const std::string& ownerName); -void renderDVec3Property(properties::Property* prop, const std::string& ownerName); -void renderDVec4Property(properties::Property* prop, const std::string& ownerName); -void renderTriggerProperty(properties::Property* prop, const std::string& ownerName); +using IsRegularProperty = ghoul::Boolean; + +void executeScript(const std::string& id, const std::string& value, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderBoolProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderOptionProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderSelectionProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderStringProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderDoubleProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderIntProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderIVec2Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderIVec3Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderIVec4Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderFloatProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderVec2Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderVec3Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderVec4Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderDVec2Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderDVec3Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderDVec4Property(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); + +void renderTriggerProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular = IsRegularProperty::Yes); } // namespace openspace diff --git a/modules/onscreengui/onscreenguimodule.cpp b/modules/onscreengui/onscreenguimodule.cpp index 324d084c45..7698ae7a1e 100644 --- a/modules/onscreengui/onscreenguimodule.cpp +++ b/modules/onscreengui/onscreenguimodule.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,7 @@ OnScreenGUIModule::OnScreenGUIModule() : OpenSpaceModule("OnScreenGUI") { addPropertySubOwner(gui); - + OsEng.registerModuleCallback( OpenSpaceEngine::CallbackOption::Initialize, [](){ @@ -66,17 +67,29 @@ OnScreenGUIModule::OnScreenGUIModule() gui._screenSpaceProperty.setSource( []() { - const auto& ssr = OsEng.renderEngine().screenSpaceRenderables(); + const std::vector& ssr = + OsEng.renderEngine().screenSpaceRenderables(); return std::vector(ssr.begin(), ssr.end()); } ); gui._property.setSource( []() { - const auto& nodes = OsEng.renderEngine().scene()->allSceneGraphNodes(); + const std::vector& nodes = + OsEng.renderEngine().scene()->allSceneGraphNodes(); return std::vector(nodes.begin(), nodes.end()); } ); + + gui._virtualProperty.setSource( + []() { + std::vector res = { + &(OsEng.virtualPropertyManager()) + }; + + return res; + } + ); } ); diff --git a/modules/onscreengui/src/gui.cpp b/modules/onscreengui/src/gui.cpp index 933406f5b1..325375639a 100644 --- a/modules/onscreengui/src/gui.cpp +++ b/modules/onscreengui/src/gui.cpp @@ -227,6 +227,7 @@ GUI::GUI() , _globalProperty("Global") , _property("Properties") , _screenSpaceProperty("ScreenSpace Properties") + , _virtualProperty("Virtual Properties") , _currentVisibility(properties::Property::Visibility::All) { addPropertySubOwner(_help); @@ -235,6 +236,7 @@ GUI::GUI() addPropertySubOwner(_globalProperty); addPropertySubOwner(_property); addPropertySubOwner(_screenSpaceProperty); + addPropertySubOwner(_virtualProperty); addPropertySubOwner(_time); addPropertySubOwner(_iswa); } @@ -312,8 +314,12 @@ void GUI::initialize() { style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.0f); _property.initialize(); + _property.setHasRegularProperties(true); _screenSpaceProperty.initialize(); + _screenSpaceProperty.setHasRegularProperties(true); _globalProperty.initialize(); + _globalProperty.setHasRegularProperties(true); + _virtualProperty.initialize(); _performance.initialize(); _help.initialize(); _iswa.initialize(); @@ -327,6 +333,7 @@ void GUI::deinitialize() { _performance.deinitialize(); _globalProperty.deinitialize(); _screenSpaceProperty.deinitialize(); + _virtualProperty.deinitialize(); _property.deinitialize(); delete iniFileBuffer; @@ -465,6 +472,10 @@ void GUI::endFrame() { _screenSpaceProperty.render(); } + if (_virtualProperty.isEnabled()) { + _virtualProperty.render(); + } + if (_help.isEnabled()) { _help.render(); } @@ -559,6 +570,10 @@ void GUI::render() { ImGui::Checkbox("Global Properties", &globalProperty); _globalProperty.setEnabled(globalProperty); + bool virtualProperty = _virtualProperty.isEnabled(); + ImGui::Checkbox("Virtual Properties", &virtualProperty); + _virtualProperty.setEnabled(virtualProperty); + #ifdef OPENSPACE_MODULE_ISWA_ENABLED bool iswa = _iswa.isEnabled(); ImGui::Checkbox("iSWA", &iswa); @@ -617,6 +632,7 @@ void GUI::renderAndUpdatePropertyVisibility() { _globalProperty.setVisibility(_currentVisibility); _property.setVisibility(_currentVisibility); _screenSpaceProperty.setVisibility(_currentVisibility); + _virtualProperty.setVisibility(_currentVisibility); } diff --git a/modules/onscreengui/src/guiiswacomponent.cpp b/modules/onscreengui/src/guiiswacomponent.cpp index 870d854633..b0a36ebb91 100644 --- a/modules/onscreengui/src/guiiswacomponent.cpp +++ b/modules/onscreengui/src/guiiswacomponent.cpp @@ -38,8 +38,8 @@ namespace { using json = nlohmann::json; - const std::string _loggerCat = "iSWAComponent"; -} + const ImVec2 size = ImVec2(350, 500); +} // namespace namespace openspace { namespace gui { diff --git a/modules/onscreengui/src/guipropertycomponent.cpp b/modules/onscreengui/src/guipropertycomponent.cpp index a6946957d1..29c43c75c9 100644 --- a/modules/onscreengui/src/guipropertycomponent.cpp +++ b/modules/onscreengui/src/guipropertycomponent.cpp @@ -69,6 +69,10 @@ void GuiPropertyComponent::setVisibility(properties::Property::Visibility visibi _visibility = visibility; } +void GuiPropertyComponent::setHasRegularProperties(bool hasOnlyRegularProperties) { + _hasOnlyRegularProperties = hasOnlyRegularProperties; +} + void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) { if (owner->propertiesRecursive().empty()) { return; @@ -94,7 +98,9 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) } } - ImGui::Spacing(); + if (!subOwners.empty()) { + ImGui::Spacing(); + } using Properties = std::vector; std::map propertiesByGroup; @@ -119,7 +125,9 @@ void GuiPropertyComponent::renderPropertyOwner(properties::PropertyOwner* owner) } } - ImGui::Spacing(); + if (!propertiesByGroup.empty()) { + ImGui::Spacing(); + } for (properties::Property* prop : remainingProperies) { renderProperty(prop, owner); @@ -132,8 +140,6 @@ void GuiPropertyComponent::render() { ImGui::Begin(name().c_str(), &v, size, 0.5f); _isEnabled = v; - ImGui::Spacing(); - if (_function) { std::vector owners = _function(); std::sort( @@ -156,12 +162,16 @@ void GuiPropertyComponent::render() { // Create a header in case we have multiple owners return ImGui::CollapsingHeader(pOwner->name().c_str()); } - else { - // Otherwise, do nothing + else if (!pOwner->name().empty()) { + // If the owner has a name, print it first ImGui::Text(pOwner->name().c_str()); ImGui::Spacing(); return true; } + else { + // Otherwise, do nothing + return true; + } }; if (header()) { @@ -176,7 +186,7 @@ void GuiPropertyComponent::render() { void GuiPropertyComponent::renderProperty(properties::Property* prop, properties::PropertyOwner* owner) { - using Func = std::function; + using Func = std::function; static const std::map FunctionMapping = { { "BoolProperty", &renderBoolProperty }, { "DoubleProperty", &renderDoubleProperty}, @@ -204,7 +214,20 @@ void GuiPropertyComponent::renderProperty(properties::Property* prop, if (v >= propV) { auto it = FunctionMapping.find(prop->className()); if (it != FunctionMapping.end()) { - it->second(prop, owner->name()); + if (owner) { + it->second( + prop, + owner->name(), + IsRegularProperty(_hasOnlyRegularProperties) + ); + } + else { + it->second( + prop, + "", + IsRegularProperty(_hasOnlyRegularProperties) + ); + } } } } diff --git a/modules/onscreengui/src/renderproperties.cpp b/modules/onscreengui/src/renderproperties.cpp index 63693c1f77..0e4ad7b3e3 100644 --- a/modules/onscreengui/src/renderproperties.cpp +++ b/modules/onscreengui/src/renderproperties.cpp @@ -46,13 +46,33 @@ void renderTooltip(Property* prop) { } } -void executeScript(const std::string& id, const std::string& value) { +void executeScriptSingle(const std::string& id, const std::string& value) { std::string script = "openspace.setPropertyValueSingle('" + id + "', " + value + ");"; OsEng.scriptEngine().queueScript(script, scripting::ScriptEngine::RemoteScripting::Yes); } -void renderBoolProperty(Property* prop, const std::string& ownerName) { +void executeScriptGroup(const std::string& id, const std::string& value) { + std::string script = + "openspace.setPropertyValue('" + id + "', " + value + ");"; + OsEng.scriptEngine().queueScript(script, scripting::ScriptEngine::RemoteScripting::Yes); +} + +void executeScript(const std::string& id, const std::string& value, + IsRegularProperty isRegular) +{ + if (isRegular) { + executeScriptSingle(id, value); + } + else { + executeScriptGroup(id, value); + } +} + +void renderBoolProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); BoolProperty* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -62,12 +82,15 @@ void renderBoolProperty(Property* prop, const std::string& ownerName) { renderTooltip(prop); if (value != p->value()) { - executeScript(p->fullyQualifiedIdentifier(), value ? "true" : "false"); + executeScript(p->fullyQualifiedIdentifier(), value ? "true" : "false", isRegular); } ImGui::PopID(); } -void renderOptionProperty(Property* prop, const std::string& ownerName) { +void renderOptionProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); OptionProperty* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -94,12 +117,15 @@ void renderOptionProperty(Property* prop, const std::string& ownerName) { } } if (value != p->value()) { - executeScript(p->fullyQualifiedIdentifier(), std::to_string(value)); + executeScript(p->fullyQualifiedIdentifier(), std::to_string(value), isRegular); } ImGui::PopID(); } -void renderSelectionProperty(Property* prop, const std::string& ownerName) { +void renderSelectionProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); SelectionProperty* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -130,14 +156,17 @@ void renderSelectionProperty(Property* prop, const std::string& ownerName) { parameters += std::to_string(i) + ","; } parameters += "}"; - executeScript(p->fullyQualifiedIdentifier(), parameters); + executeScript(p->fullyQualifiedIdentifier(), parameters, isRegular); } ImGui::TreePop(); } ImGui::PopID(); } -void renderStringProperty(Property* prop, const std::string& ownerName) { +void renderStringProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); StringProperty* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -161,13 +190,20 @@ void renderStringProperty(Property* prop, const std::string& ownerName) { if (hasNewValue) { - executeScript(p->fullyQualifiedIdentifier(), "'" + std::string(buffer) + "'"); + executeScript( + p->fullyQualifiedIdentifier(), + "'" + std::string(buffer) + "'", + isRegular + ); } ImGui::PopID(); } -void renderDoubleProperty(properties::Property* prop, const std::string& ownerName) { +void renderDoubleProperty(properties::Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); DoubleProperty* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -180,13 +216,16 @@ void renderDoubleProperty(properties::Property* prop, const std::string& ownerNa renderTooltip(prop); if (value != static_cast(p->value())) { - executeScript(p->fullyQualifiedIdentifier(), std::to_string(value)); + executeScript(p->fullyQualifiedIdentifier(), std::to_string(value), isRegular); } ImGui::PopID(); } -void renderIntProperty(Property* prop, const std::string& ownerName) { +void renderIntProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); IntProperty* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -199,13 +238,16 @@ void renderIntProperty(Property* prop, const std::string& ownerName) { renderTooltip(prop); if (value != p->value()) { - executeScript(p->fullyQualifiedIdentifier(), std::to_string(value)); + executeScript(p->fullyQualifiedIdentifier(), std::to_string(value), isRegular); } ImGui::PopID(); } -void renderIVec2Property(Property* prop, const std::string& ownerName) { +void renderIVec2Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); IVec2Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -224,14 +266,18 @@ void renderIVec2Property(Property* prop, const std::string& ownerName) { if (value != p->value()) { executeScript( p->fullyQualifiedIdentifier(), - "{" + std::to_string(value.x) + "," + std::to_string(value.y) + "}" + "{" + std::to_string(value.x) + "," + std::to_string(value.y) + "}", + isRegular ); } ImGui::PopID(); } -void renderIVec3Property(Property* prop, const std::string& ownerName) { +void renderIVec3Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); IVec3Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -252,13 +298,17 @@ void renderIVec3Property(Property* prop, const std::string& ownerName) { executeScript( p->fullyQualifiedIdentifier(), "{" + std::to_string(value.x) + "," + std::to_string(value.y) + "," + - std::to_string(value.z) + "}" + std::to_string(value.z) + "}", + isRegular ); } ImGui::PopID(); } -void renderIVec4Property(Property* prop, const std::string& ownerName) { +void renderIVec4Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); IVec4Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -283,15 +333,19 @@ void renderIVec4Property(Property* prop, const std::string& ownerName) { executeScript( p->fullyQualifiedIdentifier(), "{" + std::to_string(value.x) + "," + - std::to_string(value.y) + "," + - std::to_string(value.z) + "," + - std::to_string(value.w) + "}" + std::to_string(value.y) + "," + + std::to_string(value.z) + "," + + std::to_string(value.w) + "}", + isRegular ); } ImGui::PopID(); } -void renderFloatProperty(Property* prop, const std::string& ownerName) { +void renderFloatProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); FloatProperty* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -303,13 +357,16 @@ void renderFloatProperty(Property* prop, const std::string& ownerName) { renderTooltip(prop); if (value != p->value()) { - executeScript(p->fullyQualifiedIdentifier(), std::to_string(value)); + executeScript(p->fullyQualifiedIdentifier(), std::to_string(value), isRegular); } ImGui::PopID(); } -void renderVec2Property(Property* prop, const std::string& ownerName) { +void renderVec2Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); Vec2Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -329,14 +386,18 @@ void renderVec2Property(Property* prop, const std::string& ownerName) { if (value != p->value()) { executeScript( p->fullyQualifiedIdentifier(), - "{" + std::to_string(value.x) + "," + std::to_string(value.y) + "}" + "{" + std::to_string(value.x) + "," + std::to_string(value.y) + "}", + isRegular ); } ImGui::PopID(); } -void renderVec3Property(Property* prop, const std::string& ownerName) { +void renderVec3Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); Vec3Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -359,15 +420,19 @@ void renderVec3Property(Property* prop, const std::string& ownerName) { executeScript( p->fullyQualifiedIdentifier(), "{" + std::to_string(value.x) + "," + - std::to_string(value.y) + "," + - std::to_string(value.z) + "}" + std::to_string(value.y) + "," + + std::to_string(value.z) + "}", + isRegular ); } ImGui::PopID(); } -void renderVec4Property(Property* prop, const std::string& ownerName) { +void renderVec4Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); Vec4Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -391,16 +456,20 @@ void renderVec4Property(Property* prop, const std::string& ownerName) { executeScript( p->fullyQualifiedIdentifier(), "{" + std::to_string(value.x) + "," + - std::to_string(value.y) + "," + - std::to_string(value.z) + "," + - std::to_string(value.w) + "}" + std::to_string(value.y) + "," + + std::to_string(value.z) + "," + + std::to_string(value.w) + "}", + isRegular ); } ImGui::PopID(); } -void renderDVec2Property(Property* prop, const std::string& ownerName) { +void renderDVec2Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); DVec2Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -420,14 +489,18 @@ void renderDVec2Property(Property* prop, const std::string& ownerName) { if (glm::dvec2(value) != p->value()) { executeScript( p->fullyQualifiedIdentifier(), - "{" + std::to_string(value.x) + "," + std::to_string(value.y) + "}" + "{" + std::to_string(value.x) + "," + std::to_string(value.y) + "}", + isRegular ); } ImGui::PopID(); } -void renderDVec3Property(Property* prop, const std::string& ownerName) { +void renderDVec3Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); DVec3Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -453,15 +526,19 @@ void renderDVec3Property(Property* prop, const std::string& ownerName) { executeScript( p->fullyQualifiedIdentifier(), "{" + std::to_string(value.x) + "," + - std::to_string(value.y) + "," + - std::to_string(value.z) + "}" + std::to_string(value.y) + "," + + std::to_string(value.z) + "}", + isRegular ); } ImGui::PopID(); } -void renderDVec4Property(Property* prop, const std::string& ownerName) { +void renderDVec4Property(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); DVec4Property* p = static_cast(prop); std::string name = p->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); @@ -491,22 +568,26 @@ void renderDVec4Property(Property* prop, const std::string& ownerName) { executeScript( p->fullyQualifiedIdentifier(), "{" + std::to_string(value.x) + "," + - std::to_string(value.y) + "," + - std::to_string(value.z) + "," + - std::to_string(value.w) + "}" + std::to_string(value.y) + "," + + std::to_string(value.z) + "," + + std::to_string(value.w) + "}", + isRegular ); } ImGui::PopID(); } -void renderTriggerProperty(Property* prop, const std::string& ownerName) { +void renderTriggerProperty(Property* prop, const std::string& ownerName, + IsRegularProperty isRegular) +{ + ghoul_assert(prop, "prop must not be nullptr"); std::string name = prop->guiName(); ImGui::PushID((ownerName + "." + name).c_str()); bool pressed = ImGui::Button(name.c_str()); if (pressed) { - executeScript(prop->fullyQualifiedIdentifier(), "nil"); + executeScript(prop->fullyQualifiedIdentifier(), "nil", isRegular); } renderTooltip(prop); diff --git a/modules/space/rendering/renderableplanet.cpp b/modules/space/rendering/renderableplanet.cpp index 17bdd3c71d..cd77cff9a9 100644 --- a/modules/space/rendering/renderableplanet.cpp +++ b/modules/space/rendering/renderableplanet.cpp @@ -292,16 +292,7 @@ bool RenderablePlanet::initialize() { LERROR(ss.str()); } - loadTexture(); - - while ((err = glGetError()) != GL_NO_ERROR) { - const GLubyte * errString = gluErrorString(err); - std::stringstream ss; - ss << "Error loading textures. OpenGL error: " << errString << std::endl; - LERROR(ss.str()); - } - - _geometry->initialize(this); + _geometry->initialize(this); _programObject->deactivate(); @@ -309,6 +300,8 @@ bool RenderablePlanet::initialize() { const GLubyte * errString = gluErrorString(err); LERROR("Shader Programs Creation. OpenGL error: " << errString); } + + loadTexture(); return isReady(); } @@ -394,13 +387,13 @@ void RenderablePlanet::render(const RenderData& data) { _programObject->setUniform("texture1", dayUnit); // Bind possible night texture - if (_hasNightTexture) { + if (_hasNightTexture && _nightTexture) { nightUnit.activate(); _nightTexture->bind(); _programObject->setUniform("nightTex", nightUnit); } - if (_hasHeightTexture) { + if (_hasHeightTexture && _heightMapTexture) { heightUnit.activate(); _heightMapTexture->bind(); _programObject->setUniform("heightTex", heightUnit); diff --git a/modules/space/rendering/simplespheregeometry.h b/modules/space/rendering/simplespheregeometry.h index 35740746df..3604050944 100644 --- a/modules/space/rendering/simplespheregeometry.h +++ b/modules/space/rendering/simplespheregeometry.h @@ -46,7 +46,6 @@ public: bool initialize(Renderable* parent) override; void deinitialize() override; void render() override; - PowerScaledSphere* _planet; private: void createSphere(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a71d95f78..330ff94505 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,6 +37,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/engine/openspaceengine.cpp ${OPENSPACE_BASE_DIR}/src/engine/settingsengine.cpp ${OPENSPACE_BASE_DIR}/src/engine/syncengine.cpp + ${OPENSPACE_BASE_DIR}/src/engine/virtualpropertymanager.cpp ${OPENSPACE_BASE_DIR}/src/engine/wrapper/sgctwindowwrapper.cpp ${OPENSPACE_BASE_DIR}/src/engine/wrapper/windowwrapper.cpp ${OPENSPACE_BASE_DIR}/src/interaction/controller.cpp @@ -174,6 +175,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/engine/openspaceengine.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/settingsengine.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/syncengine.h + ${OPENSPACE_BASE_DIR}/include/openspace/engine/virtualpropertymanager.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/wrapper/sgctwindowwrapper.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/wrapper/windowwrapper.h ${OPENSPACE_BASE_DIR}/include/openspace/interaction/controller.h diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 5af479dc7b..03158a20e6 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +136,7 @@ OpenSpaceEngine::OpenSpaceEngine( , _parallelConnection(new ParallelConnection) , _windowWrapper(std::move(windowWrapper)) , _globalPropertyNamespace(new properties::PropertyOwner("")) + , _virtualPropertyManager(new VirtualPropertyManager) , _scheduledSceneSwitch(false) , _scenePath("") , _runTime(0.0) @@ -148,7 +150,7 @@ OpenSpaceEngine::OpenSpaceEngine( _globalPropertyNamespace->addPropertySubOwner(_settingsEngine.get()); _globalPropertyNamespace->addPropertySubOwner(_renderEngine.get()); _globalPropertyNamespace->addPropertySubOwner(_windowWrapper.get()); - + FactoryManager::initialize(); FactoryManager::ref().addFactory( std::make_unique>(), @@ -1170,6 +1172,24 @@ scripting::LuaLibrary OpenSpaceEngine::luaLibrary() { &luascriptfunctions::writeDocumentation, "", "Writes out documentation files" + }, + { + "addVirtualProperty", + &luascriptfunctions::addVirtualProperty, + "type, name, identifier, [value, minimumValue, maximumValue]", + "Adds a virtual property that will set a group of properties" + }, + { + "removeVirtualProperty", + &luascriptfunctions::removeVirtualProperty, + "string", + "Removes a previously added virtual property" + }, + { + "removeAllVirtualProperties", + &luascriptfunctions::removeAllVirtualProperties, + "", + "Remove all registered virtual properties" } } }; @@ -1315,6 +1335,15 @@ properties::PropertyOwner& OpenSpaceEngine::globalPropertyOwner() { return *_globalPropertyNamespace; } +VirtualPropertyManager& OpenSpaceEngine::virtualPropertyManager() { + ghoul_assert( + _virtualPropertyManager, + "Virtual Property Manager must not be nullptr" + ); + + return *_virtualPropertyManager; +} + ScriptEngine& OpenSpaceEngine::scriptEngine() { ghoul_assert(_scriptEngine, "ScriptEngine must not be nullptr"); return *_scriptEngine; diff --git a/src/engine/openspaceengine_lua.inl b/src/engine/openspaceengine_lua.inl index b83b472aa0..5b82fa7bbb 100644 --- a/src/engine/openspaceengine_lua.inl +++ b/src/engine/openspaceengine_lua.inl @@ -32,13 +32,14 @@ namespace luascriptfunctions { * reached */ int toggleShutdown(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 0) + const int nArguments = lua_gettop(L); + if (nArguments != 0) { return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); + } OsEng.toggleShutdownMode(); - return 1; + return 0; } /** @@ -47,13 +48,92 @@ int toggleShutdown(lua_State* L) { * Writes out documentation files */ int writeDocumentation(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 0) + const int nArguments = lua_gettop(L); + if (nArguments != 0) { return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); + } OsEng.writeDocumentation(); - return 1; + return 0; +} + +/** + * \ingroup LuaScripts + * addVirtualProperty(): + * Adds a virtual property that will set a group of properties + */ +int addVirtualProperty(lua_State* L) { + using namespace properties; + + const int nArguments = lua_gettop(L); + if (nArguments != 6) { + return luaL_error(L, "Expected %i arguments, got %i", 6, nArguments); + } + + const std::string type = lua_tostring(L, -6); + const std::string name = lua_tostring(L, -5); + const std::string identifier = lua_tostring(L, -4); + + std::unique_ptr prop; + if (type == "BoolProperty") { + bool v = lua_toboolean(L, -3); + prop = std::make_unique(identifier, name, v); + } + else if (type == "IntProperty") { + int v = static_cast(lua_tonumber(L, -3)); + int min = static_cast(lua_tonumber(L, -2)); + int max = static_cast(lua_tonumber(L, -1)); + + prop = std::make_unique(identifier, name, v, min, max); + } + else if (type == "FloatProperty") { + float v = static_cast(lua_tonumber(L, -3)); + float min = static_cast(lua_tonumber(L, -2)); + float max = static_cast(lua_tonumber(L, -1)); + + prop = std::make_unique(identifier, name, v, min, max); + } + else if (type == "TriggerProperty") { + prop = std::make_unique(identifier, name); + } + else { + return luaL_error(L, "Unknown property type '%s'", type.c_str()); + } + + OsEng.virtualPropertyManager().addProperty(std::move(prop)); + return 0; +} + +/** +* \ingroup LuaScripts +* removeVirtualProperty(): +* Removes a previously added virtual property +*/ +int removeVirtualProperty(lua_State* L) { + const int nArguments = lua_gettop(L); + if (nArguments != 1) { + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + } + + const std::string name = lua_tostring(L, -1); + properties::Property* p = OsEng.virtualPropertyManager().property(name); + OsEng.virtualPropertyManager().removeProperty(p); + return 0; +} + +/** +* \ingroup LuaScripts +* removeAllVirtualProperties(): +* Remove all registered virtual properties +*/ +int removeAllVirtualProperties(lua_State* L) { + std::vector ps = OsEng.virtualPropertyManager().properties(); + for (properties::Property* p : ps) { + OsEng.virtualPropertyManager().removeProperty(p); + delete p; + } + return 0; } diff --git a/src/engine/virtualpropertymanager.cpp b/src/engine/virtualpropertymanager.cpp new file mode 100644 index 0000000000..2543ee284a --- /dev/null +++ b/src/engine/virtualpropertymanager.cpp @@ -0,0 +1,58 @@ +/***************************************************************************************** + * * + * 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 + +namespace openspace { + +VirtualPropertyManager::VirtualPropertyManager() + : properties::PropertyOwner("") +{ + +} + +void VirtualPropertyManager::addProperty(std::unique_ptr prop) { + // PropertyOwner does not take the ownership of the pointer + properties::PropertyOwner::addProperty(prop.get()); + + // So we store the pointer locally instead + _properties.push_back(std::move(prop)); +} + +void VirtualPropertyManager::removeProperty(properties::Property* prop) { + properties::PropertyOwner::removeProperty(prop); + _properties.erase( + std::remove_if( + _properties.begin(), + _properties.end(), + [prop](const std::unique_ptr& p) { + return p.get() == prop; + } + ), + _properties.end() + ); +} + + +} // namespace openspace diff --git a/src/query/query.cpp b/src/query/query.cpp index 1eb2db2988..194a4cf563 100644 --- a/src/query/query.cpp +++ b/src/query/query.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -108,6 +109,15 @@ std::vector allProperties() { p.end() ); + std::vector q = + OsEng.virtualPropertyManager().propertiesRecursive(); + + properties.insert( + properties.end(), + q.begin(), + q.end() + ); + const Scene* graph = sceneGraph(); std::vector nodes = graph->allSceneGraphNodes();