diff --git a/core/src/view/light/DistantLight.cpp b/core/src/view/light/DistantLight.cpp index 15a4ed59ec..a4b7ea5326 100644 --- a/core/src/view/light/DistantLight.cpp +++ b/core/src/view/light/DistantLight.cpp @@ -32,7 +32,7 @@ DistantLight::DistantLight(void) lightsource = std::make_shared(); this->angularDiameter << new core::param::FloatParam(0.0f); - this->direction << new core::param::Vector3fParam(vislib::math::Vector(0.0f, -1.0f, 0.0f)); + this->direction << new core::param::Vector3fParam(vislib::math::Vector(-0.25f, -0.5f, -0.75f)); this->eye_direction << new core::param::BoolParam(0); this->MakeSlotAvailable(&this->direction); this->MakeSlotAvailable(&this->angularDiameter); diff --git a/externals/CMakeExternals.cmake b/externals/CMakeExternals.cmake index 1a8f896c4a..f065ed46a8 100644 --- a/externals/CMakeExternals.cmake +++ b/externals/CMakeExternals.cmake @@ -377,8 +377,8 @@ function(require_external NAME) external_get_property(imgui INSTALL_DIR) add_external_project(imguizmoquat STATIC - GIT_REPOSITORY https://github.com/BrutPitt/imGuIZMO.quat.git - GIT_TAG "v3.0" + GIT_REPOSITORY https://github.com/braunms/imGuIZMO.quat.git + GIT_TAG "v3.0a" BUILD_BYPRODUCTS "/${IMGUIZMOQUAT_LIB}" DEPENDS imgui CMAKE_ARGS diff --git a/plugins/gui/src/Configurator.cpp b/plugins/gui/src/Configurator.cpp index 22bdadf1f7..2c1b70d8ec 100644 --- a/plugins/gui/src/Configurator.cpp +++ b/plugins/gui/src/Configurator.cpp @@ -5,15 +5,6 @@ * Alle Rechte vorbehalten. */ -/** - * USED HOTKEYS: - * - * - Search Module: Ctrl + Shift + m - * - Search Parameter: Ctrl + Shift + p - * - Save Edited Project: Ctrl + Shift + s - * - Delete Graph Item: Delete - */ - #include "stdafx.h" #include "Configurator.h" diff --git a/plugins/gui/src/GUIUtils.h b/plugins/gui/src/GUIUtils.h index 9621fb3c36..181ea0f794 100644 --- a/plugins/gui/src/GUIUtils.h +++ b/plugins/gui/src/GUIUtils.h @@ -9,6 +9,27 @@ #define MEGAMOL_GUI_GUIUTILS_INCLUDED +/** + * USED HOTKEYS: + * + * ----- GUIWindows ----- + * - Trigger Screenshot: F2 + * - Toggle Graph Entry: F3 + * - Show/hide Windows: F7-F11 + * - Show/hide Menu: F12 + * - Show/hide GUI: Ctrl + g + * - Search Parameter: Ctrl + p + * - Save Running Project: Ctrl + s + * - Quit Program: Alt + F4 + + * ----- Configurator ----- + * - Search Module: Ctrl + Shift + m + * - Search Parameter: Ctrl + Shift + p + * - Save Edited Project: Ctrl + Shift + s + * - Delete Graph Item: Delete + * + **/ + #define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS #include "imgui.h" @@ -229,14 +250,14 @@ namespace gui { ImGuiID group_hovered_uid; // in out bool group_layout; // out - UIDVector_t modules_selected_uids; // in out - ImGuiID module_hovered_uid; // in out - UIDPairVector_t modules_add_group_uids; // out - UIDVector_t modules_remove_group_uids; // out - bool modules_layout; // out - StrPairVector_t module_rename; // out - vislib::math::Ternary module_mainview_changed; // out - ImVec2 module_param_child_position; // out + UIDVector_t modules_selected_uids; // in out + ImGuiID module_hovered_uid; // in out + UIDPairVector_t modules_add_group_uids; // out + UIDVector_t modules_remove_group_uids; // out + bool modules_layout; // out + StrPairVector_t module_rename; // out + vislib::math::Ternary module_graphentry_changed; // out + ImVec2 module_param_child_position; // out ImGuiID call_selected_uid; // in out ImGuiID call_hovered_uid; // in out diff --git a/plugins/gui/src/GUIWindows.cpp b/plugins/gui/src/GUIWindows.cpp index c2882ac812..6b5fde0cf7 100644 --- a/plugins/gui/src/GUIWindows.cpp +++ b/plugins/gui/src/GUIWindows.cpp @@ -5,18 +5,6 @@ * Alle Rechte vorbehalten. */ -/** - * USED HOTKEYS: - * - * - Trigger Screenshot: F2 - * - Toggle Main View: F3 - * - Show/hide Windows: F7-F11 - * - Show/hide Menu: F12 - * - Search Parameter: Ctrl + p - * - Save Running Project: Ctrl + s - * - Quit Program: Alt + F4 - */ - #include "stdafx.h" #include "GUIWindows.h" @@ -42,7 +30,7 @@ GUIWindows::GUIWindows(void) this->hotkeys[GUIWindows::GuiHotkeyIndex::TRIGGER_SCREENSHOT] = { megamol::core::view::KeyCode(megamol::core::view::Key::KEY_F2, core::view::Modifier::NONE), false}; - this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_MAIN_VIEWS] = { + this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_GRAPH_ENTRY] = { megamol::core::view::KeyCode(megamol::core::view::Key::KEY_F3, core::view::Modifier::NONE), false}; this->hotkeys[GUIWindows::GuiHotkeyIndex::EXIT_PROGRAM] = { megamol::core::view::KeyCode(megamol::core::view::Key::KEY_F4, core::view::Modifier::ALT), false}; @@ -175,28 +163,34 @@ bool GUIWindows::PreDraw(glm::vec2 framebuffer_size, glm::vec2 window_size, doub /// [DEPRECATED USAGE - only mmconsole] /// // Disable GUI drawing if GUIView module is chained - if (this->state.gui_enabled && ImGui::GetCurrentContext()->WithinFrameScope) { + if (this->state.gui_visible && ImGui::GetCurrentContext()->WithinFrameScope) { megamol::core::utility::log::Log::DefaultLog.WriteError( "[GUI] Chaining GUIVIew modules is not supported. GUI is disabled. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__); - this->state.gui_enabled = false; + this->state.gui_visible = false; } - // Check hotkey for gui toggling - if (this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].is_pressed) { - this->state.gui_enabled = !this->state.gui_enabled; - // Restore menu when GUI is enabled - if (this->state.gui_enabled) { - this->state.menu_visible = true; - } + // Restore GUI after it was disabled (before early exit!) + if (!this->state.gui_visible && this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].is_pressed) { this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].is_pressed = false; + // Restore window 'open' state (Always restore at least menu) + this->state.menu_visible = true; + const auto func = [&, this](WindowCollection::WindowConfiguration& wc) { + if (std::find(this->state.gui_visible_buffer.begin(), this->state.gui_visible_buffer.end(), + wc.win_callback) != this->state.gui_visible_buffer.end()) { + wc.win_show = true; + } + }; + this->window_collection.EnumWindows(func); + this->state.gui_visible_buffer.clear(); + this->state.gui_visible = true; } // Required to prevent change in gui drawing between pre and post draw - this->state.enable_gui_post = this->state.gui_enabled; + this->state.gui_visible_post = this->state.gui_visible; // Early exit when pre step should be omitted - if (!this->state.gui_enabled) { + if (!this->state.gui_visible) { return true; } @@ -258,6 +252,28 @@ bool GUIWindows::PreDraw(glm::vec2 framebuffer_size, glm::vec2 window_size, doub // Process hotkeys this->checkMultipleHotkeyAssignement(); + if (this->state.gui_visible) { + // Second frame + if (this->state.gui_hide_next_frame) { + this->state.gui_hide_next_frame = false; + this->state.gui_visible = false; + } + // First frame + if (this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].is_pressed) { + this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].is_pressed = false; + // Save 'open' state of windows for later restore. Closing all windows before omitting GUI rendering is + // required to set right ImGui state for mouse handling + this->state.gui_visible_buffer.clear(); + const auto func = [&, this](WindowCollection::WindowConfiguration& wc) { + if (wc.win_show) { + this->state.gui_visible_buffer.push_back(wc.win_callback); + wc.win_show = false; + } + }; + this->window_collection.EnumWindows(func); + this->state.gui_hide_next_frame = true; + } + } if (this->hotkeys[GUIWindows::GuiHotkeyIndex::EXIT_PROGRAM].is_pressed) { this->triggerCoreInstanceShutdown(); this->state.shutdown_triggered = true; @@ -271,42 +287,42 @@ bool GUIWindows::PreDraw(glm::vec2 framebuffer_size, glm::vec2 window_size, doub this->state.screenshot_triggered = true; this->hotkeys[GUIWindows::GuiHotkeyIndex::TRIGGER_SCREENSHOT].is_pressed = false; } - if (this->state.toggle_main_view || this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_MAIN_VIEWS].is_pressed) { + if (this->state.toggle_graph_entry || this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_GRAPH_ENTRY].is_pressed) { GraphPtr_t graph_ptr; if (this->configurator.GetGraphCollection().GetGraph(this->state.graph_uid, graph_ptr)) { - megamol::gui::ModulePtrVector_t::const_iterator module_mainview_iter = graph_ptr->GetModules().begin(); - // Search for first main view and set next view to main view (= graph entry point) + megamol::gui::ModulePtrVector_t::const_iterator module_graph_entry_iter = graph_ptr->GetModules().begin(); + // Search for first graph entry and set next view to graph entry (= graph entry point) for (auto module_iter = graph_ptr->GetModules().begin(); module_iter != graph_ptr->GetModules().end(); module_iter++) { - if ((*module_iter)->is_view && (*module_iter)->IsMainView()) { - // Remove all main views - (*module_iter)->main_view_name.clear(); + if ((*module_iter)->is_view && (*module_iter)->IsGraphEntry()) { + // Remove all graph entries + (*module_iter)->graph_entry_name.clear(); Graph::QueueData queue_data; queue_data.name_id = (*module_iter)->FullName(); - graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); - // Save index of last found main view + graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_GRAPH_ENTRY, queue_data); + // Save index of last found graph entry if (module_iter != graph_ptr->GetModules().end()) { - module_mainview_iter = module_iter + 1; + module_graph_entry_iter = module_iter + 1; } } } - if ((module_mainview_iter == graph_ptr->GetModules().begin()) || - (module_mainview_iter != graph_ptr->GetModules().end())) { - // Search for next main view - for (auto module_iter = module_mainview_iter; module_iter != graph_ptr->GetModules().end(); + if ((module_graph_entry_iter == graph_ptr->GetModules().begin()) || + (module_graph_entry_iter != graph_ptr->GetModules().end())) { + // Search for next graph entry + for (auto module_iter = module_graph_entry_iter; module_iter != graph_ptr->GetModules().end(); module_iter++) { if ((*module_iter)->is_view) { - (*module_iter)->main_view_name = graph_ptr->GenerateUniqueMainViewName(); + (*module_iter)->graph_entry_name = graph_ptr->GenerateUniqueGraphEntryName(); Graph::QueueData queue_data; queue_data.name_id = (*module_iter)->FullName(); - graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_MAIN_VIEW, queue_data); + graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_GRAPH_ENTRY, queue_data); break; } } } } - this->state.toggle_main_view = false; - this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_MAIN_VIEWS].is_pressed = false; + this->state.toggle_graph_entry = false; + this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_GRAPH_ENTRY].is_pressed = false; } // Auto-save state @@ -367,7 +383,7 @@ bool GUIWindows::PreDraw(glm::vec2 framebuffer_size, glm::vec2 window_size, doub bool GUIWindows::PostDraw(void) { // Early exit when post step should be omitted - if (!this->state.enable_gui_post) { + if (!this->state.gui_visible_post) { return true; } @@ -859,7 +875,7 @@ void megamol::gui::GUIWindows::SetClipboardFunc(const char* (*get_clipboard_func bool megamol::gui::GUIWindows::SynchronizeGraphs(megamol::core::MegaMolGraph* megamol_graph) { // Disable synchronizing graphs when pre step is omitted - if (!this->state.gui_enabled) { + if (!this->state.gui_visible) { return true; } @@ -937,7 +953,7 @@ bool megamol::gui::GUIWindows::SynchronizeGraphs(megamol::core::MegaMolGraph* me vislib::StringA(data.caller.c_str()), vislib::StringA(data.callee.c_str())); } } break; - case (Graph::QueueAction::CREATE_MAIN_VIEW): { + case (Graph::QueueAction::CREATE_GRAPH_ENTRY): { if (megamol_graph != nullptr) { megamol_graph->SetGraphEntryPoint(data.name_id, megamol::core::view::get_gl_view_runtime_resources_requests(), @@ -947,7 +963,7 @@ bool megamol::gui::GUIWindows::SynchronizeGraphs(megamol::core::MegaMolGraph* me */ } } break; - case (Graph::QueueAction::REMOVE_MAIN_VIEW): { + case (Graph::QueueAction::REMOVE_GRAPH_ENTRY): { if (megamol_graph != nullptr) { megamol_graph->RemoveGraphEntryPoint(data.name_id); } else if (this->core_instance != nullptr) { @@ -1718,11 +1734,6 @@ void GUIWindows::drawMenu(void) { // FILE ------------------------------------------------------------------- if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("Enable/Disable GUI", - this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].keycode.ToString().c_str())) { - this->state.gui_enabled = !this->state.gui_enabled; - } - if (megamolgraph_interface) { if (ImGui::MenuItem("Load Project", this->hotkeys[GUIWindows::GuiHotkeyIndex::LOAD_PROJECT].keycode.ToString().c_str())) { @@ -1739,6 +1750,7 @@ void GUIWindows::drawMenu(void) { } ImGui::EndMenu(); } + ImGui::Separator(); // WINDOWS ---------------------------------------------------------------- if (ImGui::BeginMenu("Windows")) { @@ -1769,6 +1781,7 @@ void GUIWindows::drawMenu(void) { ImGui::EndMenu(); } + ImGui::Separator(); // SCREENSHOT ------------------------------------------------------------- if (megamolgraph_interface) { @@ -1784,48 +1797,56 @@ void GUIWindows::drawMenu(void) { ImGui::EndMenu(); } } + ImGui::Separator(); // RENDER ----------------------------------------------------------------- if (megamolgraph_interface && (graph_ptr != nullptr)) { if (ImGui::BeginMenu("Render")) { for (auto& module_ptr : graph_ptr->GetModules()) { if (module_ptr->is_view) { - if (ImGui::MenuItem(module_ptr->FullName().c_str(), "", module_ptr->IsMainView())) { - if (!module_ptr->IsMainView()) { - // Remove all main views + if (ImGui::MenuItem(module_ptr->FullName().c_str(), "", module_ptr->IsGraphEntry())) { + if (!module_ptr->IsGraphEntry()) { + // Remove all graph entries for (auto module_ptr : graph_ptr->GetModules()) { - if (module_ptr->is_view && module_ptr->IsMainView()) { - module_ptr->main_view_name.clear(); + if (module_ptr->is_view && module_ptr->IsGraphEntry()) { + module_ptr->graph_entry_name.clear(); Graph::QueueData queue_data; queue_data.name_id = module_ptr->FullName(); - graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_GRAPH_ENTRY, queue_data); } } - // Add new main view - module_ptr->main_view_name = graph_ptr->GenerateUniqueMainViewName(); + // Add new graph entry + module_ptr->graph_entry_name = graph_ptr->GenerateUniqueGraphEntryName(); Graph::QueueData queue_data; queue_data.name_id = module_ptr->FullName(); - graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_MAIN_VIEW, queue_data); + graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_GRAPH_ENTRY, queue_data); } else { - module_ptr->main_view_name.clear(); + module_ptr->graph_entry_name.clear(); Graph::QueueData queue_data; queue_data.name_id = module_ptr->FullName(); - graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_GRAPH_ENTRY, queue_data); } } } } - if (ImGui::MenuItem("Toggle Main Views", - this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_MAIN_VIEWS].keycode.ToString().c_str())) { - this->state.toggle_main_view = true; + if (ImGui::MenuItem("Toggle Graph Entry", + this->hotkeys[GUIWindows::GuiHotkeyIndex::TOGGLE_GRAPH_ENTRY].keycode.ToString().c_str())) { + this->state.toggle_graph_entry = true; } ImGui::EndMenu(); } } + ImGui::Separator(); // SETTINGS --------------------------------------------------------------- if (ImGui::BeginMenu("Settings")) { + if (ImGui::MenuItem("Enable/Disable GUI", + this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].keycode.ToString().c_str())) { + /// gui_visible needs to be toggled via hotkey! + this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].is_pressed = true; + } + if (ImGui::BeginMenu("Style")) { if (ImGui::MenuItem("ImGui Dark Colors", nullptr, (this->state.style == GUIWindows::Styles::DarkColors))) { @@ -1946,6 +1967,7 @@ void GUIWindows::drawMenu(void) { ImGui::EndMenu(); } + ImGui::Separator(); // HELP ------------------------------------------------------------------- if (ImGui::BeginMenu("Help")) { @@ -1954,6 +1976,7 @@ void GUIWindows::drawMenu(void) { } ImGui::EndMenu(); } + ImGui::Separator(); } @@ -2015,7 +2038,7 @@ void megamol::gui::GUIWindows::drawPopUps(void) { ImGui::TextUnformatted(about.c_str()); ImGui::Separator(); - if (ImGui::Button("Close")) { + if (ImGui::Button("Close") || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape))) { ImGui::CloseCurrentPopup(); } @@ -2032,16 +2055,17 @@ void megamol::gui::GUIWindows::drawPopUps(void) { filename = graph_ptr->GetFilename(); } if (graph_ptr != nullptr) { - bool check_option = false; // Default for option asking for saving gui state + vislib::math::Ternary save_gui_state( + vislib::math::Ternary::TRI_FALSE); // Default for option asking for saving gui state this->state.open_popup_save |= this->configurator.ConsumeTriggeredGlobalProjectSave(); if (this->file_browser.PopUp(filename, FileBrowserWidget::FileBrowserFlag::SAVE, "Save Project", - this->state.open_popup_save, "lua", "Save GUI State?", check_option)) { + this->state.open_popup_save, "lua", save_gui_state)) { graph_ptr->SetFilename(filename); std::string gui_state; - if (check_option) { + if (save_gui_state.IsTrue()) { gui_state = this->dump_state_to_file(filename); } @@ -2324,7 +2348,7 @@ bool megamol::gui::GUIWindows::state_from_json(const nlohmann::json& in_json) { for (auto& header_item : in_json.items()) { if (header_item.key() == GUI_JSON_TAG_GUI) { auto gui_state = header_item.value(); - megamol::core::utility::get_json_value(gui_state, {"gui_enabled"}, &this->state.gui_enabled); + megamol::core::utility::get_json_value(gui_state, {"gui_visible"}, &this->state.gui_visible); megamol::core::utility::get_json_value(gui_state, {"menu_visible"}, &this->state.menu_visible); int style = 0; megamol::core::utility::get_json_value(gui_state, {"style"}, &style); @@ -2379,7 +2403,7 @@ bool megamol::gui::GUIWindows::state_to_json(nlohmann::json& inout_json) { try { // Write GUI state - inout_json[GUI_JSON_TAG_GUI]["gui_enabled"] = this->state.gui_enabled; + inout_json[GUI_JSON_TAG_GUI]["gui_visible"] = this->state.gui_visible; inout_json[GUI_JSON_TAG_GUI]["menu_visible"] = this->state.menu_visible; inout_json[GUI_JSON_TAG_GUI]["style"] = static_cast(this->state.style); GUIUtils::Utf8Encode(this->state.font_file_name); @@ -2425,8 +2449,10 @@ bool megamol::gui::GUIWindows::state_to_json(nlohmann::json& inout_json) { void megamol::gui::GUIWindows::init_state(void) { - this->state.gui_enabled = true; - this->state.enable_gui_post = true; + this->state.gui_visible = true; + this->state.gui_visible_post = true; + this->state.gui_visible_buffer.clear(); + this->state.gui_hide_next_frame = false; this->state.style = GUIWindows::Styles::DarkColors; this->state.rescale_windows = false; this->state.style_changed = true; @@ -2444,7 +2470,7 @@ void megamol::gui::GUIWindows::init_state(void) { this->state.open_popup_screenshot = false; this->state.menu_visible = true; this->state.graph_fonts_reserved = 0; - this->state.toggle_main_view = false; + this->state.toggle_graph_entry = false; this->state.shutdown_triggered = false; this->state.screenshot_triggered = false; this->state.screenshot_filepath = "megamol_screenshot.png"; diff --git a/plugins/gui/src/GUIWindows.h b/plugins/gui/src/GUIWindows.h index 7107cbe6e0..b7d5491912 100644 --- a/plugins/gui/src/GUIWindows.h +++ b/plugins/gui/src/GUIWindows.h @@ -136,10 +136,12 @@ namespace gui { } /** - * Enable or disable GUI drawing + * Show or hide GUI */ - void SetEnableDisable(bool enable) { - this->state.gui_enabled = enable; + void SetVisibility(bool visible) { + if (this->state.gui_visible != visible) { + this->hotkeys[GUIWindows::GuiHotkeyIndex::SHOW_HIDE_GUI].is_pressed = true; + } } /** @@ -176,12 +178,15 @@ namespace gui { /** The global state (for settings to be applied before ImGui::Begin). */ struct StateBuffer { - bool gui_enabled; // Flag indicating whether GUI is completely disabled - bool enable_gui_post; // Required to prevent changes to 'gui_enabled' between pre and post drawing - bool rescale_windows; // Indicates resizing of windows for new gui zoom - Styles style; // Predefined GUI style - bool style_changed; // Flag indicating changed style - bool autosave_gui_state; // Automatically save state after gui has been changed + bool gui_visible; // Flag indicating whether GUI is completely disabled + bool gui_visible_post; // Required to prevent changes to 'gui_enabled' between pre and post drawing + std::vector + gui_visible_buffer; // List of all visible window IDs for restore when GUI is visible again + bool gui_hide_next_frame; // Hiding all GUI windows properly needs two frames for ImGui to apply right state + bool rescale_windows; // Indicates resizing of windows for new gui zoom + Styles style; // Predefined GUI style + bool style_changed; // Flag indicating changed style + bool autosave_gui_state; // Automatically save state after gui has been changed std::vector project_script_paths; // Project Script Path provided by Lua ImGuiID graph_uid; // UID of currently running graph std::vector font_utf8_ranges; // Additional UTF-8 glyph ranges for all ImGui fonts. @@ -195,7 +200,7 @@ namespace gui { bool open_popup_screenshot; // Flag for opening screenshot file pop-up bool menu_visible; // Flag indicating menu state unsigned int graph_fonts_reserved; // Number of fonts reserved for the configurator graph canvas - bool toggle_main_view; // Flag indicating that the main view should be toggeled + bool toggle_graph_entry; // Flag indicating that the main view should be toggeled bool shutdown_triggered; // Flag indicating user triggered shutdown bool screenshot_triggered; // Trigger and file name for screenshot std::string screenshot_filepath; // Filename the screenshot should be saved to @@ -214,7 +219,7 @@ namespace gui { SAVE_PROJECT = 2, LOAD_PROJECT = 3, MENU = 4, - TOGGLE_MAIN_VIEWS = 5, + TOGGLE_GRAPH_ENTRY = 5, TRIGGER_SCREENSHOT = 6, SHOW_HIDE_GUI = 7, INDEX_COUNT = 8 diff --git a/plugins/gui/src/graph/Call.cpp b/plugins/gui/src/graph/Call.cpp index 1347719b1d..c3bcbb23e9 100644 --- a/plugins/gui/src/graph/Call.cpp +++ b/plugins/gui/src/graph/Call.cpp @@ -106,3 +106,17 @@ const megamol::gui::CallSlotPtr_t& megamol::gui::Call::GetCallSlot(megamol::gui: } return this->connected_callslots[type]; } + + +const std::string megamol::gui::Call::GetSlotsLabel(void) { + + std::string caller = "n/a"; + std::string callee = "n/a"; + auto callerslot_ptr = this->GetCallSlot(CallSlotType::CALLER); + auto calleeslot_ptr = this->GetCallSlot(CallSlotType::CALLEE); + if (callerslot_ptr != nullptr) + caller = callerslot_ptr->name; + if (calleeslot_ptr != nullptr) + callee = calleeslot_ptr->name; + return std::string("[" + caller + "] > [" + callee + "]"); +} diff --git a/plugins/gui/src/graph/Call.h b/plugins/gui/src/graph/Call.h index 18abcdc39f..1646cfa68a 100644 --- a/plugins/gui/src/graph/Call.h +++ b/plugins/gui/src/graph/Call.h @@ -74,6 +74,8 @@ namespace gui { this->present.Present(phase, *this, state); } + const std::string GetSlotsLabel(void); + private: // VARIABLES -------------------------------------------------------------- diff --git a/plugins/gui/src/graph/CallPresentation.cpp b/plugins/gui/src/graph/CallPresentation.cpp index 1c7ce9a4ef..38b791b953 100644 --- a/plugins/gui/src/graph/CallPresentation.cpp +++ b/plugins/gui/src/graph/CallPresentation.cpp @@ -18,7 +18,8 @@ using namespace megamol; using namespace megamol::gui; -megamol::gui::CallPresentation::CallPresentation(void) : label_visible(true), selected(false), tooltip() {} +megamol::gui::CallPresentation::CallPresentation(void) + : label_visible(true), slots_visible(false), selected(false), tooltip() {} megamol::gui::CallPresentation::~CallPresentation(void) {} @@ -111,11 +112,23 @@ void megamol::gui::CallPresentation::Present( } } - if (this->label_visible) { + if (this->label_visible || this->slots_visible) { + std::string slots_label = inout_call.GetSlotsLabel(); + auto slots_label_width = ImGui::CalcTextSize(slots_label.c_str()).x; + auto class_name_width = ImGui::CalcTextSize(inout_call.class_name.c_str()).x; ImVec2 call_center = ImVec2(p1.x + (p2.x - p1.x) / 2.0f, p1.y + (p2.y - p1.y) / 2.0f); - auto call_name_width = ImGui::CalcTextSize(inout_call.class_name.c_str()).x; + auto call_name_width = 0.0f; + if (this->label_visible) { + call_name_width = std::max(call_name_width, class_name_width); + } + if (this->slots_visible) { + call_name_width = std::max(call_name_width, slots_label_width); + } ImVec2 rect_size = ImVec2(call_name_width + (2.0f * style.ItemSpacing.x), ImGui::GetFontSize() + (2.0f * style.ItemSpacing.y)); + if (this->label_visible && this->slots_visible) { + rect_size.y += (ImGui::GetFontSize() + style.ItemSpacing.y); + } ImVec2 call_rect_min = ImVec2(call_center.x - (rect_size.x / 2.0f), call_center.y - (rect_size.y / 2.0f)); ImVec2 call_rect_max = ImVec2((call_rect_min.x + rect_size.x), (call_rect_min.y + rect_size.y)); @@ -159,11 +172,12 @@ void megamol::gui::CallPresentation::Present( } // Hover Tooltip - if (state.interact.call_hovered_uid == inout_call.uid) { - std::string tooltip = callerslot_ptr->name + " > " + calleeslot_ptr->name; - this->tooltip.ToolTip(tooltip, ImGui::GetID(button_label.c_str()), 0.5f, 5.0f); - } else { - this->tooltip.Reset(); + if (!this->slots_visible) { + if (state.interact.call_hovered_uid == inout_call.uid) { + this->tooltip.ToolTip(slots_label, ImGui::GetID(button_label.c_str()), 0.5f, 5.0f); + } else { + this->tooltip.Reset(); + } } } else if (phase == megamol::gui::PresentPhase::RENDERING) { @@ -207,9 +221,24 @@ void megamol::gui::CallPresentation::Present( // Draw Text ImVec2 text_pos_left_upper = - (call_center + ImVec2(-(call_name_width / 2.0f), -0.5f * ImGui::GetFontSize())); - draw_list->AddText(text_pos_left_upper, - ImGui::ColorConvertFloat4ToU32(style.Colors[ImGuiCol_Text]), inout_call.class_name.c_str()); + (call_center + ImVec2(-(class_name_width / 2.0f), -0.5f * ImGui::GetFontSize())); + if (this->label_visible && this->slots_visible) { + text_pos_left_upper.y -= (0.5f * ImGui::GetFontSize()); + } + if (this->label_visible) { + draw_list->AddText(text_pos_left_upper, + ImGui::ColorConvertFloat4ToU32(style.Colors[ImGuiCol_Text]), + inout_call.class_name.c_str()); + } + text_pos_left_upper = + (call_center + ImVec2(-(slots_label_width / 2.0f), -0.5f * ImGui::GetFontSize())); + if (this->label_visible && this->slots_visible) { + text_pos_left_upper.y += (0.5f * ImGui::GetFontSize()); + } + if (this->slots_visible) { + draw_list->AddText(text_pos_left_upper, + ImGui::ColorConvertFloat4ToU32(style.Colors[ImGuiCol_Text]), slots_label.c_str()); + } } } diff --git a/plugins/gui/src/graph/CallPresentation.h b/plugins/gui/src/graph/CallPresentation.h index 2c53860554..869ab81008 100644 --- a/plugins/gui/src/graph/CallPresentation.h +++ b/plugins/gui/src/graph/CallPresentation.h @@ -31,6 +31,7 @@ namespace gui { // VARIABLES -------------------------------------------------------------- bool label_visible; + bool slots_visible; // FUNCTIONS -------------------------------------------------------------- diff --git a/plugins/gui/src/graph/Graph.cpp b/plugins/gui/src/graph/Graph.cpp index bdf3faf288..6ac18ed75b 100644 --- a/plugins/gui/src/graph/Graph.cpp +++ b/plugins/gui/src/graph/Graph.cpp @@ -73,7 +73,7 @@ ImGuiID megamol::gui::Graph::AddModule(const ModuleStockVector_t& stock_modules, mod_ptr->plugin_name = mod.plugin_name; mod_ptr->is_view = mod.is_view; mod_ptr->name = this->generate_unique_module_name(mod.class_name); - mod_ptr->main_view_name.clear(); + mod_ptr->graph_entry_name.clear(); mod_ptr->present.label_visible = this->present.GetModuleLabelVisibility(); for (auto& p : mod.parameters) { @@ -145,10 +145,10 @@ bool megamol::gui::Graph::DeleteModule(ImGuiID module_uid, bool force) { for (auto iter = this->modules.begin(); iter != this->modules.end(); iter++) { if ((*iter)->uid == module_uid) { - if (!force && (*iter)->IsMainView()) { + if (!force && (*iter)->IsGraphEntry()) { if (this->GetCoreInterface() == GraphCoreInterface::CORE_INSTANCE_GRAPH) { megamol::core::utility::log::Log::DefaultLog.WriteWarn( - "[GUI] The action [Delete main view/ view instance] is not yet supported for the graph " + "[GUI] The action [Delete graph entry/ view instance] is not yet supported for the graph " "using the 'Core Instance Graph' interface. Open project from file to make desired " "changes. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__); @@ -902,9 +902,9 @@ bool megamol::gui::Graph::PushSyncQueue(QueueAction action, const QueueData& in_ return false; } } break; - case (QueueAction::CREATE_MAIN_VIEW): { + case (QueueAction::CREATE_GRAPH_ENTRY): { } break; - case (QueueAction::REMOVE_MAIN_VIEW): { + case (QueueAction::REMOVE_GRAPH_ENTRY): { } break; default: { megamol::core::utility::log::Log::DefaultLog.WriteError( @@ -968,31 +968,37 @@ bool megamol::gui::Graph::StateFromJSON(const nlohmann::json& in_json) { graph_state, {"show_grid"}, &this->present.show_grid); if (megamol::core::utility::get_json_value( - graph_state, {"show_call_names"}, &this->present.show_call_names)) { + graph_state, {"show_call_label"}, &this->present.show_call_label)) { for (auto& call : this->GetCalls()) { - call->present.label_visible = this->present.show_call_names; + call->present.label_visible = this->present.show_call_label; } } if (megamol::core::utility::get_json_value( - graph_state, {"show_module_names"}, &this->present.show_module_names)) { + graph_state, {"show_call_slots_label"}, &this->present.show_call_slots_label)) { + for (auto& call : this->GetCalls()) { + call->present.slots_visible = this->present.show_call_slots_label; + } + } + if (megamol::core::utility::get_json_value( + graph_state, {"show_module_label"}, &this->present.show_module_label)) { for (auto& mod : this->GetModules()) { - mod->present.label_visible = this->present.show_module_names; + mod->present.label_visible = this->present.show_module_label; } } if (megamol::core::utility::get_json_value( - graph_state, {"show_slot_names"}, &this->present.show_slot_names)) { + graph_state, {"show_slot_label"}, &this->present.show_slot_label)) { for (auto& mod : this->GetModules()) { for (auto& callslot_types : mod->GetCallSlots()) { for (auto& callslots : callslot_types.second) { - callslots->present.label_visible = this->present.show_slot_names; + callslots->present.label_visible = this->present.show_slot_label; } } } for (auto& group_ptr : this->GetGroups()) { for (auto& interfaceslots_map : group_ptr->GetInterfaceSlots()) { for (auto& interfaceslot_ptr : interfaceslots_map.second) { - interfaceslot_ptr->present.label_visible = this->present.show_slot_names; + interfaceslot_ptr->present.label_visible = this->present.show_slot_label; } } } @@ -1167,9 +1173,11 @@ bool megamol::gui::Graph::StateToJSON(nlohmann::json& inout_json) { inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["parameter_sidebar_width"] = this->present.parameter_sidebar_width; inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_grid"] = this->present.show_grid; - inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_call_names"] = this->present.show_call_names; - inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_slot_names"] = this->present.show_slot_names; - inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_module_names"] = this->present.show_module_names; + inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_call_label"] = this->present.show_call_label; + inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_call_slots_label"] = + this->present.show_call_slots_label; + inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_slot_label"] = this->present.show_slot_label; + inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["show_module_label"] = this->present.show_module_label; inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["params_visible"] = this->present.params_visible; inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["params_readonly"] = this->present.params_readonly; inout_json[GUI_JSON_TAG_GRAPHS][GUI_JSON_TAG_PROJECT]["param_extended_mode"] = @@ -1254,13 +1262,13 @@ const std::string megamol::gui::Graph::generate_unique_module_name(const std::st } -const std::string megamol::gui::Graph::GenerateUniqueMainViewName(void) { +const std::string megamol::gui::Graph::GenerateUniqueGraphEntryName(void) { int new_name_id = 0; - std::string new_name_prefix("MainView_"); + std::string new_name_prefix("GraphEntry_"); for (auto& module_ptr : this->modules) { - if (module_ptr->main_view_name.find(new_name_prefix) == 0) { - std::string int_postfix = module_ptr->main_view_name.substr(new_name_prefix.length()); + if (module_ptr->graph_entry_name.find(new_name_prefix) == 0) { + std::string int_postfix = module_ptr->graph_entry_name.substr(new_name_prefix.length()); try { int last_id = std::stoi(int_postfix); new_name_id = std::max(new_name_id, last_id); diff --git a/plugins/gui/src/graph/Graph.h b/plugins/gui/src/graph/Graph.h index 0b3dda4d1a..20f0ce9799 100644 --- a/plugins/gui/src/graph/Graph.h +++ b/plugins/gui/src/graph/Graph.h @@ -45,8 +45,8 @@ namespace gui { RENAME_MODULE, ADD_CALL, DELETE_CALL, - CREATE_MAIN_VIEW, - REMOVE_MAIN_VIEW + CREATE_GRAPH_ENTRY, + REMOVE_GRAPH_ENTRY }; struct QueueData { @@ -130,7 +130,7 @@ namespace gui { return (this->graph_core_interface != GraphCoreInterface::NO_INTERFACE); } - const std::string GenerateUniqueMainViewName(void); + const std::string GenerateUniqueGraphEntryName(void); bool StateFromJSON(const nlohmann::json& in_json); bool StateToJSON(nlohmann::json& inout_json); diff --git a/plugins/gui/src/graph/GraphCollection.cpp b/plugins/gui/src/graph/GraphCollection.cpp index 551cbf75a0..bea8f0e32c 100644 --- a/plugins/gui/src/graph/GraphCollection.cpp +++ b/plugins/gui/src/graph/GraphCollection.cpp @@ -383,7 +383,7 @@ bool megamol::gui::GraphCollection::AddUpdateProjectFromCore(ImGuiID in_graph_ui if (!graph_ptr->ModuleExists(module_fullname)) { add_module_list.emplace_back(module_inst.modulePtr.get()); if (module_inst.isGraphEntryPoint) { - new_view_instances[module_fullname] = graph_ptr->GenerateUniqueMainViewName(); + new_view_instances[module_fullname] = graph_ptr->GenerateUniqueGraphEntryName(); } } } @@ -466,19 +466,19 @@ bool megamol::gui::GraphCollection::AddUpdateProjectFromCore(ImGuiID in_graph_ui // Check if module is view instance auto view_inst_iter = new_view_instances.find(full_name); if (view_inst_iter != new_view_instances.end()) { - new_module_ptr->main_view_name = view_inst_iter->second; + new_module_ptr->graph_entry_name = view_inst_iter->second; Graph::QueueData queue_data; - // Remove all main views + // Remove all graph entries // for (auto module_ptr : graph_ptr->GetModules()) { - // if (module_ptr->is_view && module_ptr->IsMainView()) { - // module_ptr->main_view_name.clear(); + // if (module_ptr->is_view && module_ptr->IsGraphEntry()) { + // module_ptr->graph_entry_name.clear(); // queue_data.name_id = module_ptr->FullName(); - // graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + // graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_graph_entry, queue_data); // } //} - // Add new main view + // Add new graph entry queue_data.name_id = new_module_ptr->FullName(); - graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_MAIN_VIEW, queue_data); + graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_GRAPH_ENTRY, queue_data); } // Add module to group graph_ptr->AddGroupModule(module_namespace, new_module_ptr); @@ -845,26 +845,26 @@ ImGuiID megamol::gui::GraphCollection::LoadAddProjectFromFile( graph_ptr->UniqueModuleRename(view_name); graph_module->name = view_name; graph_ptr->AddGroupModule(view_namespace, graph_module); - graph_module->main_view_name = view_instance; + graph_module->graph_entry_name = view_instance; queue_data.rename_id = graph_module->FullName(); graph_ptr->PushSyncQueue(Graph::QueueAction::RENAME_MODULE, queue_data); - // Remove all main views + // Remove all graph entries // for (auto module_ptr : graph_ptr->GetModules()) { - // if (module_ptr->is_view && module_ptr->IsMainView()) { - // module_ptr->main_view_name.clear(); + // if (module_ptr->is_view && module_ptr->IsGraphEntry()) { + // module_ptr->graph_entry_name.clear(); // queue_data.name_id = module_ptr->FullName(); - // graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + // graph_ptr->PushSyncQueue(Graph::QueueAction::REMOVE_graph_entry, queue_data); // } //} - // Add new main view + // Add new graph entry queue_data.name_id = queue_data.rename_id; - graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_MAIN_VIEW, queue_data); + graph_ptr->PushSyncQueue(Graph::QueueAction::CREATE_GRAPH_ENTRY, queue_data); - // Allow only one main view at a time - /// XXX TODO reset other main views + // Allow only one graph entry at a time + /// XXX TODO reset other graph entry } } @@ -1194,8 +1194,8 @@ bool megamol::gui::GraphCollection::SaveProjectToFile( std::string projectstr; std::stringstream confInstances, confModules, confCalls, confParams, confGUIState; for (auto& module_ptr : graph_ptr->GetModules()) { - if (module_ptr->IsMainView()) { - confInstances << "mmCreateView(\"" << module_ptr->main_view_name << "\",\"" + if (module_ptr->IsGraphEntry()) { + confInstances << "mmCreateView(\"" << module_ptr->graph_entry_name << "\",\"" << module_ptr->class_name << "\",\"" << module_ptr->FullName() << "\") \n"; } else { confModules << "mmCreateModule(\"" << module_ptr->class_name << "\",\"" diff --git a/plugins/gui/src/graph/GraphCollectionPresentation.cpp b/plugins/gui/src/graph/GraphCollectionPresentation.cpp index c555fd0653..9b3c545ee2 100644 --- a/plugins/gui/src/graph/GraphCollectionPresentation.cpp +++ b/plugins/gui/src/graph/GraphCollectionPresentation.cpp @@ -78,12 +78,13 @@ void megamol::gui::GraphCollectionPresentation::Present( project_filename = graph_ptr->GetFilename(); } } - bool check_option = false; // Default for option asking for saving gui state + vislib::math::Ternary save_gui_state( + vislib::math::Ternary::TRI_FALSE); // Default for option asking for saving gui state if (this->file_browser.PopUp(project_filename, FileBrowserWidget::FileBrowserFlag::SAVE, "Save Project", - state.configurator_graph_save, "lua", "Save GUI State?", check_option)) { + state.configurator_graph_save, "lua", save_gui_state)) { std::string gui_state; - if (check_option) { + if (save_gui_state.IsTrue()) { gui_state = inout_graph_collection.GetUpdatedGUIState(state.graph_selected_uid, project_filename); } diff --git a/plugins/gui/src/graph/GraphPresentation.cpp b/plugins/gui/src/graph/GraphPresentation.cpp index e28d262aa3..68d2b19080 100644 --- a/plugins/gui/src/graph/GraphPresentation.cpp +++ b/plugins/gui/src/graph/GraphPresentation.cpp @@ -30,9 +30,10 @@ megamol::gui::GraphPresentation::GraphPresentation(void) , param_extended_mode(false) , update(true) , show_grid(false) - , show_call_names(true) - , show_slot_names(false) - , show_module_names(true) + , show_call_label(true) + , show_call_slots_label(false) + , show_slot_label(false) + , show_module_label(true) , show_parameter_sidebar(true) , change_show_parameter_sidebar(true) , graph_layout(0) @@ -41,13 +42,12 @@ megamol::gui::GraphPresentation::GraphPresentation(void) , increment_zooming(false) , decrement_zooming(false) , param_name_space() - , current_main_view_name() + , current_graph_entry_name() , multiselect_start_pos() , multiselect_end_pos() , multiselect_done(false) , canvas_hovered(false) , current_font_scaling(1.0f) - , add_menu_scrollbar_height(false) , graph_state() , search_widget() , splitter_widget() @@ -74,7 +74,7 @@ megamol::gui::GraphPresentation::GraphPresentation(void) this->graph_state.interact.modules_remove_group_uids.clear(); this->graph_state.interact.modules_layout = false; this->graph_state.interact.module_rename.clear(); - this->graph_state.interact.module_mainview_changed = vislib::math::Ternary::TRI_UNKNOWN; + this->graph_state.interact.module_graphentry_changed = vislib::math::Ternary::TRI_UNKNOWN; this->graph_state.interact.module_param_child_position = ImVec2(-1.0f, -1.0f); this->graph_state.interact.call_selected_uid = GUI_INVALID_ID; @@ -291,8 +291,8 @@ void megamol::gui::GraphPresentation::Present(megamol::gui::Graph& inout_graph, } this->graph_state.interact.module_rename.clear(); } - // Add module main view event to graph synchronization queue ---------- - if (this->graph_state.interact.module_mainview_changed != vislib::math::Ternary::TRI_UNKNOWN) { + // Add module graph entry event to graph synchronization queue ---------- + if (this->graph_state.interact.module_graphentry_changed != vislib::math::Ternary::TRI_UNKNOWN) { // Choose single selected view module ModulePtr_t selected_mod_ptr; if (this->graph_state.interact.modules_selected_uids.size() == 1) { @@ -304,26 +304,26 @@ void megamol::gui::GraphPresentation::Present(megamol::gui::Graph& inout_graph, } if (selected_mod_ptr != nullptr) { Graph::QueueData queue_data; - if (this->graph_state.interact.module_mainview_changed == vislib::math::Ternary::TRI_TRUE) { - // Remove all main views + if (this->graph_state.interact.module_graphentry_changed == vislib::math::Ternary::TRI_TRUE) { + // Remove all graph entries for (auto module_ptr : inout_graph.GetModules()) { - if (module_ptr->is_view && module_ptr->IsMainView()) { - module_ptr->main_view_name.clear(); + if (module_ptr->is_view && module_ptr->IsGraphEntry()) { + module_ptr->graph_entry_name.clear(); queue_data.name_id = module_ptr->FullName(); - inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_GRAPH_ENTRY, queue_data); } } - // Add new main view + // Add new graph entry queue_data.name_id = selected_mod_ptr->FullName(); - selected_mod_ptr->main_view_name = inout_graph.GenerateUniqueMainViewName(); - inout_graph.PushSyncQueue(Graph::QueueAction::CREATE_MAIN_VIEW, queue_data); + selected_mod_ptr->graph_entry_name = inout_graph.GenerateUniqueGraphEntryName(); + inout_graph.PushSyncQueue(Graph::QueueAction::CREATE_GRAPH_ENTRY, queue_data); } else { queue_data.name_id = selected_mod_ptr->FullName(); - selected_mod_ptr->main_view_name.clear(); - inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + selected_mod_ptr->graph_entry_name.clear(); + inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_GRAPH_ENTRY, queue_data); } } - this->graph_state.interact.module_mainview_changed = vislib::math::Ternary::TRI_UNKNOWN; + this->graph_state.interact.module_graphentry_changed = vislib::math::Ternary::TRI_UNKNOWN; } // Add module to group ------------------------------------------------ if (!this->graph_state.interact.modules_add_group_uids.empty()) { @@ -739,16 +739,79 @@ void megamol::gui::GraphPresentation::Present(megamol::gui::Graph& inout_graph, void megamol::gui::GraphPresentation::present_menu(megamol::gui::Graph& inout_graph) { ImGuiStyle& style = ImGui::GetStyle(); - const std::string delimiter("|"); + auto button_size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()); float child_height = ImGui::GetFrameHeightWithSpacing(); - if (this->add_menu_scrollbar_height) { - child_height += static_cast(ImGuiStyleVar_ScrollbarSize) + - (style.ItemInnerSpacing.y * megamol::gui::gui_scaling.Get()); // why? - } - auto child_flags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NavFlattened | ImGuiWindowFlags_HorizontalScrollbar; + auto child_flags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NavFlattened | ImGuiWindowFlags_MenuBar; ImGui::BeginChild("graph_menu", ImVec2(0.0f, child_height), false, child_flags); - float content_region_avail_x = ImGui::GetContentRegionAvail().x; + + ImGui::BeginMenuBar(); + + // GRAPH LAYOUT + if (ImGui::Button("Layout Graph")) { + this->graph_layout = 1; + } + ImGui::Separator(); + + // MODULES + if (ImGui::BeginMenu("Modules")) { + if (ImGui::MenuItem("Label", nullptr, &this->show_module_label)) { + for (auto& module_ptr : inout_graph.GetModules()) { + module_ptr->present.label_visible = this->show_module_label; + } + this->update = true; + } + ImGui::EndMenu(); + } + ImGui::Separator(); + + // CALLS + if (ImGui::BeginMenu("Calls")) { + if (ImGui::MenuItem("Label", nullptr, &this->show_call_label)) { + for (auto& call_ptr : inout_graph.GetCalls()) { + call_ptr->present.label_visible = this->show_call_label; + } + this->update = true; + } + if (ImGui::MenuItem("Slots", nullptr, &this->show_call_slots_label)) { + for (auto& call_ptr : inout_graph.GetCalls()) { + call_ptr->present.slots_visible = this->show_call_slots_label; + } + this->update = true; + } + ImGui::EndMenu(); + } + ImGui::Separator(); + + // SLOTS + if (ImGui::BeginMenu("Slots")) { + if (ImGui::MenuItem("Label", nullptr, &this->show_slot_label)) { + for (auto& module_ptr : inout_graph.GetModules()) { + for (auto& callslot_types : module_ptr->GetCallSlots()) { + for (auto& callslots : callslot_types.second) { + callslots->present.label_visible = this->show_slot_label; + } + } + } + for (auto& group_ptr : inout_graph.GetGroups()) { + for (auto& interfaceslots_map : group_ptr->GetInterfaceSlots()) { + for (auto& interfaceslot_ptr : interfaceslots_map.second) { + interfaceslot_ptr->present.label_visible = this->show_slot_label; + } + } + } + this->update = true; + } + ImGui::EndMenu(); + } + ImGui::Separator(); + + // GRID + if (ImGui::BeginMenu("Grid")) { + ImGui::MenuItem("Show/Hide", nullptr, &this->show_grid); + ImGui::EndMenu(); + } + ImGui::Separator(); // Choose single selected view module ModulePtr_t selected_mod_ptr; @@ -759,181 +822,114 @@ void megamol::gui::GraphPresentation::present_menu(megamol::gui::Graph& inout_gr } } } - // Main View Checkbox + // Graph Entry Checkbox const float min_text_width = 3.0f * ImGui::GetFrameHeightWithSpacing(); if (selected_mod_ptr == nullptr) { GUIUtils::ReadOnlyWigetStyle(true); - bool is_main_view = false; - this->current_main_view_name.clear(); - ImGui::Checkbox("Main View", &is_main_view); - ImGui::SameLine(0.0f, min_text_width + 2.0f * style.ItemSpacing.x); + bool is_graph_entry = false; + this->current_graph_entry_name.clear(); + ImGui::Checkbox("Graph Entry", &is_graph_entry); + // ImGui::SameLine(0.0f, min_text_width + 2.0f * style.ItemSpacing.x); GUIUtils::ReadOnlyWigetStyle(false); } else { - bool is_main_view = selected_mod_ptr->IsMainView(); - if (ImGui::Checkbox("Main View", &is_main_view)) { + bool is_graph_entry = selected_mod_ptr->IsGraphEntry(); + if (ImGui::Checkbox("Graph Entry", &is_graph_entry)) { if (inout_graph.GetCoreInterface() == GraphCoreInterface::CORE_INSTANCE_GRAPH) { megamol::core::utility::log::Log::DefaultLog.WriteWarn( - "[GUI] The action [Change Main View] is not yet supported for the graph " + "[GUI] The action [Change Graph Entry] is not yet supported for the graph " "using the 'Core Instance Graph' interface. Open project from file to make desired " "changes. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__); } else { Graph::QueueData queue_data; - if (is_main_view) { - // Remove all main views + if (is_graph_entry) { + // Remove all graph entries for (auto module_ptr : inout_graph.GetModules()) { - if (module_ptr->is_view && module_ptr->IsMainView()) { - module_ptr->main_view_name.clear(); + if (module_ptr->is_view && module_ptr->IsGraphEntry()) { + module_ptr->graph_entry_name.clear(); queue_data.name_id = module_ptr->FullName(); - inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_GRAPH_ENTRY, queue_data); } } - // Add new main view - selected_mod_ptr->main_view_name = inout_graph.GenerateUniqueMainViewName(); + // Add new graph entry + selected_mod_ptr->graph_entry_name = inout_graph.GenerateUniqueGraphEntryName(); queue_data.name_id = selected_mod_ptr->FullName(); - inout_graph.PushSyncQueue(Graph::QueueAction::CREATE_MAIN_VIEW, queue_data); + inout_graph.PushSyncQueue(Graph::QueueAction::CREATE_GRAPH_ENTRY, queue_data); } else { - selected_mod_ptr->main_view_name.clear(); + selected_mod_ptr->graph_entry_name.clear(); queue_data.name_id = selected_mod_ptr->FullName(); - inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_MAIN_VIEW, queue_data); + inout_graph.PushSyncQueue(Graph::QueueAction::REMOVE_GRAPH_ENTRY, queue_data); } } } - ImGui::SameLine(); - this->current_main_view_name = selected_mod_ptr->main_view_name; - float input_text_width = std::max( - min_text_width, (ImGui::CalcTextSize(this->current_main_view_name.c_str()).x + 2.0f * style.ItemSpacing.x)); + + this->current_graph_entry_name = selected_mod_ptr->graph_entry_name; + float input_text_width = std::max(min_text_width, + (ImGui::CalcTextSize(this->current_graph_entry_name.c_str()).x + 2.0f * style.ItemSpacing.x)); ImGui::PushItemWidth(input_text_width); - GUIUtils::Utf8Encode(this->current_main_view_name); - ImGui::InputText("###current_main_view_name", &this->current_main_view_name, ImGuiInputTextFlags_None); - GUIUtils::Utf8Decode(this->current_main_view_name); + GUIUtils::Utf8Encode(this->current_graph_entry_name); + ImGui::InputText("###current_graph_entry_name", &this->current_graph_entry_name, ImGuiInputTextFlags_None); + GUIUtils::Utf8Decode(this->current_graph_entry_name); if (ImGui::IsItemDeactivatedAfterEdit()) { if (inout_graph.GetCoreInterface() == GraphCoreInterface::CORE_INSTANCE_GRAPH) { megamol::core::utility::log::Log::DefaultLog.WriteWarn( - "[GUI] The action [Change Main View] is not yet supported for the graph " + "[GUI] The action [Change Graph Entry] is not yet supported for the graph " "using the 'Core Instance Graph' interface. Open project from file to make desired " "changes. [%s, %s, line %d]\n", __FILE__, __FUNCTION__, __LINE__); } else { - selected_mod_ptr->main_view_name = this->current_main_view_name; + selected_mod_ptr->graph_entry_name = this->current_graph_entry_name; } } else { - this->current_main_view_name = selected_mod_ptr->main_view_name; + this->current_graph_entry_name = selected_mod_ptr->graph_entry_name; } ImGui::PopItemWidth(); - ImGui::SameLine(); } - ImGui::TextUnformatted(delimiter.c_str()); - ImGui::SameLine(); - - auto button_size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()); + ImGui::Separator(); + // SCROLLING const float scroll_fac = 10.0f; ImGui::Text("Scrolling: %.2f, %.2f", this->graph_state.canvas.scrolling.x, this->graph_state.canvas.scrolling.y); - ImGui::SameLine(); ImGui::TextUnformatted("H:"); - ImGui::SameLine(); if (ImGui::Button("+###hor_incr_scrolling", button_size)) { this->graph_state.canvas.scrolling.x += scroll_fac; this->update = true; } - ImGui::SameLine(); if (ImGui::Button("-###hor_decr_scrolling", button_size)) { this->graph_state.canvas.scrolling.x -= scroll_fac; this->update = true; } - ImGui::SameLine(); ImGui::TextUnformatted("V:"); - ImGui::SameLine(); if (ImGui::Button("+###vert_incr_scrolling", button_size)) { this->graph_state.canvas.scrolling.y += scroll_fac; this->update = true; } - ImGui::SameLine(); if (ImGui::Button("-###vert_decr_scrolling", button_size)) { this->graph_state.canvas.scrolling.y -= scroll_fac; this->update = true; } - ImGui::SameLine(); if (ImGui::Button("Reset###reset_scrolling")) { this->graph_state.canvas.scrolling = ImVec2(0.0f, 0.0f); this->update = true; } - ImGui::SameLine(); this->tooltip.Marker("Middle Mouse Button"); - ImGui::SameLine(); - ImGui::TextUnformatted(delimiter.c_str()); - ImGui::SameLine(); + ImGui::Separator(); + // ZOOMING ImGui::Text("Zooming: %.2f", this->graph_state.canvas.zooming); - ImGui::SameLine(); if (ImGui::Button("+###incr_zooming", button_size)) { this->increment_zooming = true; } - ImGui::SameLine(); if (ImGui::Button("-###decr_zooming", button_size)) { this->decrement_zooming = true; } - ImGui::SameLine(); if (ImGui::Button("Reset###reset_zooming")) { this->reset_zooming = true; } - ImGui::SameLine(); this->tooltip.Marker("Mouse Wheel"); - ImGui::SameLine(); - ImGui::TextUnformatted(delimiter.c_str()); - ImGui::SameLine(); - - ImGui::Checkbox("Grid", &this->show_grid); - - ImGui::SameLine(); - - if (ImGui::Checkbox("Call Names", &this->show_call_names)) { - for (auto& call_ptr : inout_graph.GetCalls()) { - call_ptr->present.label_visible = this->show_call_names; - } - this->update = true; - } - ImGui::SameLine(); - - if (ImGui::Checkbox("Module Names", &this->show_module_names)) { - for (auto& module_ptr : inout_graph.GetModules()) { - module_ptr->present.label_visible = this->show_module_names; - } - this->update = true; - } - ImGui::SameLine(); - - if (ImGui::Checkbox("Slot Names", &this->show_slot_names)) { - for (auto& module_ptr : inout_graph.GetModules()) { - for (auto& callslot_types : module_ptr->GetCallSlots()) { - for (auto& callslots : callslot_types.second) { - callslots->present.label_visible = this->show_slot_names; - } - } - } - for (auto& group_ptr : inout_graph.GetGroups()) { - for (auto& interfaceslots_map : group_ptr->GetInterfaceSlots()) { - for (auto& interfaceslot_ptr : interfaceslots_map.second) { - interfaceslot_ptr->present.label_visible = this->show_slot_names; - } - } - } - this->update = true; - } - ImGui::SameLine(); - - if (ImGui::Button("Layout Graph")) { - this->graph_layout = 1; - } + ImGui::Separator(); - // -------------------------------------------------- - ImGui::SameLine(); - float cursor_pos_x = ImGui::GetCursorPosX() - style.ItemSpacing.x; - this->add_menu_scrollbar_height = false; - if (content_region_avail_x < cursor_pos_x) { - this->add_menu_scrollbar_height = true; - } + ImGui::EndMenuBar(); ImGui::EndChild(); } @@ -1666,7 +1662,7 @@ void megamol::gui::GraphPresentation::layout( size_t layer_count = layers.size(); for (size_t i = 0; i < layer_count; i++) { - if (this->show_call_names) { + if (this->show_call_label || this->show_call_slots_label) { max_call_width = 0.0f; } max_graph_element_width = 0.0f; @@ -1678,7 +1674,7 @@ void megamol::gui::GraphPresentation::layout( auto layer_item = layers[i][j]; if (layer_item.module_ptr != nullptr) { - if (this->show_call_names) { + if (this->show_call_label) { for (auto& callerslot_ptr : layer_item.module_ptr->GetCallSlots(CallSlotType::CALLER)) { if (callerslot_ptr->CallsConnected() && this->connected_callslot(modules, groups, callerslot_ptr)) { @@ -1689,6 +1685,17 @@ void megamol::gui::GraphPresentation::layout( } } } + if (this->show_call_slots_label) { + for (auto& callerslot_ptr : layer_item.module_ptr->GetCallSlots(CallSlotType::CALLER)) { + if (callerslot_ptr->CallsConnected() && + this->connected_callslot(modules, groups, callerslot_ptr)) { + for (auto& call_ptr : callerslot_ptr->GetConnectedCalls()) { + auto call_name_length = ImGui::CalcTextSize(call_ptr->GetSlotsLabel().c_str()).x; + max_call_width = std::max(call_name_length, max_call_width); + } + } + } + } layer_item.module_ptr->present.position = pos; auto module_size = layer_item.module_ptr->present.GetSize(); pos.y += (module_size.y + GUI_GRAPH_BORDER); @@ -1696,7 +1703,7 @@ void megamol::gui::GraphPresentation::layout( found_layer_item = true; } else if (layer_item.group_ptr != nullptr) { - if (this->show_call_names) { + if (this->show_call_label) { for (auto& interfaceslot_slot : layer_item.group_ptr->GetInterfaceSlots(CallSlotType::CALLER)) { for (auto& callerslot_ptr : interfaceslot_slot->GetCallSlots()) { if (callerslot_ptr->CallsConnected() && @@ -1709,6 +1716,19 @@ void megamol::gui::GraphPresentation::layout( } } } + if (this->show_call_slots_label) { + for (auto& interfaceslot_slot : layer_item.group_ptr->GetInterfaceSlots(CallSlotType::CALLER)) { + for (auto& callerslot_ptr : interfaceslot_slot->GetCallSlots()) { + if (callerslot_ptr->CallsConnected() && + this->connected_callslot(modules, groups, callerslot_ptr)) { + for (auto& call_ptr : callerslot_ptr->GetConnectedCalls()) { + auto call_name_length = ImGui::CalcTextSize(call_ptr->GetSlotsLabel().c_str()).x; + max_call_width = std::max(call_name_length, max_call_width); + } + } + } + } + } layer_item.group_ptr->SetGUIPosition(this->graph_state.canvas, pos); auto group_size = layer_item.group_ptr->present.GetSize(); pos.y += (group_size.y + GUI_GRAPH_BORDER); diff --git a/plugins/gui/src/graph/GraphPresentation.h b/plugins/gui/src/graph/GraphPresentation.h index 358d6db629..afe0481d0a 100644 --- a/plugins/gui/src/graph/GraphPresentation.h +++ b/plugins/gui/src/graph/GraphPresentation.h @@ -71,13 +71,13 @@ namespace gui { return this->graph_state.interact.slot_dropped_uid; } bool GetModuleLabelVisibility(void) const { - return this->show_module_names; + return this->show_module_label; } bool GetCallSlotLabelVisibility(void) const { - return this->show_slot_names; + return this->show_slot_label; } bool GetCallLabelVisibility(void) const { - return this->show_call_names; + return this->show_call_label; } bool IsCanvasHoverd(void) const { return this->canvas_hovered; @@ -92,9 +92,10 @@ namespace gui { bool update; bool show_grid; - bool show_call_names; - bool show_slot_names; - bool show_module_names; + bool show_call_label; + bool show_call_slots_label; + bool show_slot_label; + bool show_module_label; bool show_parameter_sidebar; bool change_show_parameter_sidebar; unsigned int graph_layout; @@ -103,13 +104,12 @@ namespace gui { bool increment_zooming; bool decrement_zooming; std::string param_name_space; - std::string current_main_view_name; + std::string current_graph_entry_name; ImVec2 multiselect_start_pos; ImVec2 multiselect_end_pos; bool multiselect_done; bool canvas_hovered; float current_font_scaling; - bool add_menu_scrollbar_height; // State propagated and shared by all graph items. megamol::gui::GraphItemsState_t graph_state; diff --git a/plugins/gui/src/graph/Module.cpp b/plugins/gui/src/graph/Module.cpp index b009473023..298af099cb 100644 --- a/plugins/gui/src/graph/Module.cpp +++ b/plugins/gui/src/graph/Module.cpp @@ -26,7 +26,7 @@ megamol::gui::Module::Module(ImGuiID uid) , is_view(false) , parameters() , name() - , main_view_name() + , graph_entry_name() , callslots() { this->callslots.emplace(megamol::gui::CallSlotType::CALLER, std::vector()); diff --git a/plugins/gui/src/graph/Module.h b/plugins/gui/src/graph/Module.h index bce50f2a4b..5a9708b908 100644 --- a/plugins/gui/src/graph/Module.h +++ b/plugins/gui/src/graph/Module.h @@ -58,7 +58,7 @@ namespace gui { // Init when adding module to graph std::string name; - std::string main_view_name; + std::string graph_entry_name; // FUNCTIONS -------------------------------------------------------------- @@ -75,8 +75,8 @@ namespace gui { return this->callslots; } - bool IsMainView(void) { - return (!this->main_view_name.empty()); + bool IsGraphEntry(void) { + return (!this->graph_entry_name.empty()); } const inline std::string FullName(void) const { diff --git a/plugins/gui/src/graph/ModulePresentation.cpp b/plugins/gui/src/graph/ModulePresentation.cpp index 0d89179bd7..82db9418cf 100644 --- a/plugins/gui/src/graph/ModulePresentation.cpp +++ b/plugins/gui/src/graph/ModulePresentation.cpp @@ -346,11 +346,11 @@ void megamol::gui::ModulePresentation::Present( ImVec2 text_pos_left_upper; const float line_height = ImGui::GetTextLineHeightWithSpacing(); bool other_item_hovered = false; + bool graph_entry_button = inout_module.is_view; + bool parameter_button = (inout_module.parameters.size() > 0); + bool any_option_button = (graph_entry_button || parameter_button); if (this->label_visible) { - bool main_view_button = inout_module.is_view; - bool parameter_button = (inout_module.parameters.size() > 0); - bool any_option_button = (main_view_button || parameter_button); auto header_color = (this->selected) ? (COLOR_HEADER_HIGHLIGHT) : (COLOR_HEADER); ImVec2 header_rect_max = @@ -368,80 +368,82 @@ void megamol::gui::ModulePresentation::Present( module_center - ImVec2((text_width / 2.0f), ((any_option_button) ? (line_height * 0.6f) : (0.0f))); draw_list->AddText(text_pos_left_upper, COLOR_TEXT, inout_module.name.c_str()); + } - if (any_option_button) { - float item_y_offset = (line_height / 2.0f); - float item_x_offset = (ImGui::GetFrameHeight() / 2.0f); - if (main_view_button && parameter_button) { - item_x_offset = - ImGui::GetFrameHeight() + (0.5f * style.ItemSpacing.x * state.canvas.zooming); - } - ImGui::SetCursorScreenPos(module_center + ImVec2(-item_x_offset, item_y_offset)); - - if (main_view_button) { - bool is_main_view = inout_module.IsMainView(); - if (ImGui::RadioButton("###main_view_switch", is_main_view)) { - if (state.interact.graph_core_interface == - GraphCoreInterface::CORE_INSTANCE_GRAPH) { - megamol::core::utility::log::Log::DefaultLog.WriteWarn( - "[GUI] The action [Change Main View] is not yet supported for the graph " - "using the 'Core Instance Graph' interface. Open project from file to make " - "desired changes. [%s, %s, line %d]\n", - __FILE__, __FUNCTION__, __LINE__); + if (any_option_button) { + float item_y_offset = (line_height / 2.0f); + float item_x_offset = (ImGui::GetFrameHeight() / 2.0f); + if (!this->label_visible) { + item_y_offset = -(line_height / 2.0f); + } + if (graph_entry_button && parameter_button) { + item_x_offset = + ImGui::GetFrameHeight() + (0.5f * style.ItemSpacing.x * state.canvas.zooming); + } + ImGui::SetCursorScreenPos(module_center + ImVec2(-item_x_offset, item_y_offset)); + + if (graph_entry_button) { + bool is_graph_entry = inout_module.IsGraphEntry(); + if (ImGui::RadioButton("###graph_entry_switch", is_graph_entry)) { + if (state.interact.graph_core_interface == GraphCoreInterface::CORE_INSTANCE_GRAPH) { + megamol::core::utility::log::Log::DefaultLog.WriteWarn( + "[GUI] The action [Change Graph Entry] is not yet supported for the graph " + "using the 'Core Instance Graph' interface. Open project from file to make " + "desired changes. [%s, %s, line %d]\n", + __FILE__, __FUNCTION__, __LINE__); + } else { + if (!is_graph_entry) { + state.interact.module_graphentry_changed = vislib::math::Ternary::TRI_TRUE; } else { - if (!is_main_view) { - state.interact.module_mainview_changed = vislib::math::Ternary::TRI_TRUE; - } else { - state.interact.module_mainview_changed = vislib::math::Ternary::TRI_FALSE; - } + state.interact.module_graphentry_changed = vislib::math::Ternary::TRI_FALSE; } } - ImGui::SetItemAllowOverlap(); - if (hovered) { - std::string tooltip_label; - if (is_main_view) { - tooltip_label = - tooltip_label + "Main View '" + inout_module.main_view_name + "'"; - } else { - tooltip_label = "No Main View"; - } - other_item_hovered = other_item_hovered || this->tooltip.ToolTip(tooltip_label); + } + ImGui::SetItemAllowOverlap(); + if (hovered) { + std::string tooltip_label; + if (is_graph_entry) { + tooltip_label = + tooltip_label + "Graph Entry '" + inout_module.graph_entry_name + "'"; + } else { + tooltip_label = "No Graph Entry"; } - ImGui::SameLine(0.0f, style.ItemSpacing.x * state.canvas.zooming); + other_item_hovered = other_item_hovered || this->tooltip.ToolTip(tooltip_label); } + ImGui::SameLine(0.0f, style.ItemSpacing.x * state.canvas.zooming); + } - // Param Button - if (parameter_button) { - ImVec2 param_button_pos = ImGui::GetCursorScreenPos(); - if (this->selected) { - this->param_child_show = ((state.interact.module_param_child_position.x > 0.0f) && - (state.interact.module_param_child_position.y > 0.0f)); + // Param Button + if (parameter_button) { + ImVec2 param_button_pos = ImGui::GetCursorScreenPos(); + if (this->selected) { + this->param_child_show = ((state.interact.module_param_child_position.x > 0.0f) && + (state.interact.module_param_child_position.y > 0.0f)); + } else { + this->param_child_show = false; + } + if (ImGui::ArrowButton("###parameter_toggle", + ((this->param_child_show) ? (ImGuiDir_Down) : (ImGuiDir_Up))) && + hovered) { + this->param_child_show = !this->param_child_show; + if (this->param_child_show) { + state.interact.module_param_child_position = param_button_pos; } else { - this->param_child_show = false; - } - if (ImGui::ArrowButton("###parameter_toggle", - ((this->param_child_show) ? (ImGuiDir_Down) : (ImGuiDir_Up))) && - hovered) { - this->param_child_show = !this->param_child_show; - if (this->param_child_show) { - state.interact.module_param_child_position = param_button_pos; - } else { - state.interact.module_param_child_position = ImVec2(-1.0f, -1.0f); - } - } - ImGui::SetItemAllowOverlap(); - if (hovered) { - other_item_hovered |= this->tooltip.ToolTip("Parameters"); + state.interact.module_param_child_position = ImVec2(-1.0f, -1.0f); } } + ImGui::SetItemAllowOverlap(); + if (hovered) { + other_item_hovered |= this->tooltip.ToolTip("Parameters"); + } } - } - // Draw Outline - float border = ((!inout_module.main_view_name.empty()) ? (4.0f) : (1.0f)) * - megamol::gui::gui_scaling.Get() * state.canvas.zooming; - draw_list->AddRect(module_rect_min, module_rect_max, COLOR_MODULE_BORDER, GUI_RECT_CORNER_RADIUS, - ImDrawCornerFlags_All, border); + // Draw Outline + float border = ((!inout_module.graph_entry_name.empty()) ? (4.0f) : (1.0f)) * + megamol::gui::gui_scaling.Get() * state.canvas.zooming; + draw_list->AddRect(module_rect_min, module_rect_max, COLOR_MODULE_BORDER, + GUI_RECT_CORNER_RADIUS, ImDrawCornerFlags_All, border); + } } } @@ -484,10 +486,11 @@ void megamol::gui::ModulePresentation::Update(megamol::gui::Module& inout_module if (this->label_visible) { class_width = ImGui::CalcTextSize(inout_module.class_name.c_str()).x; float name_length = ImGui::CalcTextSize(inout_module.name.c_str()).x; - float button_width = - ((inout_module.is_view) ? (2.0f) : (1.0f)) * ImGui::GetTextLineHeightWithSpacing() + style.ItemSpacing.x; - max_label_length = std::max(name_length, button_width); + max_label_length = name_length; } + float button_width = + ((inout_module.is_view) ? (2.0f) : (1.0f)) * ImGui::GetTextLineHeightWithSpacing() + style.ItemSpacing.x; + max_label_length = std::max(max_label_length, button_width); max_label_length /= in_canvas.zooming; float max_slot_name_length = 0.0f; for (auto& callslots_map : inout_module.GetCallSlots()) { diff --git a/plugins/gui/src/widgets/FileBrowserWidget.cpp b/plugins/gui/src/widgets/FileBrowserWidget.cpp index 3f3a20c69b..028a6bf062 100644 --- a/plugins/gui/src/widgets/FileBrowserWidget.cpp +++ b/plugins/gui/src/widgets/FileBrowserWidget.cpp @@ -25,12 +25,13 @@ megamol::gui::FileBrowserWidget::FileBrowserWidget() , file_warning() , child_paths() , additional_lines(0) - , check_option(false) {} + , save_gui_state(vislib::math::Ternary::TRI_UNKNOWN) + , tooltip() {} bool megamol::gui::FileBrowserWidget::PopUp(std::string& inout_filename, megamol::gui::FileBrowserWidget::FileBrowserFlag flag, const std::string& label, bool open_popup, - const std::string& extension, const std::string& check_option_label, bool& inout_check_option) { + const std::string& extension, vislib::math::Ternary& inout_save_gui_state) { bool retval = false; @@ -51,7 +52,7 @@ bool megamol::gui::FileBrowserWidget::PopUp(std::string& inout_filename, this->search_widget.ClearSearchString(); - this->check_option = inout_check_option; + this->save_gui_state = inout_save_gui_state; ImGui::OpenPopup(label_id.c_str()); // Set initial window size of pop up @@ -94,7 +95,8 @@ bool megamol::gui::FileBrowserWidget::PopUp(std::string& inout_filename, // File browser selectables --------------------------------------- auto select_flags = ImGuiSelectableFlags_DontClosePopups; - float footer_height = ImGui::GetFrameHeightWithSpacing() * ((check_option_label.empty()) ? (2.0f) : (3.0f)); + float footer_height = + ImGui::GetFrameHeightWithSpacing() * ((inout_save_gui_state.IsUnknown()) ? (2.0f) : (3.0f)); float child_select_height = (ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() * this->additional_lines) - footer_height); @@ -229,9 +231,13 @@ bool megamol::gui::FileBrowserWidget::PopUp(std::string& inout_filename, this->validate_file(this->file_name_str, extension, flag); } - // Optional check option ------------ - if (!check_option_label.empty()) { - ImGui::Checkbox(check_option_label.c_str(), &this->check_option); + // Optional save GUI state option ------------ + if (!inout_save_gui_state.IsUnknown()) { + bool check = this->save_gui_state.IsTrue(); + ImGui::Checkbox("Save GUI state", &check); + this->save_gui_state = + ((check) ? (vislib::math::Ternary::TRI_TRUE) : (vislib::math::Ternary::TRI_FALSE)); + this->tooltip.Marker("Check this option to also save all settings affecting the GUI."); } // Buttons -------------------------- @@ -249,7 +255,7 @@ bool megamol::gui::FileBrowserWidget::PopUp(std::string& inout_filename, ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape))) { ImGui::CloseCurrentPopup(); } @@ -273,7 +279,7 @@ bool megamol::gui::FileBrowserWidget::PopUp(std::string& inout_filename, static_cast(this->file_path_str) / static_cast(this->file_name_str); inout_filename = tmp_file_path.generic_u8string(); GUIUtils::Utf8Decode(inout_filename); - inout_check_option = this->check_option; + inout_save_gui_state = this->save_gui_state; ImGui::CloseCurrentPopup(); retval = true; } diff --git a/plugins/gui/src/widgets/FileBrowserWidget.h b/plugins/gui/src/widgets/FileBrowserWidget.h index 545ef3e91e..79dd089b15 100644 --- a/plugins/gui/src/widgets/FileBrowserWidget.h +++ b/plugins/gui/src/widgets/FileBrowserWidget.h @@ -11,6 +11,7 @@ #include "FileUtils.h" #include "GUIUtils.h" +#include "HoverToolTip.h" #include "StringSearchWidget.h" @@ -41,12 +42,12 @@ namespace gui { * @return True on success, false otherwise. */ bool PopUp(std::string& inout_filename, FileBrowserFlag flag, const std::string& label, bool open_popup, - const std::string& extension, const std::string& check_option_label, bool& inout_check_option); + const std::string& extension, vislib::math::Ternary& inout_save_gui_state); bool PopUp(std::string& inout_filename, FileBrowserFlag flag, const std::string& label, bool open_popup, const std::string& extension) { - bool check_option = false; - return this->PopUp(inout_filename, flag, label, open_popup, extension, "", check_option); + vislib::math::Ternary tmp_save_gui_state(vislib::math::Ternary::TRI_UNKNOWN); + return this->PopUp(inout_filename, flag, label, open_popup, extension, tmp_save_gui_state); } /** @@ -75,7 +76,9 @@ namespace gui { // Keeps child path and flag whether child is director or not std::vector child_paths; size_t additional_lines; - bool check_option; + vislib::math::Ternary save_gui_state; + + HoverToolTip tooltip; // FUNCTIONS -------------------------------------------------------------- diff --git a/plugins/gui/src/widgets/MinimalPopUp.cpp b/plugins/gui/src/widgets/MinimalPopUp.cpp index 8fa63c2e48..12661d946b 100644 --- a/plugins/gui/src/widgets/MinimalPopUp.cpp +++ b/plugins/gui/src/widgets/MinimalPopUp.cpp @@ -49,6 +49,9 @@ bool megamol::gui::MinimalPopUp::PopUp(const std::string& label_id, bool open_po ImGui::CloseCurrentPopup(); } } + if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape))) { + ImGui::CloseCurrentPopup(); + } ImGui::EndPopup(); } diff --git a/plugins/gui/src/widgets/ParameterOrbitalWidget.cpp b/plugins/gui/src/widgets/ParameterOrbitalWidget.cpp index f5505fb457..f953387c66 100644 --- a/plugins/gui/src/widgets/ParameterOrbitalWidget.cpp +++ b/plugins/gui/src/widgets/ParameterOrbitalWidget.cpp @@ -14,12 +14,16 @@ using namespace megamol::gui; ParameterOrbitalWidget::ParameterOrbitalWidget(void) - : m_rotation(1.0f, 0.0f, 0.0f, 0.0f), m_direction(0.0f, 0.0f, -1.0f) {} + : m_rotation(1.0f, 0.0f, 0.0f, 0.0f), m_direction(0.0f, 0.0f, 0.0f), init(false) {} bool megamol::gui::ParameterOrbitalWidget::gizmo3D_rotation_axes(glm::vec4& inout_rotation) { bool retval = false; + if (this->init) { + this->m_rotation = ::quat(inout_rotation.w, inout_rotation.x, inout_rotation.y, inout_rotation.z); + this->init = true; + } if (ImGui::gizmo3D("##gizmo_rotation", this->m_rotation, ImGui::CalcItemWidth(), imguiGizmo::mode3Axes | imguiGizmo::cubeAtOrigin | imguiGizmo::sphereAtOrigin)) { @@ -36,6 +40,10 @@ bool megamol::gui::ParameterOrbitalWidget::gizmo3D_rotation_axes(glm::vec4& inou bool megamol::gui::ParameterOrbitalWidget::gizmo3D_rotation_direction(glm::vec3& inout_direction) { bool retval = false; + if (this->init) { + this->m_direction = ::vec3(inout_direction.x, inout_direction.y, inout_direction.z); + this->init = true; + } if (ImGui::gizmo3D("##gizmo_direction", this->m_direction, ImGui::CalcItemWidth(), imguiGizmo::modeDirection)) { inout_direction = glm::vec3(this->m_direction.x, this->m_direction.y, this->m_direction.z); diff --git a/plugins/gui/src/widgets/ParameterOrbitalWidget.h b/plugins/gui/src/widgets/ParameterOrbitalWidget.h index 0633728e4c..27ca104e5f 100644 --- a/plugins/gui/src/widgets/ParameterOrbitalWidget.h +++ b/plugins/gui/src/widgets/ParameterOrbitalWidget.h @@ -34,6 +34,8 @@ namespace gui { private: ::quat m_rotation; ::vec3 m_direction; + + bool init; }; diff --git a/plugins/gui/src/widgets/RenamePopUp.cpp b/plugins/gui/src/widgets/RenamePopUp.cpp index ee9f4e5587..d0de4f4c1f 100644 --- a/plugins/gui/src/widgets/RenamePopUp.cpp +++ b/plugins/gui/src/widgets/RenamePopUp.cpp @@ -54,7 +54,7 @@ bool megamol::gui::RenamePopUp::PopUp(const std::string& label_id, bool open_pop ImGui::CloseCurrentPopup(); } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape))) { ImGui::CloseCurrentPopup(); }