Skip to content

Commit

Permalink
Modern menu support (Kenix3#639)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 30, 2024
1 parent 31e9b00 commit 181465d
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 81 deletions.
4 changes: 2 additions & 2 deletions src/controller/controldeck/ControlDeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
5 changes: 4 additions & 1 deletion src/graphic/Fast3D/Fast3dWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down
10 changes: 10 additions & 0 deletions src/window/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
3 changes: 3 additions & 0 deletions src/window/Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Window {
float GetCurrentAspectRatio();
void SaveWindowToConfig();
std::shared_ptr<Gui> GetGui();
bool ShouldForceCursorVisibility();
void SetForceCursorVisibility(bool visible);

protected:
void SetWindowBackend(WindowBackend backend);
Expand All @@ -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<Config> mConfig;
bool mForceCursorVisibility;
};
} // namespace Ship
4 changes: 0 additions & 4 deletions src/window/gui/ConsoleWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -458,7 +455,6 @@ void ConsoleWindow::DrawElement() {
}
ImGui::PopItemWidth();
}
ImGui::End();
}

void ConsoleWindow::Dispatch(const std::string& line) {
Expand Down
2 changes: 1 addition & 1 deletion src/window/gui/ConsoleWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 0 additions & 5 deletions src/window/gui/GfxDebuggerWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -429,8 +426,6 @@ void GfxDebuggerWindow::DrawElement() {
DrawDisas();
}
}

ImGui::End();
}

} // namespace LUS
62 changes: 53 additions & 9 deletions src/window/gui/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ Gui::Gui(std::vector<std::shared_ptr<GuiWindow>> guiWindows) : mNeedsConsoleVari
}

if (GetGuiWindow("Console") == nullptr) {
AddGuiWindow(std::make_shared<ConsoleWindow>(CVAR_CONSOLE_WINDOW_OPEN, "Console"));
AddGuiWindow(std::make_shared<ConsoleWindow>(CVAR_CONSOLE_WINDOW_OPEN, "Console", ImVec2(520, 600),
ImGuiWindowFlags_NoFocusOnAppearing));
}

if (GetGuiWindow("GfxDebuggerWindow") == nullptr) {
AddGuiWindow(std::make_shared<LUS::GfxDebuggerWindow>(CVAR_GFX_DEBUGGER_WINDOW_OPEN, "GfxDebuggerWindow"));
AddGuiWindow(std::make_shared<LUS::GfxDebuggerWindow>(CVAR_GFX_DEBUGGER_WINDOW_OPEN, "GfxDebuggerWindow",
ImVec2(520, 600)));
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -370,6 +378,10 @@ void Gui::DrawMenu() {
GetMenuBar()->Draw();
}

if (GetMenu()) {
GetMenu()->Draw();
}

ImGui::End();

for (auto& windowIter : mGuiWindows) {
Expand Down Expand Up @@ -898,11 +910,43 @@ void Gui::SetMenuBar(std::shared_ptr<GuiMenuBar> 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<GuiWindow> 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<GuiMenuBar> Gui::GetMenuBar() {
return mMenuBar;
}

bool Gui::GetMenuOrMenubarVisible() {
return (GetMenuBar() && GetMenuBar()->IsVisible()) || (GetMenu() && GetMenu()->IsVisible());
}

std::shared_ptr<GuiWindow> Gui::GetMenu() {
return mMenu;
}

bool Gui::GetPadBtnTogglesMenu() {
return mPadBtnTogglesMenu;
}

void Gui::SetPadBtnTogglesMenu() {
mPadBtnTogglesMenu = true;
}
} // namespace Ship
7 changes: 7 additions & 0 deletions src/window/gui/Gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ class Gui {
bool ImGuiGamepadNavigationEnabled();
void BlockImGuiGamepadNavigation();
void UnblockImGuiGamepadNavigation();
void SetMenu(std::shared_ptr<GuiWindow> menu);
bool GetMenuOrMenubarVisible();
std::shared_ptr<GuiWindow> GetMenu();
bool GetPadBtnTogglesMenu();
void SetPadBtnTogglesMenu();

protected:
void ImGuiWMInit();
Expand All @@ -115,8 +120,10 @@ class Gui {
bool mNeedsConsoleVariableSave;
std::shared_ptr<GameOverlay> mGameOverlay;
std::shared_ptr<GuiMenuBar> mMenuBar;
std::shared_ptr<GuiWindow> mMenu;
std::unordered_map<std::string, GuiTextureMetadata> mGuiTextures;
std::map<std::string, std::shared_ptr<GuiWindow>> mGuiWindows;
bool mPadBtnTogglesMenu = false;
};
} // namespace Ship

Expand Down
44 changes: 2 additions & 42 deletions src/window/gui/GuiElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down
11 changes: 3 additions & 8 deletions src/window/gui/GuiElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,29 @@
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();
void Hide();
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;
};

Expand Down
Loading

0 comments on commit 181465d

Please sign in to comment.