From cbe74cdab46661a39ee3c9ca0abc55eb30082348 Mon Sep 17 00:00:00 2001 From: Andrew Lanzone Date: Sat, 31 May 2025 18:58:30 -0700 Subject: [PATCH] Add controller support to repair and recharge menus --- apps/openmw/mwgui/itemchargeview.cpp | 62 ++++++++++++++++++++++++++ apps/openmw/mwgui/itemchargeview.hpp | 5 +++ apps/openmw/mwgui/itemselection.cpp | 1 + apps/openmw/mwgui/messagebox.cpp | 4 +- apps/openmw/mwgui/recharge.cpp | 16 +++++++ apps/openmw/mwgui/recharge.hpp | 2 + apps/openmw/mwgui/repair.cpp | 16 +++++++ apps/openmw/mwgui/repair.hpp | 2 + apps/openmw/mwgui/windowmanagerimp.cpp | 3 ++ files/data/mygui/openmw_resources.xml | 4 ++ 10 files changed, 113 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/itemchargeview.cpp b/apps/openmw/mwgui/itemchargeview.cpp index 02c3cc182c..abbf328a8c 100644 --- a/apps/openmw/mwgui/itemchargeview.cpp +++ b/apps/openmw/mwgui/itemchargeview.cpp @@ -1,5 +1,6 @@ #include "itemchargeview.hpp" +#include #include #include @@ -9,8 +10,11 @@ #include #include +#include #include "../mwbase/environment.hpp" +#include "../mwbase/inputmanager.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwmechanics/spellutil.hpp" @@ -19,6 +23,7 @@ #include "itemmodel.hpp" #include "itemwidget.hpp" +#include "textcolours.hpp" namespace MWGui { @@ -156,11 +161,20 @@ namespace MWGui mScrollView->setCanvasSize( MyGUI::IntSize(mScrollView->getWidth(), std::max(mScrollView->getHeight(), currentY))); mScrollView->setVisibleVScroll(true); + + if (Settings::gui().mControllerMenus) + updateControllerFocus(-1, mControllerFocus); } void ItemChargeView::resetScrollbars() { mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + + if (Settings::gui().mControllerMenus) + { + updateControllerFocus(mControllerFocus, 0); + mControllerFocus = 0; + } } void ItemChargeView::setSize(const MyGUI::IntSize& value) @@ -224,4 +238,52 @@ namespace MWGui mScrollView->setViewOffset( MyGUI::IntPoint(0, static_cast(mScrollView->getViewOffset().top + rel * 0.3f))); } + + void ItemChargeView::onControllerButton(const unsigned char button) + { + if (mLines.empty()) + return; + + int prevFocus = mControllerFocus; + + if (button == SDL_CONTROLLER_BUTTON_A) + { + // Select the focused item, if any. + if (mControllerFocus >= 0 && mControllerFocus < mLines.size()) + onIconClicked(mLines[mControllerFocus].mIcon); + } + else if (button == SDL_CONTROLLER_BUTTON_DPAD_UP) + mControllerFocus = wrap(mControllerFocus - 1, mLines.size()); + else if (button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) + mControllerFocus = wrap(mControllerFocus + 1, mLines.size()); + + if (prevFocus != mControllerFocus) + updateControllerFocus(prevFocus, mControllerFocus); + } + + void ItemChargeView::updateControllerFocus(int prevFocus, int newFocus) + { + if (mLines.empty()) + return; + + const TextColours& textColours{ MWBase::Environment::get().getWindowManager()->getTextColours() }; + + if (prevFocus >= 0 && prevFocus < mLines.size()) + { + mLines[prevFocus].mText->setTextColour(textColours.normal); + mLines[prevFocus].mIcon->setControllerFocus(false); + } + + if (newFocus >= 0 && newFocus < mLines.size()) + { + mLines[newFocus].mText->setTextColour(textColours.link); + mLines[newFocus].mIcon->setControllerFocus(true); + + // Scroll the list to keep the active item in view + if (mControllerFocus <= 3) + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mScrollView->setViewOffset(MyGUI::IntPoint(-55 * (mControllerFocus - 3), 0)); + } + } } diff --git a/apps/openmw/mwgui/itemchargeview.hpp b/apps/openmw/mwgui/itemchargeview.hpp index f7617d37eb..73bf9c3de2 100644 --- a/apps/openmw/mwgui/itemchargeview.hpp +++ b/apps/openmw/mwgui/itemchargeview.hpp @@ -52,6 +52,8 @@ namespace MWGui MyGUI::delegates::MultiDelegate eventItemClicked; + void onControllerButton(const unsigned char button); + private: struct Line { @@ -72,6 +74,9 @@ namespace MWGui std::unique_ptr mModel; MyGUI::ScrollView* mScrollView; DisplayMode mDisplayMode; + + int mControllerFocus; + void updateControllerFocus(int prevFocus, int newFocus); }; } diff --git a/apps/openmw/mwgui/itemselection.cpp b/apps/openmw/mwgui/itemselection.cpp index a00c754c3d..ec4ecb9d0f 100644 --- a/apps/openmw/mwgui/itemselection.cpp +++ b/apps/openmw/mwgui/itemselection.cpp @@ -31,6 +31,7 @@ namespace MWGui mControllerButtons.a = "#{sSelect}"; mControllerButtons.b = "#{sBack}"; + mControllerButtons.r3 = "#{sInfo}"; } bool ItemSelectionDialog::exit() diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index ec42993f4d..5f074a67c6 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -454,7 +454,7 @@ namespace MWGui if (mButtons.size() == 1) buttonActivated(mButtons[0]); } - else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) { if (mButtons.size() <= 1) return true; @@ -465,7 +465,7 @@ namespace MWGui mControllerFocus = wrap(mControllerFocus - 1, mButtons.size()); mButtons[mControllerFocus]->setStateSelected(true); } - else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN || arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) { if (mButtons.size() <= 1) return true; diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index 7d57988d97..605a9a1a94 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -39,6 +39,10 @@ namespace MWGui mBox->setDisplayMode(ItemChargeView::DisplayMode_EnchantmentCharge); mGemIcon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onSelectItem); + + mControllerButtons.a = "Recharge"; + mControllerButtons.b = "#{sBack}"; + mControllerButtons.y = "#{sSoulGem}"; } void Recharge::onOpen() @@ -136,4 +140,16 @@ namespace MWGui updateView(); } + bool Recharge::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) + { + if ((arg.button == SDL_CONTROLLER_BUTTON_A && !mGemBox->getVisible()) + || arg.button == SDL_CONTROLLER_BUTTON_Y) + onSelectItem(mGemIcon); + else if (arg.button == SDL_CONTROLLER_BUTTON_B) + onCancel(mCancelButton); + else + mBox->onControllerButton(arg.button); + + return true; + } } diff --git a/apps/openmw/mwgui/recharge.hpp b/apps/openmw/mwgui/recharge.hpp index f8a037d2db..c10f96e71e 100644 --- a/apps/openmw/mwgui/recharge.hpp +++ b/apps/openmw/mwgui/recharge.hpp @@ -51,6 +51,8 @@ namespace MWGui void onItemClicked(MyGUI::Widget* sender, const MWWorld::Ptr& item); void onCancel(MyGUI::Widget* sender); void onMouseWheel(MyGUI::Widget* _sender, int _rel); + + bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; }; } diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index c1602b8407..6f5d256d86 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -39,6 +39,10 @@ namespace MWGui mRepairBox->setDisplayMode(ItemChargeView::DisplayMode_Health); mToolIcon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onSelectItem); + + mControllerButtons.a = "#{sRepair}"; + mControllerButtons.b = "#{sBack}"; + mControllerButtons.y = "Tool"; } void Repair::onOpen() @@ -150,4 +154,16 @@ namespace MWGui updateRepairView(); } + bool Repair::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) + { + if ((arg.button == SDL_CONTROLLER_BUTTON_A && !mToolBox->getVisible()) + || arg.button == SDL_CONTROLLER_BUTTON_Y) + onSelectItem(mToolIcon); + else if (arg.button == SDL_CONTROLLER_BUTTON_B) + onCancel(mCancelButton); + else + mRepairBox->onControllerButton(arg.button); + + return true; + } } diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index 093a10e3fa..986b28b613 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -50,6 +50,8 @@ namespace MWGui void onRepairItem(MyGUI::Widget* sender, const MWWorld::Ptr& ptr); void onCancel(MyGUI::Widget* sender); + + bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; }; } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 00a35df774..9350ef4d1a 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -952,6 +952,9 @@ namespace MWGui for (int i = 0; i < winCount; i++) mGuiModeStates[mode].mWindows[i]->setActiveControllerWindow(i == activeIndex); + MWBase::Environment::get().getInputManager()->setGamepadGuiCursorEnabled( + mGuiModeStates[mode].mWindows[activeIndex]->isGamepadCursorAllowed()); + updateControllerButtonsOverlay(); setCursorActive(false); diff --git a/files/data/mygui/openmw_resources.xml b/files/data/mygui/openmw_resources.xml index 08586ea75c..d107c094e3 100644 --- a/files/data/mygui/openmw_resources.xml +++ b/files/data/mygui/openmw_resources.xml @@ -172,6 +172,10 @@ + + + +