From cd012548afed8cd5647df7e13e6716a3ecd0d192 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 18 Dec 2014 19:15:57 +0100 Subject: [PATCH] Intermediate work on making imgui into components --- include/openspace/engine/openspaceengine.h | 5 +- include/openspace/gui/gui.h | 53 +- include/openspace/gui/guicomponent.h | 73 ++ .../openspace/gui/guiperformancecomponent.h | 51 + include/openspace/gui/guipropertycomponent.h | 64 ++ src/engine/openspaceengine.cpp | 4 +- src/gui/gui.cpp | 926 ++++++++++-------- src/gui/guicomponent.cpp | 47 + src/gui/guiperformancecomponent.cpp | 107 ++ src/gui/guipropertycomponent.cpp | 237 +++++ src/scenegraph/scenegraph.cpp | 2 +- 11 files changed, 1129 insertions(+), 440 deletions(-) create mode 100644 include/openspace/gui/guicomponent.h create mode 100644 include/openspace/gui/guiperformancecomponent.h create mode 100644 include/openspace/gui/guipropertycomponent.h create mode 100644 src/gui/guicomponent.cpp create mode 100644 src/gui/guiperformancecomponent.cpp create mode 100644 src/gui/guipropertycomponent.cpp diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 0f7d9e5c29..296c2af672 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -34,7 +34,6 @@ namespace openspace { -class GUI; class SyncBuffer; class LuaConsole; @@ -59,7 +58,7 @@ public: scripting::ScriptEngine& scriptEngine(); LuaConsole& console(); - GUI& gui(); + gui::GUI& gui(); // SGCT callbacks bool initializeGL(); @@ -97,7 +96,7 @@ private: scripting::ScriptEngine _scriptEngine; ghoul::cmdparser::CommandlineParser _commandlineParser; LuaConsole _console; - GUI _gui; + gui::GUI _gui; SyncBuffer* _syncBuffer; diff --git a/include/openspace/gui/gui.h b/include/openspace/gui/gui.h index 36363c42a3..dd39dacfe3 100644 --- a/include/openspace/gui/gui.h +++ b/include/openspace/gui/gui.h @@ -25,40 +25,27 @@ #ifndef __GUI_H__ #define __GUI_H__ +#include +#include +#include #include -#include - -#include -#include -#include -#include - -namespace ghoul { - class SharedMemory; -} - namespace openspace { - -namespace properties { - class Property; -} +namespace gui { class GUI { public: GUI(); - ~GUI(); bool isEnabled() const; void setEnabled(bool enabled); void initialize(); + void deinitialize(); void initializeGL(); void deinitializeGL(); - void registerProperty(properties::Property* prop); - bool mouseButtonCallback(int key, int action); bool mouseWheelCallback(int position); bool keyCallback(int key, int action); @@ -67,38 +54,20 @@ public: void startFrame(float deltaTime, const glm::vec2& windowSize, const glm::vec2& mousePos, bool mouseButtonsPressed[2]); void endFrame(); - - static scripting::ScriptEngine::LuaLibrary luaLibrary(); - -private: void renderMainWindow(); - void renderPropertyWindow(); - void renderPerformanceWindow(); + static openspace::scripting::ScriptEngine::LuaLibrary luaLibrary(); + +//protected: + GuiPerformanceComponent _performance; + GuiPropertyComponent _property; bool _isEnabled; - bool _showPropertyWindow; - bool _showPerformanceWindow; bool _showHelp; - - - ghoul::SharedMemory* _performanceMemory; - float _minMaxValues[2]; - - std::set _boolProperties; - std::set _intProperties; - std::set _floatProperties; - std::set _vec2Properties; - std::set _vec3Properties; - std::set _stringProperties; - std::set _optionProperty; - std::set _selectionProperty; - std::set _triggerProperty; - - std::map> _propertiesByOwner; }; +} // namespace gui } // namespace openspace #endif // __GUI_H__ diff --git a/include/openspace/gui/guicomponent.h b/include/openspace/gui/guicomponent.h new file mode 100644 index 0000000000..dcb4294319 --- /dev/null +++ b/include/openspace/gui/guicomponent.h @@ -0,0 +1,73 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __GUICOMPONENT_H__ +#define __GUICOMPONENT_H__ + +namespace openspace { +namespace gui { + +/** + * The base class for a GUI component that can be rendered to the screen. + */ +class GuiComponent { +public: + /** + * Returns if this component is enabled, that is, if it is currently active and + * visible on the screen. + * \return true if this component is enabled, false + * otherwise + */ + bool isEnabled() const; + + /** + * Sets if this component is enabled, that is, if it is currently active and visible + * on the screen. + * \param enabled The new enabled status of this component + */ + void setEnabled(bool enabled); + + /// Initializes the component with everything that does not require an OpenGL context + virtual void initialize(); + /// Initializes the component with everything that requires an OpenGL context + virtual void initializeGL(); + + /// Deinitializes the component with things that do not require an OpenGL context + virtual void deinitialize(); + + /// Deinitializes the component with things that require an OpenGL context + virtual void deinitializeGL(); + + /// Renders the individual subcomponents to the screen + virtual void render() = 0; + +protected: + /// true if this component is enabled and visible on the screen + bool _isEnabled; +}; + +} // namespace gui +} // namespace openspace + +#endif // __GUICOMPONENT_H__ diff --git a/include/openspace/gui/guiperformancecomponent.h b/include/openspace/gui/guiperformancecomponent.h new file mode 100644 index 0000000000..cf7c8aa5de --- /dev/null +++ b/include/openspace/gui/guiperformancecomponent.h @@ -0,0 +1,51 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __GUIPERFORMANCECOMPONENT_H__ +#define __GUIPERFORMANCECOMPONENT_H__ + +#include + +namespace ghoul { + class SharedMemory; +} + +namespace openspace { +namespace gui { + +class GuiPerformanceComponent : public GuiComponent { +public: + void initialize(); + + void render(); + +protected: + ghoul::SharedMemory* _performanceMemory; + float _minMaxValues[2]; +}; + +} // namespace gui +} // namespace openspace + +#endif // __GUIPERFORMANCECOMPONENT_H__ diff --git a/include/openspace/gui/guipropertycomponent.h b/include/openspace/gui/guipropertycomponent.h new file mode 100644 index 0000000000..c61e54fcd8 --- /dev/null +++ b/include/openspace/gui/guipropertycomponent.h @@ -0,0 +1,64 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __GUIPROPERTYCOMPONENT_H__ +#define __GUIPROPERTYCOMPONENT_H__ + +#include + +#include +#include +#include + +namespace openspace { + +namespace properties { + class Property; +} + +namespace gui { + +class GuiPropertyComponent : public GuiComponent { +public: + void registerProperty(properties::Property* prop); + void render(); + +protected: + std::set _boolProperties; + std::set _intProperties; + std::set _floatProperties; + std::set _vec2Properties; + std::set _vec3Properties; + std::set _stringProperties; + std::set _optionProperty; + std::set _selectionProperty; + std::set _triggerProperty; + + std::map> _propertiesByOwner; +}; + +} // namespace gui +} // namespace openspace + +#endif // __GUIPROPERTYCOMPONENT_H__ diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 8409dc85fe..efb0b86746 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -242,7 +242,7 @@ bool OpenSpaceEngine::initialize() { _scriptEngine.addLibrary(Time::luaLibrary()); _scriptEngine.addLibrary(interaction::InteractionHandler::luaLibrary()); _scriptEngine.addLibrary(LuaConsole::luaLibrary()); - _scriptEngine.addLibrary(GUI::luaLibrary()); + _scriptEngine.addLibrary(gui::GUI::luaLibrary()); // TODO: Maybe move all scenegraph and renderengine stuff to initializeGL scriptEngine().initialize(); @@ -479,7 +479,7 @@ LuaConsole& OpenSpaceEngine::console() { return _console; } -GUI& OpenSpaceEngine::gui() { +gui::GUI& OpenSpaceEngine::gui() { return _gui; } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 70ac8d5d55..33affc47a4 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1,3 +1,4 @@ +GUI /***************************************************************************************** * * * OpenSpace * @@ -25,230 +26,110 @@ #include #include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - #include #include +#include +#include +#include #include -#include #define STB_IMAGE_IMPLEMENTATION #include namespace { const std::string _loggerCat = "GUI"; const std::string configurationFile = "imgui.ini"; - - GLuint fontTex = 0; + const ImVec2 size = ImVec2(350, 500); + + GLuint fontTex = 0; GLint positionLocation = 0; GLint uvLocation = 0; GLint colorLocation = 0; size_t vboMaxSize = 20000; GLuint vao = 0; GLuint vbo = 0; - ghoul::opengl::ProgramObject* _program; - const ImVec2 size = ImVec2(350, 500); -static void ImImpl_RenderDrawLists(ImDrawList** const commandLists, int nCommandLists) { - if (nCommandLists == 0) - return; + static void ImImpl_RenderDrawLists(ImDrawList** const commandLists, int nCommandLists) { + if (nCommandLists == 0) + return; - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); - ghoul::opengl::TextureUnit unit; - unit.activate(); - glBindTexture(GL_TEXTURE_2D, fontTex); + ghoul::opengl::TextureUnit unit; + unit.activate(); + glBindTexture(GL_TEXTURE_2D, fontTex); - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - static const glm::mat4 ortho( - 2.f/width, 0.0f, 0.0f, 0.0f, - 0.0f, 2.0f/-height, 0.0f, 0.0f, - 0.0f, 0.0f, -1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 1.0f - ); - _program->activate(); - _program->setUniform("tex", unit.glEnum()); - _program->setUniform("ortho", ortho); + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + static const glm::mat4 ortho( + 2.f / width, 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f / -height, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f + ); + _program->activate(); + _program->setUniform("tex", unit.glEnum()); + _program->setUniform("ortho", ortho); - // Grow our buffer according to what we need - size_t total_vtx_count = 0; - for (int n = 0; n < nCommandLists; n++) - total_vtx_count += commandLists[n]->vtx_buffer.size(); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - // @BUGFIX @HACK The imgui crashes on complex scenes without the * 2 ---abock - size_t neededBufferSize = total_vtx_count * sizeof(ImDrawVert) * 2; - if (neededBufferSize > vboMaxSize) { - vboMaxSize = neededBufferSize + 5000; // Grow buffer - glBufferData(GL_ARRAY_BUFFER, neededBufferSize, NULL, GL_STREAM_DRAW); - } - - // Copy and convert all vertices into a single contiguous buffer - unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - if (!buffer_data) - return; - for (int n = 0; n < nCommandLists; ++n) { - const ImDrawList* cmd_list = commandLists[n]; - memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert)); - buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert); - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(vao); - - int cmd_offset = 0; - for (int n = 0; n < nCommandLists; ++n) { - const ImDrawList* cmd_list = commandLists[n]; - int vtx_offset = cmd_offset; - const ImDrawCmd* pcmd_end = cmd_list->commands.end(); - for (auto pcmd : cmd_list->commands) { - glScissor((int)pcmd.clip_rect.x, (int)(height - pcmd.clip_rect.w), (int)(pcmd.clip_rect.z - pcmd.clip_rect.x), (int)(pcmd.clip_rect.w - pcmd.clip_rect.y)); - glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd.vtx_count); - vtx_offset += pcmd.vtx_count; - } - cmd_offset = vtx_offset; - } - - glBindVertexArray(0); - _program->deactivate(); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, 0); -} - -using namespace openspace::properties; - -void renderBoolProperty(Property* prop, const std::string& ownerName) { - BoolProperty* p = static_cast(prop); - std::string name = p->guiName(); - - BoolProperty::ValueType value = *p; - ImGui::Checkbox((ownerName + "." + name).c_str(), &value); - p->set(value); -} - -void renderOptionProperty(Property* prop, const std::string& ownerName) { - OptionProperty* p = static_cast(prop); - std::string name = p->guiName(); - - int value = *p; - std::vector options = p->options(); - for (const OptionProperty::Option& o : options) { - ImGui::RadioButton((ownerName + "." + name).c_str(), &value, o.value); - ImGui::SameLine(); - ImGui::Text(o.description.c_str()); - } - p->set(value); -} - -void renderSelectionProperty(Property* prop, const std::string& ownerName) { - SelectionProperty* p = static_cast(prop); - std::string name = p->guiName(); - - if (ImGui::CollapsingHeader((ownerName + "." + name).c_str())) { - const std::vector& options = p->options(); - std::vector newSelectedIndices; - - std::vector selectedIndices = p->value(); - - for (int i = 0; i < options.size(); ++i) { - std::string description = options[i].description; - bool selected = std::find(selectedIndices.begin(), selectedIndices.end(), i) != selectedIndices.end(); - ImGui::Checkbox(description.c_str(), &selected); - - if (selected) - newSelectedIndices.push_back(i); + // Grow our buffer according to what we need + size_t total_vtx_count = 0; + for (int n = 0; n < nCommandLists; n++) + total_vtx_count += commandLists[n]->vtx_buffer.size(); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + // @BUGFIX @HACK The imgui crashes on complex scenes without the * 2 ---abock + size_t neededBufferSize = total_vtx_count * sizeof(ImDrawVert) * 2; + if (neededBufferSize > vboMaxSize) { + vboMaxSize = neededBufferSize + 5000; // Grow buffer + glBufferData(GL_ARRAY_BUFFER, neededBufferSize, NULL, GL_STREAM_DRAW); } - p->setValue(std::move(newSelectedIndices)); + // Copy and convert all vertices into a single contiguous buffer + unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + if (!buffer_data) + return; + for (int n = 0; n < nCommandLists; ++n) { + const ImDrawList* cmd_list = commandLists[n]; + memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert)); + buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert); + } + glUnmapBuffer(GL_ARRAY_BUFFER); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(vao); + + int cmd_offset = 0; + for (int n = 0; n < nCommandLists; ++n) { + const ImDrawList* cmd_list = commandLists[n]; + int vtx_offset = cmd_offset; + const ImDrawCmd* pcmd_end = cmd_list->commands.end(); + for (auto pcmd : cmd_list->commands) { + glScissor((int)pcmd.clip_rect.x, (int)(height - pcmd.clip_rect.w), (int)(pcmd.clip_rect.z - pcmd.clip_rect.x), (int)(pcmd.clip_rect.w - pcmd.clip_rect.y)); + glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd.vtx_count); + vtx_offset += pcmd.vtx_count; + } + cmd_offset = vtx_offset; + } + + glBindVertexArray(0); + _program->deactivate(); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, 0); } } -void renderIntProperty(Property* prop, const std::string& ownerName) { - IntProperty* p = static_cast(prop); - std::string name = p->guiName(); - - IntProperty::ValueType value = *p; - ImGui::SliderInt((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue()); - p->set(value); -} - -void renderFloatProperty(Property* prop, const std::string& ownerName) { - FloatProperty* p = static_cast(prop); - std::string name = p->guiName(); - - FloatProperty::ValueType value = *p; - ImGui::SliderFloat((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue()); - p->set(value); -} - -void renderVec2Property(Property* prop, const std::string& ownerName) { - Vec2Property* p = static_cast(prop); - std::string name = p->guiName(); - - Vec2Property::ValueType value = *p; - - ImGui::SliderFloat2((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x); - p->set(value); -} - - -void renderVec3Property(Property* prop, const std::string& ownerName) { - Vec3Property* p = static_cast(prop); - std::string name = p->guiName(); - - Vec3Property::ValueType value = *p; - - ImGui::SliderFloat3((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x); - p->set(value); -} - -void renderTriggerProperty(Property* prop, const std::string& ownerName) { - std::string name = prop->guiName(); - bool pressed = ImGui::Button((ownerName + "." + name).c_str()); - if (pressed) - prop->set(0); -} - -} - namespace openspace { +namespace gui { -GUI::GUI() +GUI::GUI() : _isEnabled(false) - , _showPropertyWindow(false) - , _showHelp(false) - , _performanceMemory(nullptr) -{ - _minMaxValues[0] = 100.f; - _minMaxValues[1] = 1000.f; -} - -GUI::~GUI() { - delete _performanceMemory; - ImGui::Shutdown(); -} +{} bool GUI::isEnabled() const { return _isEnabled; @@ -296,53 +177,62 @@ void GUI::initialize() { io.RenderDrawListsFn = ImImpl_RenderDrawLists; //io.SetClipboardTextFn = ImImpl_SetClipboardTextFn; // @TODO implement? ---abock //io.GetClipboardTextFn = ImImpl_GetClipboardTextFn; // @TODO implement? ---abock + + _property.initialize(); + _performance.initialize(); } void GUI::initializeGL() { _program = ghoul::opengl::ProgramObject::Build("GUI", "${SHADERS}/gui_vs.glsl", "${SHADERS}/gui_fs.glsl"); - - positionLocation = glGetAttribLocation(*_program, "in_position"); - uvLocation = glGetAttribLocation(*_program, "in_uv"); - colorLocation = glGetAttribLocation(*_program, "in_color"); - glGenTextures(1, &fontTex); - glBindTexture(GL_TEXTURE_2D, fontTex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - const void* png_data; - unsigned int png_size; - ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); - int tex_x, tex_y, tex_comp; - void* tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data); - stbi_image_free(tex_data); + positionLocation = glGetAttribLocation(*_program, "in_position"); + uvLocation = glGetAttribLocation(*_program, "in_uv"); + colorLocation = glGetAttribLocation(*_program, "in_color"); - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, vboMaxSize, NULL, GL_DYNAMIC_DRAW); + glGenTextures(1, &fontTex); + glBindTexture(GL_TEXTURE_2D, fontTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + const void* png_data; + unsigned int png_size; + ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); + int tex_x, tex_y, tex_comp; + void* tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data); + stbi_image_free(tex_data); - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glEnableVertexAttribArray(positionLocation); - glEnableVertexAttribArray(uvLocation); - glEnableVertexAttribArray(colorLocation); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, vboMaxSize, NULL, GL_DYNAMIC_DRAW); - glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, pos)); - glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, uv)); - glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, col)); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glEnableVertexAttribArray(positionLocation); + glEnableVertexAttribArray(uvLocation); + glEnableVertexAttribArray(colorLocation); + + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, pos)); + glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, uv)); + glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col)); + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + _property.initializeGL(); + _performance.initializeGL(); } void GUI::deinitializeGL() { - if(_program) + if (_program) delete _program; _program = nullptr; if (vao) glDeleteVertexArrays(1, &vao); - if (vbo) glDeleteBuffers(1, &vbo); + if (vbo) glDeleteBuffers(1, &vbo); + + _property.deinitializeGL(); + _performance.deinitializeGL(); } void GUI::startFrame(float deltaTime, @@ -364,10 +254,11 @@ void GUI::endFrame() { static bool show = true; //ImGui::ShowTestWindow(&show); renderMainWindow(); - if (_showPropertyWindow) - renderPropertyWindow(); - if (_showPerformanceWindow) - renderPerformanceWindow(); + + if (_property.isEnabled()) + _property.render(); + if (_performance.isEnabled()) + _performance.render(); ImGui::Render(); } @@ -409,51 +300,17 @@ bool GUI::charCallback(unsigned int character) { return consumeEvent; } -void GUI::registerProperty(properties::Property* prop) { - using namespace properties; - - std::string className = prop->className(); - - if (className == "BoolProperty") - _boolProperties.insert(prop); - else if (className == "IntProperty") - _intProperties.insert(prop); - else if (className == "FloatProperty") - _floatProperties.insert(prop); - else if (className == "StringProperty") - _stringProperties.insert(prop); - else if (className == "Vec2Property") - _vec2Properties.insert(prop); - else if (className == "Vec3Property") - _vec3Properties.insert(prop); - else if (className == "OptionProperty") - _optionProperty.insert(prop); - else if (className == "TriggerProperty") - _triggerProperty.insert(prop); - else if (className == "SelectionProperty") - _selectionProperty.insert(prop); - else { - LWARNING("Class name '" << className << "' not handled in GUI generation"); - return; - } - - std::string fullyQualifiedId = prop->fullyQualifiedIdentifier(); - size_t pos = fullyQualifiedId.find('.'); - std::string owner = fullyQualifiedId.substr(0, pos); - - auto it =_propertiesByOwner.find(owner); - if (it == _propertiesByOwner.end()) - _propertiesByOwner[owner] = { prop }; - else - it->second.push_back(prop); - -} - void GUI::renderMainWindow() { ImGui::Begin("OpenSpace GUI", nullptr); - ImGui::Checkbox("Properties", &_showPropertyWindow); - ImGui::Checkbox("Performance", &_showPerformanceWindow); + bool showPropertyWindow = _property.isEnabled(); + ImGui::Checkbox("Properties", &showPropertyWindow); + _property.setEnabled(showPropertyWindow); + + bool showPerformanceWindow = _performance.isEnabled(); + ImGui::Checkbox("Performance", &showPerformanceWindow); + _performance.setEnabled(showPerformanceWindow); + ImGui::Checkbox("Help", &_showHelp); if (_showHelp) { @@ -465,127 +322,7 @@ void GUI::renderMainWindow() { ImGui::End(); } -void GUI::renderPropertyWindow() { - using namespace properties; - - ImGui::Begin("Properties", &_showPropertyWindow, size, 0.5f); - - //ImGui::ShowUserGuide(); - ImGui::Spacing(); - - for (const auto& p : _propertiesByOwner) { - if (ImGui::CollapsingHeader(p.first.c_str())) { - for (properties::Property* prop : p.second) { - if (_boolProperties.find(prop) != _boolProperties.end()) { - renderBoolProperty(prop, p.first); - continue; - } - - if (_intProperties.find(prop) != _intProperties.end()) { - renderIntProperty(prop, p.first); - continue; - } - - if (_floatProperties.find(prop) != _floatProperties.end()) { - renderFloatProperty(prop, p.first); - continue; - } - - if (_vec2Properties.find(prop) != _vec2Properties.end()) { - renderVec2Property(prop, p.first); - continue; - } - - if (_vec3Properties.find(prop) != _vec3Properties.end()) { - renderVec3Property(prop, p.first); - continue; - } - - if (_optionProperty.find(prop) != _optionProperty.end()) { - renderOptionProperty(prop, p.first); - continue; - } - - if (_triggerProperty.find(prop) != _triggerProperty.end()) { - renderTriggerProperty(prop, p.first); - continue; - } - - if (_selectionProperty.find(prop) != _selectionProperty.end()) { - renderSelectionProperty(prop, p.first); - continue; - } - } - } - } - - ImGui::End(); -} - -void GUI::renderPerformanceWindow() { - // Copy and paste from renderengine.cpp::storePerformanceMeasurements method - const int8_t Version = 0; - const int nValues = 250; - const int lengthName = 256; - const int maxValues = 50; - - struct PerformanceLayout { - int8_t version; - int32_t nValuesPerEntry; - int32_t nEntries; - int32_t maxNameLength; - int32_t maxEntries; - - struct PerformanceLayoutEntry { - char name[lengthName]; - float renderTime[nValues]; - float updateRenderable[nValues]; - float updateEphemeris[nValues]; - - int32_t currentRenderTime; - int32_t currentUpdateRenderable; - int32_t currentUpdateEphemeris; - }; - - PerformanceLayoutEntry entries[maxValues]; - }; - - ImGui::Begin("Performance", &_showPerformanceWindow); - if (OsEng.renderEngine().doesPerformanceMeasurements() && - ghoul::SharedMemory::exists(RenderEngine::PerformanceMeasurementSharedData)) - { - ImGui::SliderFloat2("Min values, max Value", _minMaxValues, 0.f, 10000.f); - _minMaxValues[1] = std::max(_minMaxValues[0], _minMaxValues[1]); - - if (!_performanceMemory) - _performanceMemory = new ghoul::SharedMemory(RenderEngine::PerformanceMeasurementSharedData); - - PerformanceLayout* layout = reinterpret_cast(_performanceMemory->pointer()); - - for (int i = 0; i < layout->nEntries; ++i) { - const PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; - - if (ImGui::CollapsingHeader(entry.name)) { - std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[entry.currentUpdateEphemeris - 1]) + "us"; - ImGui::PlotLines("UpdateEphemeris", &entry.updateEphemeris[0], layout->nValuesPerEntry, 0, updateEphemerisTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); - - std::string updateRenderableTime = std::to_string(entry.updateRenderable[entry.currentUpdateRenderable - 1]) + "us"; - ImGui::PlotLines("UpdateRender", &entry.updateRenderable[0], layout->nValuesPerEntry, 0, updateRenderableTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); - - std::string renderTime = std::to_string(entry.renderTime[entry.currentRenderTime - 1]) + "us"; - ImGui::PlotLines("RenderTime", &entry.renderTime[0], layout->nValuesPerEntry, 0, renderTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); - } - } - } - else { - ImGui::TextWrapped("Performance monitoring is disabled. Enable with " - "'openspace.setPerformanceMeasurement(true)'"); - } - - ImGui::End(); -} - -namespace { +namespace { /** * \ingroup LuaScripts @@ -657,4 +394,409 @@ scripting::ScriptEngine::LuaLibrary GUI::luaLibrary() { }; } + +} // namespace gui } // namespace openspace + +// +// +// +// +// +// +// +// +// +// +// +// +// +// +//#include +// +//#include +//#include +// +//#include +//#include +//#include +//#include +//#include +//#include +// +//#include +//#include +//#include +//#include +//#include +//#include +// +//#include +//#include +// +//#include +//#include +//#define STB_IMAGE_IMPLEMENTATION +//#include +// +//namespace { +// const std::string _loggerCat = "GUI"; +// const std::string configurationFile = "imgui.ini"; +// +// +//namespace openspace { +// namespace gui { +// +//GUI::GUI() +// : _isEnabled(false) +// , _showPropertyWindow(false) +// , _showHelp(false) +// , _performanceMemory(nullptr) +//{ +// _minMaxValues[0] = 100.f; +// _minMaxValues[1] = 1000.f; +//} +// +//GUI::~GUI() { +// delete _performanceMemory; +// ImGui::Shutdown(); +//} +// +//bool GUI::isEnabled() const { +// return _isEnabled; +//} +// +//void GUI::setEnabled(bool enabled) { +// _isEnabled = enabled; +//} +// +//void GUI::initialize() { +// std::string cachedFile; +// FileSys.cacheManager()->getCachedFile(configurationFile, "", cachedFile, true); +// +// char* buffer = new char[cachedFile.size() + 1]; +// +//#ifdef WIN32 +// strcpy_s(buffer, cachedFile.size() + 1, cachedFile.c_str()); +//#else +// strcpy(buffer, cachedFile.c_str()); +//#endif +// +// ImGuiIO& io = ImGui::GetIO(); +// io.IniFilename = buffer; +// //io.IniSavingRate = 5.f; +// io.DeltaTime = 1.f / 60.f; +// io.PixelCenterOffset = 0.5f; +// io.KeyMap[ImGuiKey_Tab] = SGCT_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. +// io.KeyMap[ImGuiKey_LeftArrow] = SGCT_KEY_LEFT; +// io.KeyMap[ImGuiKey_RightArrow] = SGCT_KEY_RIGHT; +// io.KeyMap[ImGuiKey_UpArrow] = SGCT_KEY_UP; +// io.KeyMap[ImGuiKey_DownArrow] = SGCT_KEY_DOWN; +// io.KeyMap[ImGuiKey_Home] = SGCT_KEY_HOME; +// io.KeyMap[ImGuiKey_End] = SGCT_KEY_END; +// io.KeyMap[ImGuiKey_Delete] = SGCT_KEY_DELETE; +// io.KeyMap[ImGuiKey_Backspace] = SGCT_KEY_BACKSPACE; +// io.KeyMap[ImGuiKey_Enter] = SGCT_KEY_ENTER; +// io.KeyMap[ImGuiKey_Escape] = SGCT_KEY_ESCAPE; +// io.KeyMap[ImGuiKey_A] = SGCT_KEY_A; +// io.KeyMap[ImGuiKey_C] = SGCT_KEY_C; +// io.KeyMap[ImGuiKey_V] = SGCT_KEY_V; +// io.KeyMap[ImGuiKey_X] = SGCT_KEY_X; +// io.KeyMap[ImGuiKey_Y] = SGCT_KEY_Y; +// io.KeyMap[ImGuiKey_Z] = SGCT_KEY_Z; +// +// io.RenderDrawListsFn = ImImpl_RenderDrawLists; +// //io.SetClipboardTextFn = ImImpl_SetClipboardTextFn; // @TODO implement? ---abock +// //io.GetClipboardTextFn = ImImpl_GetClipboardTextFn; // @TODO implement? ---abock +//} +// +//void GUI::initializeGL() { +// _program = ghoul::opengl::ProgramObject::Build("GUI", +// "${SHADERS}/gui_vs.glsl", "${SHADERS}/gui_fs.glsl"); +// +// positionLocation = glGetAttribLocation(*_program, "in_position"); +// uvLocation = glGetAttribLocation(*_program, "in_uv"); +// colorLocation = glGetAttribLocation(*_program, "in_color"); +// +// glGenTextures(1, &fontTex); +// glBindTexture(GL_TEXTURE_2D, fontTex); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +// const void* png_data; +// unsigned int png_size; +// ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); +// int tex_x, tex_y, tex_comp; +// void* tex_data = stbi_load_from_memory((const unsigned char*)png_data, (int)png_size, &tex_x, &tex_y, &tex_comp, 0); +// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_x, tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data); +// stbi_image_free(tex_data); +// +// glGenBuffers(1, &vbo); +// glBindBuffer(GL_ARRAY_BUFFER, vbo); +// glBufferData(GL_ARRAY_BUFFER, vboMaxSize, NULL, GL_DYNAMIC_DRAW); +// +// glGenVertexArrays(1, &vao); +// glBindVertexArray(vao); +// glBindBuffer(GL_ARRAY_BUFFER, vbo); +// glEnableVertexAttribArray(positionLocation); +// glEnableVertexAttribArray(uvLocation); +// glEnableVertexAttribArray(colorLocation); +// +// glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, pos)); +// glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, uv)); +// glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, col)); +// glBindVertexArray(0); +// glBindBuffer(GL_ARRAY_BUFFER, 0); +//} +// +//void GUI::deinitializeGL() { +// if(_program) +// delete _program; +// _program = nullptr; +// +// if (vao) glDeleteVertexArrays(1, &vao); +// if (vbo) glDeleteBuffers(1, &vbo); +//} +// +//void GUI::startFrame(float deltaTime, +// const glm::vec2& windowSize, +// const glm::vec2& mousePos, +// bool mouseButtonsPressed[2]) +//{ +// ImGuiIO& io = ImGui::GetIO(); +// io.DisplaySize = ImVec2(windowSize.x, windowSize.y); +// io.DeltaTime = deltaTime; +// io.MousePos = ImVec2(mousePos.x, mousePos.y); +// io.MouseDown[0] = mouseButtonsPressed[0]; +// io.MouseDown[1] = mouseButtonsPressed[1]; +// +// ImGui::NewFrame(); +//} +// +//void GUI::endFrame() { +// static bool show = true; +// //ImGui::ShowTestWindow(&show); +// renderMainWindow(); +// if (_showPropertyWindow) +// renderPropertyWindow(); +// if (_showPerformanceWindow) +// renderPerformanceWindow(); +// +// ImGui::Render(); +//} +// +//bool GUI::mouseButtonCallback(int key, int action) { +// ImGuiIO& io = ImGui::GetIO(); +// bool consumeEvent = io.WantCaptureMouse; +// return consumeEvent; +//} +// +//bool GUI::mouseWheelCallback(int position) { +// ImGuiIO& io = ImGui::GetIO(); +// bool consumeEvent = io.WantCaptureMouse; +// if (consumeEvent) +// io.MouseWheel = static_cast(position); +// +// return consumeEvent; +//} +// +//bool GUI::keyCallback(int key, int action) { +// ImGuiIO& io = ImGui::GetIO(); +// bool consumeEvent = io.WantCaptureKeyboard; +// if (consumeEvent) { +// if (action == SGCT_PRESS) +// io.KeysDown[key] = true; +// if (action == SGCT_RELEASE) +// io.KeysDown[key] = false; +// } +// return consumeEvent; +//} +// +//bool GUI::charCallback(unsigned int character) { +// ImGuiIO& io = ImGui::GetIO(); +// bool consumeEvent = io.WantCaptureKeyboard; +// +// if (consumeEvent) +// io.AddInputCharacter((unsigned short)character); +// +// return consumeEvent; +//} +// +//void GUI::registerProperty(properties::Property* prop) { +// using namespace openspace::properties; +// +// std::string className = prop->className(); +// +// if (className == "BoolProperty") +// _boolProperties.insert(prop); +// else if (className == "IntProperty") +// _intProperties.insert(prop); +// else if (className == "FloatProperty") +// _floatProperties.insert(prop); +// else if (className == "StringProperty") +// _stringProperties.insert(prop); +// else if (className == "Vec2Property") +// _vec2Properties.insert(prop); +// else if (className == "Vec3Property") +// _vec3Properties.insert(prop); +// else if (className == "OptionProperty") +// _optionProperty.insert(prop); +// else if (className == "TriggerProperty") +// _triggerProperty.insert(prop); +// else if (className == "SelectionProperty") +// _selectionProperty.insert(prop); +// else { +// LWARNING("Class name '" << className << "' not handled in GUI generation"); +// return; +// } +// +// std::string fullyQualifiedId = prop->fullyQualifiedIdentifier(); +// size_t pos = fullyQualifiedId.find('.'); +// std::string owner = fullyQualifiedId.substr(0, pos); +// +// auto it =_propertiesByOwner.find(owner); +// if (it == _propertiesByOwner.end()) +// _propertiesByOwner[owner] = { prop }; +// else +// it->second.push_back(prop); +// +//} +// +//void GUI::renderMainWindow() { +// ImGui::Begin("OpenSpace GUI", nullptr); +// +// ImGui::Checkbox("Properties", &_showPropertyWindow); +// ImGui::Checkbox("Performance", &_showPerformanceWindow); +// ImGui::Checkbox("Help", &_showHelp); +// +// if (_showHelp) { +// ImGui::Separator(); +// ImGui::ShowUserGuide(); +// ImGui::ShowTestWindow(); +// } +// +// ImGui::End(); +//} +// +//void GUI::renderPropertyWindow() { +// using namespace properties; +// +// ImGui::Begin("Properties", &_showPropertyWindow, size, 0.5f); +// +// //ImGui::ShowUserGuide(); +// ImGui::Spacing(); +// +// for (const auto& p : _propertiesByOwner) { +// if (ImGui::CollapsingHeader(p.first.c_str())) { +// for (properties::Property* prop : p.second) { +// if (_boolProperties.find(prop) != _boolProperties.end()) { +// renderBoolProperty(prop, p.first); +// continue; +// } +// +// if (_intProperties.find(prop) != _intProperties.end()) { +// renderIntProperty(prop, p.first); +// continue; +// } +// +// if (_floatProperties.find(prop) != _floatProperties.end()) { +// renderFloatProperty(prop, p.first); +// continue; +// } +// +// if (_vec2Properties.find(prop) != _vec2Properties.end()) { +// renderVec2Property(prop, p.first); +// continue; +// } +// +// if (_vec3Properties.find(prop) != _vec3Properties.end()) { +// renderVec3Property(prop, p.first); +// continue; +// } +// +// if (_optionProperty.find(prop) != _optionProperty.end()) { +// renderOptionProperty(prop, p.first); +// continue; +// } +// +// if (_triggerProperty.find(prop) != _triggerProperty.end()) { +// renderTriggerProperty(prop, p.first); +// continue; +// } +// +// if (_selectionProperty.find(prop) != _selectionProperty.end()) { +// renderSelectionProperty(prop, p.first); +// continue; +// } +// } +// } +// } +// +// ImGui::End(); +//} +// +//void GUI::renderPerformanceWindow() { +// // Copy and paste from renderengine.cpp::storePerformanceMeasurements method +// const int8_t Version = 0; +// const int nValues = 250; +// const int lengthName = 256; +// const int maxValues = 50; +// +// struct PerformanceLayout { +// int8_t version; +// int32_t nValuesPerEntry; +// int32_t nEntries; +// int32_t maxNameLength; +// int32_t maxEntries; +// +// struct PerformanceLayoutEntry { +// char name[lengthName]; +// float renderTime[nValues]; +// float updateRenderable[nValues]; +// float updateEphemeris[nValues]; +// +// int32_t currentRenderTime; +// int32_t currentUpdateRenderable; +// int32_t currentUpdateEphemeris; +// }; +// +// PerformanceLayoutEntry entries[maxValues]; +// }; +// +// ImGui::Begin("Performance", &_showPerformanceWindow); +// if (OsEng.renderEngine().doesPerformanceMeasurements() && +// ghoul::SharedMemory::exists(RenderEngine::PerformanceMeasurementSharedData)) +// { +// ImGui::SliderFloat2("Min values, max Value", _minMaxValues, 0.f, 10000.f); +// _minMaxValues[1] = std::max(_minMaxValues[0], _minMaxValues[1]); +// +// if (!_performanceMemory) +// _performanceMemory = new ghoul::SharedMemory(RenderEngine::PerformanceMeasurementSharedData); +// +// PerformanceLayout* layout = reinterpret_cast(_performanceMemory->pointer()); +// +// for (int i = 0; i < layout->nEntries; ++i) { +// const PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; +// +// if (ImGui::CollapsingHeader(entry.name)) { +// std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[entry.currentUpdateEphemeris - 1]) + "us"; +// ImGui::PlotLines("UpdateEphemeris", &entry.updateEphemeris[0], layout->nValuesPerEntry, 0, updateEphemerisTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); +// +// std::string updateRenderableTime = std::to_string(entry.updateRenderable[entry.currentUpdateRenderable - 1]) + "us"; +// ImGui::PlotLines("UpdateRender", &entry.updateRenderable[0], layout->nValuesPerEntry, 0, updateRenderableTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); +// +// std::string renderTime = std::to_string(entry.renderTime[entry.currentRenderTime - 1]) + "us"; +// ImGui::PlotLines("RenderTime", &entry.renderTime[0], layout->nValuesPerEntry, 0, renderTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); +// } +// } +// } +// else { +// ImGui::TextWrapped("Performance monitoring is disabled. Enable with " +// "'openspace.setPerformanceMeasurement(true)'"); +// } +// +// ImGui::End(); +//} +// +// +//} // namespace openspace +//} // namespace gui diff --git a/src/gui/guicomponent.cpp b/src/gui/guicomponent.cpp new file mode 100644 index 0000000000..28764ebe82 --- /dev/null +++ b/src/gui/guicomponent.cpp @@ -0,0 +1,47 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 { +namespace gui { + +bool GuiComponent::isEnabled() const { + return _isEnabled; +} + +void GuiComponent::setEnabled(bool enabled) { + _isEnabled = enabled; +} + +void GuiComponent::initialize() {} + +void GuiComponent::initializeGL() {} + +void GuiComponent::deinitialize() {} + +void GuiComponent::deinitializeGL() {} + +} // namespace gui +} // namespace openspace diff --git a/src/gui/guiperformancecomponent.cpp b/src/gui/guiperformancecomponent.cpp new file mode 100644 index 0000000000..1924af6350 --- /dev/null +++ b/src/gui/guiperformancecomponent.cpp @@ -0,0 +1,107 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 +#include + +namespace { + const std::string _loggerCat = "GuiPerformanceComponent"; +} + +namespace openspace { +namespace gui { + +void GuiPerformanceComponent::initialize() { +} + +void GuiPerformanceComponent::render() { + // Copy and paste from renderengine.cpp::storePerformanceMeasurements method + const int8_t Version = 0; + const int nValues = 250; + const int lengthName = 256; + const int maxValues = 50; + + struct PerformanceLayout { + int8_t version; + int32_t nValuesPerEntry; + int32_t nEntries; + int32_t maxNameLength; + int32_t maxEntries; + + struct PerformanceLayoutEntry { + char name[lengthName]; + float renderTime[nValues]; + float updateRenderable[nValues]; + float updateEphemeris[nValues]; + + int32_t currentRenderTime; + int32_t currentUpdateRenderable; + int32_t currentUpdateEphemeris; + }; + + PerformanceLayoutEntry entries[maxValues]; + }; + + ImGui::Begin("Performance", &_isEnabled); + if (OsEng.renderEngine().doesPerformanceMeasurements() && + ghoul::SharedMemory::exists(RenderEngine::PerformanceMeasurementSharedData)) + { + ImGui::SliderFloat2("Min values, max Value", _minMaxValues, 0.f, 10000.f); + _minMaxValues[1] = std::max(_minMaxValues[0], _minMaxValues[1]); + + if (!_performanceMemory) + _performanceMemory = new ghoul::SharedMemory(RenderEngine::PerformanceMeasurementSharedData); + + PerformanceLayout* layout = reinterpret_cast(_performanceMemory->pointer()); + + for (int i = 0; i < layout->nEntries; ++i) { + const PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; + + if (ImGui::CollapsingHeader(entry.name)) { + std::string updateEphemerisTime = std::to_string(entry.updateEphemeris[entry.currentUpdateEphemeris - 1]) + "us"; + ImGui::PlotLines("UpdateEphemeris", &entry.updateEphemeris[0], layout->nValuesPerEntry, 0, updateEphemerisTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); + + std::string updateRenderableTime = std::to_string(entry.updateRenderable[entry.currentUpdateRenderable - 1]) + "us"; + ImGui::PlotLines("UpdateRender", &entry.updateRenderable[0], layout->nValuesPerEntry, 0, updateRenderableTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); + + std::string renderTime = std::to_string(entry.renderTime[entry.currentRenderTime - 1]) + "us"; + ImGui::PlotLines("RenderTime", &entry.renderTime[0], layout->nValuesPerEntry, 0, renderTime.c_str(), _minMaxValues[0], _minMaxValues[1], ImVec2(0, 40)); + } + } + } + else { + ImGui::TextWrapped("Performance monitoring is disabled. Enable with " + "'openspace.setPerformanceMeasurement(true)'"); + } + + ImGui::End(); +} + + +} // namespace gui +} // namespace openspace diff --git a/src/gui/guipropertycomponent.cpp b/src/gui/guipropertycomponent.cpp new file mode 100644 index 0000000000..4dba9ddf46 --- /dev/null +++ b/src/gui/guipropertycomponent.cpp @@ -0,0 +1,237 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 +#include +#include +#include + +#include "imgui.h" + +namespace { + const std::string _loggerCat = "GuiPropertyComponent"; + const ImVec2 size = ImVec2(350, 500); + + using namespace openspace::properties; + + void renderBoolProperty(Property* prop, const std::string& ownerName) { + BoolProperty* p = static_cast(prop); + std::string name = p->guiName(); + + BoolProperty::ValueType value = *p; + ImGui::Checkbox((ownerName + "." + name).c_str(), &value); + p->set(value); + } + + void renderOptionProperty(Property* prop, const std::string& ownerName) { + OptionProperty* p = static_cast(prop); + std::string name = p->guiName(); + + int value = *p; + std::vector options = p->options(); + for (const OptionProperty::Option& o : options) { + ImGui::RadioButton((ownerName + "." + name).c_str(), &value, o.value); + ImGui::SameLine(); + ImGui::Text(o.description.c_str()); + } + p->set(value); + } + + void renderSelectionProperty(Property* prop, const std::string& ownerName) { + SelectionProperty* p = static_cast(prop); + std::string name = p->guiName(); + + if (ImGui::CollapsingHeader((ownerName + "." + name).c_str())) { + const std::vector& options = p->options(); + std::vector newSelectedIndices; + + std::vector selectedIndices = p->value(); + + for (int i = 0; i < options.size(); ++i) { + std::string description = options[i].description; + bool selected = std::find(selectedIndices.begin(), selectedIndices.end(), i) != selectedIndices.end(); + ImGui::Checkbox(description.c_str(), &selected); + + if (selected) + newSelectedIndices.push_back(i); + } + + p->setValue(std::move(newSelectedIndices)); + } + } + + void renderIntProperty(Property* prop, const std::string& ownerName) { + IntProperty* p = static_cast(prop); + std::string name = p->guiName(); + + IntProperty::ValueType value = *p; + ImGui::SliderInt((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue()); + p->set(value); + } + + void renderFloatProperty(Property* prop, const std::string& ownerName) { + FloatProperty* p = static_cast(prop); + std::string name = p->guiName(); + + FloatProperty::ValueType value = *p; + ImGui::SliderFloat((ownerName + "." + name).c_str(), &value, p->minValue(), p->maxValue()); + p->set(value); + } + + void renderVec2Property(Property* prop, const std::string& ownerName) { + Vec2Property* p = static_cast(prop); + std::string name = p->guiName(); + + Vec2Property::ValueType value = *p; + + ImGui::SliderFloat2((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x); + p->set(value); + } + + + void renderVec3Property(Property* prop, const std::string& ownerName) { + Vec3Property* p = static_cast(prop); + std::string name = p->guiName(); + + Vec3Property::ValueType value = *p; + + ImGui::SliderFloat3((ownerName + "." + name).c_str(), &value.x, p->minValue().x, p->maxValue().x); + p->set(value); + } + + void renderTriggerProperty(Property* prop, const std::string& ownerName) { + std::string name = prop->guiName(); + bool pressed = ImGui::Button((ownerName + "." + name).c_str()); + if (pressed) + prop->set(0); + } + +} + +namespace openspace { +namespace gui { + +void GuiPropertyComponent::registerProperty(properties::Property* prop) { + using namespace properties; + + std::string className = prop->className(); + + if (className == "BoolProperty") + _boolProperties.insert(prop); + else if (className == "IntProperty") + _intProperties.insert(prop); + else if (className == "FloatProperty") + _floatProperties.insert(prop); + else if (className == "StringProperty") + _stringProperties.insert(prop); + else if (className == "Vec2Property") + _vec2Properties.insert(prop); + else if (className == "Vec3Property") + _vec3Properties.insert(prop); + else if (className == "OptionProperty") + _optionProperty.insert(prop); + else if (className == "TriggerProperty") + _triggerProperty.insert(prop); + else if (className == "SelectionProperty") + _selectionProperty.insert(prop); + else { + LWARNING("Class name '" << className << "' not handled in GUI generation"); + return; + } + + std::string fullyQualifiedId = prop->fullyQualifiedIdentifier(); + size_t pos = fullyQualifiedId.find('.'); + std::string owner = fullyQualifiedId.substr(0, pos); + + auto it = _propertiesByOwner.find(owner); + if (it == _propertiesByOwner.end()) + _propertiesByOwner[owner] = { prop }; + else + it->second.push_back(prop); + +} + +void GuiPropertyComponent::render() { + using namespace openspace::properties; + + ImGui::Begin("Properties", &_isEnabled, size, 0.5f); + + //ImGui::ShowUserGuide(); + ImGui::Spacing(); + + for (const auto& p : _propertiesByOwner) { + if (ImGui::CollapsingHeader(p.first.c_str())) { + for (properties::Property* prop : p.second) { + if (_boolProperties.find(prop) != _boolProperties.end()) { + renderBoolProperty(prop, p.first); + continue; + } + + if (_intProperties.find(prop) != _intProperties.end()) { + renderIntProperty(prop, p.first); + continue; + } + + if (_floatProperties.find(prop) != _floatProperties.end()) { + renderFloatProperty(prop, p.first); + continue; + } + + if (_vec2Properties.find(prop) != _vec2Properties.end()) { + renderVec2Property(prop, p.first); + continue; + } + + if (_vec3Properties.find(prop) != _vec3Properties.end()) { + renderVec3Property(prop, p.first); + continue; + } + + if (_optionProperty.find(prop) != _optionProperty.end()) { + renderOptionProperty(prop, p.first); + continue; + } + + if (_triggerProperty.find(prop) != _triggerProperty.end()) { + renderTriggerProperty(prop, p.first); + continue; + } + + if (_selectionProperty.find(prop) != _selectionProperty.end()) { + renderSelectionProperty(prop, p.first); + continue; + } + } + } + } + + ImGui::End(); +} + +} // gui +} // openspace diff --git a/src/scenegraph/scenegraph.cpp b/src/scenegraph/scenegraph.cpp index 8ebaccbee8..ab3e5c25c0 100644 --- a/src/scenegraph/scenegraph.cpp +++ b/src/scenegraph/scenegraph.cpp @@ -445,7 +445,7 @@ bool SceneGraph::loadSceneInternal(const std::string& sceneDescriptionFilePath) for (SceneGraphNode* node : _nodes) { std::vector properties = node->propertiesRecursive(); for (properties::Property* p : properties) { - OsEng.gui().registerProperty(p); + OsEng.gui()._property.registerProperty(p); } }