From 181465d2abac3bd2914bb58a2f4d2d4016d25708 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 30 Jun 2024 16:15:47 -0700 Subject: [PATCH] Modern menu support (#639) * Added DrawContents to GuiElement to be callable from GuiElement references (console, stats, etc, from port code). Applied DrawContents to Stats, GfxDebugger and Console windows. * Implement forced cursor visibility. Implement cursor visibility for menu. Implement gamepad menu navigation (toggle in settings, and application to menu). Will need refinement to not rely on menu CVar soon. * Add mMenu and GetMenu() functionality. Includes function for checking if either menu or menubar is open for purposes of gamepad capture and cursor display. No longer relies on CVar from 2ship for functionality. * clang-format * Add cursor visibility restoration to SetMenu. * Started process of abstracting GuiElement Moved Begin and End from DrawElement to Draw in GuiWindow. Moved CVar visibility stuff from Element to Window * Finished abstracting GuiElement. Moved Draw logic, including visibility CVar, to GuiMenuBar and GuiWindow. DrawElements is public for now. Not sure if it will remain that way. Removed all DrawContents references. * clang-format * Move cursor visibility stuff to Gui::Window. Add optional structure for having the gamepad toggle button trigger the menu instead of the menubar. Moved all menu/menubar opening into Gui.cpp (not needed in port anymore). * Update src/window/gui/GuiWindow.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update src/window/gui/GuiWindow.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * tidy --------- Co-authored-by: Kenix3 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/controller/controldeck/ControlDeck.cpp | 4 +- src/graphic/Fast3D/Fast3dWindow.cpp | 5 +- src/window/Window.cpp | 10 ++++ src/window/Window.h | 3 + src/window/gui/ConsoleWindow.cpp | 4 -- src/window/gui/ConsoleWindow.h | 2 +- src/window/gui/GfxDebuggerWindow.cpp | 5 -- src/window/gui/Gui.cpp | 62 +++++++++++++++++--- src/window/gui/Gui.h | 7 +++ src/window/gui/GuiElement.cpp | 44 +------------- src/window/gui/GuiElement.h | 11 +--- src/window/gui/GuiMenuBar.cpp | 47 ++++++++++++++- src/window/gui/GuiMenuBar.h | 11 +++- src/window/gui/GuiWindow.cpp | 68 +++++++++++++++++++++- src/window/gui/GuiWindow.h | 12 +++- src/window/gui/InputEditorWindow.cpp | 2 - src/window/gui/StatsWindow.cpp | 2 - 17 files changed, 218 insertions(+), 81 deletions(-) diff --git a/src/controller/controldeck/ControlDeck.cpp b/src/controller/controldeck/ControlDeck.cpp index 2f097be4b..ae4fa3fce 100644 --- a/src/controller/controldeck/ControlDeck.cpp +++ b/src/controller/controldeck/ControlDeck.cpp @@ -65,8 +65,8 @@ bool ControlDeck::AllGameInputBlocked() { bool ControlDeck::GamepadGameInputBlocked() { // block controller input when using the controller to navigate imgui menus - return AllGameInputBlocked() || - (CVarGetInteger(CVAR_MENU_BAR_OPEN, 0) && CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0)); + return AllGameInputBlocked() || Context::GetInstance()->GetWindow()->GetGui()->GetMenuOrMenubarVisible() && + CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0); } bool ControlDeck::KeyboardGameInputBlocked() { diff --git a/src/graphic/Fast3D/Fast3dWindow.cpp b/src/graphic/Fast3D/Fast3dWindow.cpp index d9ed0aca5..c8073acd3 100644 --- a/src/graphic/Fast3D/Fast3dWindow.cpp +++ b/src/graphic/Fast3D/Fast3dWindow.cpp @@ -74,6 +74,8 @@ void Fast3dWindow::Init() { height = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Height", 480); } + SetForceCursorVisibility(CVarGetInteger("gForceCursorVisibility", 0)); + InitWindowManager(); gfx_init(mWindowManagerApi, mRenderingApi, Ship::Context::GetInstance()->GetName().c_str(), isFullscreen, width, @@ -252,7 +254,8 @@ void Fast3dWindow::OnFullscreenChanged(bool isNowFullscreen) { if (isNowFullscreen) { auto menuBar = wnd->GetGui()->GetMenuBar(); - wnd->SetCursorVisibility(menuBar && menuBar->IsVisible()); + wnd->SetCursorVisibility(menuBar && menuBar->IsVisible() || wnd->ShouldForceCursorVisibility() || + CVarGetInteger("gWindows.Menu", 0)); } else { wnd->SetCursorVisibility(true); } diff --git a/src/window/Window.cpp b/src/window/Window.cpp index 8fc792024..0fafc9027 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -79,6 +79,16 @@ bool Window::IsAvailableWindowBackend(int32_t backendId) { mAvailableWindowBackends->end(); } +bool Window::ShouldForceCursorVisibility() { + return mForceCursorVisibility; +} + +void Window::SetForceCursorVisibility(bool visible) { + mForceCursorVisibility = visible; + CVarSetInteger("gForceCursorVisibility", visible); + CVarSave(); +} + void Window::SetWindowBackend(WindowBackend backend) { mWindowBackend = backend; Context::GetInstance()->GetConfig()->SetWindowBackend(GetWindowBackend()); diff --git a/src/window/Window.h b/src/window/Window.h index 941777d65..364dcb4cc 100644 --- a/src/window/Window.h +++ b/src/window/Window.h @@ -49,6 +49,8 @@ class Window { float GetCurrentAspectRatio(); void SaveWindowToConfig(); std::shared_ptr GetGui(); + bool ShouldForceCursorVisibility(); + void SetForceCursorVisibility(bool visible); protected: void SetWindowBackend(WindowBackend backend); @@ -62,5 +64,6 @@ class Window { // Hold a reference to Config because Window has a Save function called on Context destructor, where the singleton // is no longer available. std::shared_ptr mConfig; + bool mForceCursorVisibility; }; } // namespace Ship diff --git a/src/window/gui/ConsoleWindow.cpp b/src/window/gui/ConsoleWindow.cpp index a4400c1f2..bf43477ed 100644 --- a/src/window/gui/ConsoleWindow.cpp +++ b/src/window/gui/ConsoleWindow.cpp @@ -260,9 +260,6 @@ void ConsoleWindow::UpdateElement() { void ConsoleWindow::DrawElement() { bool inputFocus = false; - - ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); - ImGui::Begin("Console", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing); const ImVec2 pos = ImGui::GetWindowPos(); const ImVec2 size = ImGui::GetWindowSize(); @@ -458,7 +455,6 @@ void ConsoleWindow::DrawElement() { } ImGui::PopItemWidth(); } - ImGui::End(); } void ConsoleWindow::Dispatch(const std::string& line) { diff --git a/src/window/gui/ConsoleWindow.h b/src/window/gui/ConsoleWindow.h index 2dd7814ea..0bf38b999 100644 --- a/src/window/gui/ConsoleWindow.h +++ b/src/window/gui/ConsoleWindow.h @@ -30,12 +30,12 @@ class ConsoleWindow : public GuiWindow { void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...); std::string GetCurrentChannel(); void ClearBindings(); + void DrawElement() override; protected: void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, va_list args); void InitElement() override; void UpdateElement() override; - void DrawElement() override; private: struct ConsoleLine { diff --git a/src/window/gui/GfxDebuggerWindow.cpp b/src/window/gui/GfxDebuggerWindow.cpp index 2c8763f8b..3e98c45f7 100644 --- a/src/window/gui/GfxDebuggerWindow.cpp +++ b/src/window/gui/GfxDebuggerWindow.cpp @@ -408,9 +408,6 @@ void GfxDebuggerWindow::DrawDisas() { void GfxDebuggerWindow::DrawElement() { auto dbg = Ship::Context::GetInstance()->GetGfxDebugger(); - - ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); - ImGui::Begin("GFX Debugger", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing); // const ImVec2 pos = ImGui::GetWindowPos(); // const ImVec2 size = ImGui::GetWindowSize(); @@ -429,8 +426,6 @@ void GfxDebuggerWindow::DrawElement() { DrawDisas(); } } - - ImGui::End(); } } // namespace LUS diff --git a/src/window/gui/Gui.cpp b/src/window/gui/Gui.cpp index c1fb50e7b..3c97b076b 100644 --- a/src/window/gui/Gui.cpp +++ b/src/window/gui/Gui.cpp @@ -83,11 +83,13 @@ Gui::Gui(std::vector> guiWindows) : mNeedsConsoleVari } if (GetGuiWindow("Console") == nullptr) { - AddGuiWindow(std::make_shared(CVAR_CONSOLE_WINDOW_OPEN, "Console")); + AddGuiWindow(std::make_shared(CVAR_CONSOLE_WINDOW_OPEN, "Console", ImVec2(520, 600), + ImGuiWindowFlags_NoFocusOnAppearing)); } if (GetGuiWindow("GfxDebuggerWindow") == nullptr) { - AddGuiWindow(std::make_shared(CVAR_GFX_DEBUGGER_WINDOW_OPEN, "GfxDebuggerWindow")); + AddGuiWindow(std::make_shared(CVAR_GFX_DEBUGGER_WINDOW_OPEN, "GfxDebuggerWindow", + ImVec2(520, 600))); } } @@ -134,7 +136,7 @@ void Gui::Init(GuiWindowInitData windowImpl) { mImGuiIo->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; } - if (CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0) && GetMenuBar() && GetMenuBar()->IsVisible()) { + if (CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0) && GetMenuOrMenubarVisible()) { mImGuiIo->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; } else { mImGuiIo->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad; @@ -289,7 +291,7 @@ void Gui::BlockImGuiGamepadNavigation() { } void Gui::UnblockImGuiGamepadNavigation() { - if (CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0) && GetMenuBar() && GetMenuBar()->IsVisible()) { + if (CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0) && GetMenuOrMenubarVisible()) { mImGuiIo->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; } } @@ -337,13 +339,19 @@ void Gui::DrawMenu() { ImGui::DockSpace(dockId, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None | ImGuiDockNodeFlags_NoDockingInCentralNode); - if (ImGui::IsKeyPressed(TOGGLE_BTN) || + if (ImGui::IsKeyPressed(TOGGLE_BTN) || ImGui::IsKeyPressed(ImGuiKey_Escape) || (ImGui::IsKeyPressed(TOGGLE_PAD_BTN) && CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0))) { - GetMenuBar()->ToggleVisibility(); + if (ImGui::IsKeyPressed(TOGGLE_BTN) || (ImGui::IsKeyPressed(TOGGLE_PAD_BTN) && !GetPadBtnTogglesMenu())) { + GetMenuBar()->ToggleVisibility(); + } else if (ImGui::IsKeyPressed(ImGuiKey_Escape) || + (ImGui::IsKeyPressed(TOGGLE_PAD_BTN) && GetPadBtnTogglesMenu())) { + GetMenu()->ToggleVisibility(); + } if (wnd->IsFullscreen()) { - Context::GetInstance()->GetWindow()->SetCursorVisibility(GetMenuBar() && GetMenuBar()->IsVisible()); + Context::GetInstance()->GetWindow()->SetCursorVisibility(GetMenuOrMenubarVisible() || + wnd->ShouldForceCursorVisibility()); } - if (CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0) && GetMenuBar() && GetMenuBar()->IsVisible()) { + if (CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0) && GetMenuOrMenubarVisible()) { mImGuiIo->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; } else { mImGuiIo->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad; @@ -370,6 +378,10 @@ void Gui::DrawMenu() { GetMenuBar()->Draw(); } + if (GetMenu()) { + GetMenu()->Draw(); + } + ImGui::End(); for (auto& windowIter : mGuiWindows) { @@ -898,11 +910,43 @@ void Gui::SetMenuBar(std::shared_ptr menuBar) { } if (Context::GetInstance()->GetWindow()->IsFullscreen()) { - Context::GetInstance()->GetWindow()->SetCursorVisibility(GetMenuBar() && GetMenuBar()->IsVisible()); + Context::GetInstance()->GetWindow()->SetCursorVisibility( + (GetMenuBar() && GetMenuBar()->IsVisible()) || + Context::GetInstance()->GetWindow()->ShouldForceCursorVisibility()); + } +} + +void Gui::SetMenu(std::shared_ptr menu) { + mMenu = menu; + + if (GetMenu()) { + GetMenu()->Init(); + } + + if (Context::GetInstance()->GetWindow()->IsFullscreen()) { + Context::GetInstance()->GetWindow()->SetCursorVisibility( + (GetMenu() && GetMenu()->IsVisible()) || + Context::GetInstance()->GetWindow()->ShouldForceCursorVisibility()); } } std::shared_ptr Gui::GetMenuBar() { return mMenuBar; } + +bool Gui::GetMenuOrMenubarVisible() { + return (GetMenuBar() && GetMenuBar()->IsVisible()) || (GetMenu() && GetMenu()->IsVisible()); +} + +std::shared_ptr Gui::GetMenu() { + return mMenu; +} + +bool Gui::GetPadBtnTogglesMenu() { + return mPadBtnTogglesMenu; +} + +void Gui::SetPadBtnTogglesMenu() { + mPadBtnTogglesMenu = true; +} } // namespace Ship diff --git a/src/window/gui/Gui.h b/src/window/gui/Gui.h index 39388af3e..3fe4d877f 100644 --- a/src/window/gui/Gui.h +++ b/src/window/gui/Gui.h @@ -98,6 +98,11 @@ class Gui { bool ImGuiGamepadNavigationEnabled(); void BlockImGuiGamepadNavigation(); void UnblockImGuiGamepadNavigation(); + void SetMenu(std::shared_ptr menu); + bool GetMenuOrMenubarVisible(); + std::shared_ptr GetMenu(); + bool GetPadBtnTogglesMenu(); + void SetPadBtnTogglesMenu(); protected: void ImGuiWMInit(); @@ -115,8 +120,10 @@ class Gui { bool mNeedsConsoleVariableSave; std::shared_ptr mGameOverlay; std::shared_ptr mMenuBar; + std::shared_ptr mMenu; std::unordered_map mGuiTextures; std::map> mGuiWindows; + bool mPadBtnTogglesMenu = false; }; } // namespace Ship diff --git a/src/window/gui/GuiElement.cpp b/src/window/gui/GuiElement.cpp index b070fe037..1027db5bf 100644 --- a/src/window/gui/GuiElement.cpp +++ b/src/window/gui/GuiElement.cpp @@ -3,21 +3,10 @@ #include "libultraship/libultraship.h" namespace Ship { -GuiElement::GuiElement(const std::string& visibilityConsoleVariable, bool isVisible) - : mIsInitialized(false), mIsVisible(isVisible), mVisibilityConsoleVariable(visibilityConsoleVariable) { - if (!mVisibilityConsoleVariable.empty()) { - mIsVisible = CVarGetInteger(mVisibilityConsoleVariable.c_str(), mIsVisible); - SyncVisibilityConsoleVariable(); - } -} - -GuiElement::GuiElement(const std::string& visibilityConsoleVariable) : GuiElement(visibilityConsoleVariable, false) { -} - -GuiElement::GuiElement(bool isVisible) : GuiElement("", isVisible) { +GuiElement::GuiElement(bool isVisible) : mIsInitialized(false), mIsVisible(isVisible) { } -GuiElement::GuiElement() : GuiElement("", false) { +GuiElement::GuiElement() : GuiElement(false) { } GuiElement::~GuiElement() { @@ -32,41 +21,12 @@ void GuiElement::Init() { mIsInitialized = true; } -void GuiElement::Draw() { - if (!IsVisible()) { - return; - } - - DrawElement(); - // Sync up the IsVisible flag if it was changed by ImGui - SyncVisibilityConsoleVariable(); -} - void GuiElement::Update() { UpdateElement(); } -void GuiElement::SyncVisibilityConsoleVariable() { - if (mVisibilityConsoleVariable.empty()) { - return; - } - - bool shouldSave = CVarGetInteger(mVisibilityConsoleVariable.c_str(), 0) != IsVisible(); - - if (IsVisible()) { - CVarSetInteger(mVisibilityConsoleVariable.c_str(), IsVisible()); - } else { - CVarClear(mVisibilityConsoleVariable.c_str()); - } - - if (shouldSave) { - Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } -} - void GuiElement::SetVisiblity(bool visible) { mIsVisible = visible; - SyncVisibilityConsoleVariable(); } void GuiElement::Show() { diff --git a/src/window/gui/GuiElement.h b/src/window/gui/GuiElement.h index db2ae1baa..0aee25751 100644 --- a/src/window/gui/GuiElement.h +++ b/src/window/gui/GuiElement.h @@ -5,14 +5,12 @@ namespace Ship { class GuiElement { public: - GuiElement(const std::string& visibilityConsoleVariable, bool isVisible); - GuiElement(const std::string& visibilityConsoleVariable); GuiElement(bool isVisible); GuiElement(); ~GuiElement(); void Init(); - void Draw(); + virtual void Draw() = 0; void Update(); void Show(); @@ -20,19 +18,16 @@ class GuiElement { void ToggleVisibility(); bool IsVisible(); bool IsInitialized(); + virtual void DrawElement() = 0; protected: virtual void InitElement() = 0; - virtual void DrawElement() = 0; virtual void UpdateElement() = 0; - void SetVisiblity(bool visible); + virtual void SetVisiblity(bool visible); bool mIsVisible; private: - void SyncVisibilityConsoleVariable(); - std::string mVisibilityConsoleVariable; - bool mIsInitialized; }; diff --git a/src/window/gui/GuiMenuBar.cpp b/src/window/gui/GuiMenuBar.cpp index 94fa48e19..a23aaf4e6 100644 --- a/src/window/gui/GuiMenuBar.cpp +++ b/src/window/gui/GuiMenuBar.cpp @@ -1,3 +1,48 @@ #include "window/gui/GuiMenuBar.h" +#include "libultraship/libultraship.h" -namespace Ship {} // namespace Ship +namespace Ship { +GuiMenuBar::GuiMenuBar(const std::string& visibilityConsoleVariable, bool isVisible) + : mVisibilityConsoleVariable(visibilityConsoleVariable), GuiElement(isVisible) { + if (!mVisibilityConsoleVariable.empty()) { + mIsVisible = CVarGetInteger(mVisibilityConsoleVariable.c_str(), mIsVisible); + SyncVisibilityConsoleVariable(); + } +} + +GuiMenuBar::GuiMenuBar(const std::string& visibilityConsoleVariable) : GuiMenuBar(visibilityConsoleVariable, false) { +} + +void GuiMenuBar::Draw() { + if (!IsVisible()) { + return; + } + + DrawElement(); + // Sync up the IsVisible flag if it was changed by ImGui + SyncVisibilityConsoleVariable(); +} + +void GuiMenuBar::SyncVisibilityConsoleVariable() { + if (mVisibilityConsoleVariable.empty()) { + return; + } + + bool shouldSave = CVarGetInteger(mVisibilityConsoleVariable.c_str(), 0) != IsVisible(); + + if (IsVisible()) { + CVarSetInteger(mVisibilityConsoleVariable.c_str(), IsVisible()); + } else { + CVarClear(mVisibilityConsoleVariable.c_str()); + } + + if (shouldSave) { + Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } +} + +void GuiMenuBar::SetVisiblity(bool visible) { + mIsVisible = visible; + SyncVisibilityConsoleVariable(); +} +} // namespace Ship diff --git a/src/window/gui/GuiMenuBar.h b/src/window/gui/GuiMenuBar.h index 7889a96b2..53314f086 100644 --- a/src/window/gui/GuiMenuBar.h +++ b/src/window/gui/GuiMenuBar.h @@ -6,6 +6,15 @@ namespace Ship { class GuiMenuBar : public GuiElement { public: - using GuiElement::GuiElement; + GuiMenuBar(const std::string& visibilityConsoleVariable, bool isVisible); + GuiMenuBar(const std::string& visibilityConsoleVariable); + void Draw() override; + + protected: + void SetVisiblity(bool visible) override; + + private: + void SyncVisibilityConsoleVariable(); + std::string mVisibilityConsoleVariable; }; } // namespace Ship diff --git a/src/window/gui/GuiWindow.cpp b/src/window/gui/GuiWindow.cpp index 5ec6ae646..71761be51 100644 --- a/src/window/gui/GuiWindow.cpp +++ b/src/window/gui/GuiWindow.cpp @@ -1,12 +1,76 @@ #include "GuiWindow.h" +#include "libultraship/libultraship.h" + namespace Ship { +GuiWindow::GuiWindow(const std::string& consoleVariable, bool isVisible, const std::string& name, ImVec2 originalSize, + uint32_t windowFlags) + : mName(name), mVisibilityConsoleVariable(consoleVariable), mOriginalSize(originalSize), mWindowFlags(windowFlags), + GuiElement(isVisible) { + if (!mVisibilityConsoleVariable.empty()) { + mIsVisible = CVarGetInteger(mVisibilityConsoleVariable.c_str(), mIsVisible); + SyncVisibilityConsoleVariable(); + } +} + +GuiWindow::GuiWindow(const std::string& consoleVariable, bool isVisible, const std::string& name, ImVec2 originalSize) + : GuiWindow(consoleVariable, isVisible, name, originalSize, ImGuiWindowFlags_None) { +} + GuiWindow::GuiWindow(const std::string& consoleVariable, bool isVisible, const std::string& name) - : mName(name), GuiElement(consoleVariable, isVisible) { + : GuiWindow(consoleVariable, isVisible, name, ImVec2{ -1, -1 }, ImGuiWindowFlags_None) { +} + +GuiWindow::GuiWindow(const std::string& consoleVariable, const std::string& name, ImVec2 originalSize, + uint32_t windowFlags) + : GuiWindow(consoleVariable, false, name, originalSize, windowFlags) { +} + +GuiWindow::GuiWindow(const std::string& consoleVariable, const std::string& name, ImVec2 originalSize) + : GuiWindow(consoleVariable, false, name, originalSize, ImGuiWindowFlags_None) { } GuiWindow::GuiWindow(const std::string& consoleVariable, const std::string& name) - : GuiWindow(consoleVariable, false, name) { + : GuiWindow(consoleVariable, false, name, ImVec2{ -1, -1 }, ImGuiWindowFlags_None) { +} + +void GuiWindow::SetVisiblity(bool visible) { + mIsVisible = visible; + SyncVisibilityConsoleVariable(); +} + +void GuiWindow::SyncVisibilityConsoleVariable() { + if (mVisibilityConsoleVariable.empty()) { + return; + } + + bool shouldSave = CVarGetInteger(mVisibilityConsoleVariable.c_str(), 0) != IsVisible(); + + if (IsVisible()) { + CVarSetInteger(mVisibilityConsoleVariable.c_str(), IsVisible()); + } else { + CVarClear(mVisibilityConsoleVariable.c_str()); + } + + if (shouldSave) { + Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } +} + +void GuiWindow::Draw() { + if (!IsVisible()) { + return; + } + if (mOriginalSize != ImVec2{ -1, -1 }) { + ImGui::SetNextWindowSize(mOriginalSize, ImGuiCond_FirstUseEver); + } + if (!ImGui::Begin(mName.c_str(), &mIsVisible, mWindowFlags)) { + ImGui::End(); + } + DrawElement(); + ImGui::End(); + // Sync up the IsVisible flag if it was changed by ImGui + SyncVisibilityConsoleVariable(); } std::string GuiWindow::GetName() { diff --git a/src/window/gui/GuiWindow.h b/src/window/gui/GuiWindow.h index 539d3529a..f52c9bea4 100644 --- a/src/window/gui/GuiWindow.h +++ b/src/window/gui/GuiWindow.h @@ -12,17 +12,27 @@ namespace Ship { class GuiWindow : public GuiElement { public: GuiWindow() = default; + GuiWindow(const std::string& consoleVariable, bool isVisible, const std::string& name, ImVec2 originalSize, + uint32_t windowFlags); + GuiWindow(const std::string& consoleVariable, bool isVisible, const std::string& name, ImVec2 originalSize); GuiWindow(const std::string& consoleVariable, bool isVisible, const std::string& name); + GuiWindow(const std::string& consoleVariable, const std::string& name, ImVec2 originalSize, uint32_t windowFlags); + GuiWindow(const std::string& consoleVariable, const std::string& name, ImVec2 originalSize); GuiWindow(const std::string& consoleVariable, const std::string& name); - + void Draw() override; std::string GetName(); protected: + void SetVisiblity(bool visible) override; void BeginGroupPanel(const char* name, const ImVec2& size); void EndGroupPanel(float minHeight); + void SyncVisibilityConsoleVariable(); private: + std::string mVisibilityConsoleVariable; std::string mName; ImVector mGroupPanelLabelStack; + ImVec2 mOriginalSize; + uint32_t mWindowFlags; }; } // namespace Ship diff --git a/src/window/gui/InputEditorWindow.cpp b/src/window/gui/InputEditorWindow.cpp index b9215ad3b..28f00c635 100644 --- a/src/window/gui/InputEditorWindow.cpp +++ b/src/window/gui/InputEditorWindow.cpp @@ -1637,12 +1637,10 @@ void InputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { } void InputEditorWindow::DrawElement() { - ImGui::Begin("Controller Configuration", &mIsVisible); ImGui::BeginTabBar("##ControllerConfigPortTabs"); for (uint8_t i = 0; i < 4; i++) { DrawPortTab(i); } ImGui::EndTabBar(); - ImGui::End(); } } // namespace Ship diff --git a/src/window/gui/StatsWindow.cpp b/src/window/gui/StatsWindow.cpp index 081f93bbf..0723ce224 100644 --- a/src/window/gui/StatsWindow.cpp +++ b/src/window/gui/StatsWindow.cpp @@ -18,7 +18,6 @@ void StatsWindow::DrawElement() { const float framerate = ImGui::GetIO().Framerate; const float deltatime = ImGui::GetIO().DeltaTime; ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); - ImGui::Begin("Debug Stats", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing); #if defined(_WIN32) ImGui::Text("Platform: Windows"); @@ -32,7 +31,6 @@ void StatsWindow::DrawElement() { ImGui::Text("Platform: Unknown"); #endif ImGui::Text("Status: %.3f ms/frame (%.1f FPS)", deltatime * 1000.0f, framerate); - ImGui::End(); ImGui::PopStyleColor(); }