From 451d68461ceb983694f7e359ce4701d5928b81f4 Mon Sep 17 00:00:00 2001 From: Andrew Lanzone Date: Tue, 27 May 2025 22:40:00 -0700 Subject: [PATCH] Add controller support to skill and attribute menus --- apps/openmw/mwgui/class.cpp | 88 +++++++++++++++++++++++++++++++---- apps/openmw/mwgui/class.hpp | 4 ++ apps/openmw/mwgui/widgets.cpp | 26 +++++++++++ apps/openmw/mwgui/widgets.hpp | 8 ++++ 4 files changed, 116 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index b1e6b77ca0..c0660b5f02 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -943,6 +943,7 @@ namespace MWGui widget->setAttributeId(attribute.mId); widget->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); ToolTips::createAttributeToolTip(widget, attribute.mId); + mAttributeButtons.emplace_back(widget); } attributes->setVisibleVScroll(false); @@ -954,8 +955,15 @@ namespace MWGui getWidget(cancelButton, "CancelButton"); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); - mControllerButtons.a = "#{sSelect}"; - mControllerButtons.b = "#{sCancel}"; + if (Settings::gui().mControllerMenus) + { + mControllerFocus = 0; + if (mAttributeButtons.size() > 0) + mAttributeButtons[0]->setStateSelected(true); + + mControllerButtons.a = "#{sSelect}"; + mControllerButtons.b = "#{sCancel}"; + } } // widget controls @@ -979,12 +987,29 @@ namespace MWGui bool SelectAttributeDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) { - if (arg.button == SDL_CONTROLLER_BUTTON_B) + if (arg.button == SDL_CONTROLLER_BUTTON_A) + { + if (mControllerFocus >= 0 && mControllerFocus < mAttributeButtons.size()) + onAttributeClicked(mAttributeButtons[mControllerFocus]); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_B) { onCancelClicked(nullptr); - return true; } - return false; + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP) + { + mAttributeButtons[mControllerFocus]->setStateSelected(false); + mControllerFocus = wrap(mControllerFocus - 1, mAttributeButtons.size()); + mAttributeButtons[mControllerFocus]->setStateSelected(true); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) + { + mAttributeButtons[mControllerFocus]->setStateSelected(false); + mControllerFocus = wrap(mControllerFocus + 1, mAttributeButtons.size()); + mAttributeButtons[mControllerFocus]->setStateSelected(true); + } + + return true; } /* SelectSkillDialog */ @@ -1016,6 +1041,7 @@ namespace MWGui skillWidget->setSkillId(skill.mId); skillWidget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked); ToolTips::createSkillToolTip(skillWidget, skill.mId); + mSkillButtons.emplace_back(skillWidget); } for (const auto& [widget, coord] : specializations) { @@ -1029,8 +1055,15 @@ namespace MWGui getWidget(cancelButton, "CancelButton"); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); - mControllerButtons.a = "#{sSelect}"; - mControllerButtons.b = "#{sCancel}"; + if (Settings::gui().mControllerMenus) + { + mControllerFocus = 0; + if (mSkillButtons.size() > 0) + mSkillButtons[0]->setStateSelected(true); + + mControllerButtons.a = "#{sSelect}"; + mControllerButtons.b = "#{sCancel}"; + } } SelectSkillDialog::~SelectSkillDialog() {} @@ -1056,12 +1089,47 @@ namespace MWGui bool SelectSkillDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) { - if (arg.button == SDL_CONTROLLER_BUTTON_B) + if (arg.button == SDL_CONTROLLER_BUTTON_A) + { + if (mControllerFocus >= 0 && mControllerFocus < mSkillButtons.size()) + onSkillClicked(mSkillButtons[mControllerFocus]); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_B) { onCancelClicked(nullptr); - return true; } - return false; + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP) + { + mSkillButtons[mControllerFocus]->setStateSelected(false); + mControllerFocus = wrap(mControllerFocus - 1, mSkillButtons.size()); + mSkillButtons[mControllerFocus]->setStateSelected(true); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) + { + mSkillButtons[mControllerFocus]->setStateSelected(false); + mControllerFocus = wrap(mControllerFocus + 1, mSkillButtons.size()); + mSkillButtons[mControllerFocus]->setStateSelected(true); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) + { + mSkillButtons[mControllerFocus]->setStateSelected(false); + if (mControllerFocus < 9) + mControllerFocus += 18; + else + mControllerFocus -= 9; + mSkillButtons[mControllerFocus]->setStateSelected(true); + } + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) + { + mSkillButtons[mControllerFocus]->setStateSelected(false); + if (mControllerFocus >= 18) + mControllerFocus -= 18; + else + mControllerFocus += 9; + mSkillButtons[mControllerFocus]->setStateSelected(true); + } + + return true; } /* DescriptionDialog */ diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 515416973e..9f04fa9e13 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -219,6 +219,8 @@ namespace MWGui void onAttributeClicked(Widgets::MWAttributePtr _sender); void onCancelClicked(MyGUI::Widget* _sender); bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; + int mControllerFocus; + std::vector mAttributeButtons; private: ESM::RefId mAttributeId; @@ -251,6 +253,8 @@ namespace MWGui void onSkillClicked(Widgets::MWSkillPtr _sender); void onCancelClicked(MyGUI::Widget* _sender); bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; + int mControllerFocus; + std::vector mSkillButtons; private: ESM::RefId mSkillId; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 6cc5bdfdf5..8995f04b92 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -14,6 +14,8 @@ #include #include +#include "textcolours.hpp" + #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -66,6 +68,12 @@ namespace MWGui::Widgets } } + void MWSkill::setStateSelected(bool selected) + { + const TextColours& textColours{ MWBase::Environment::get().getWindowManager()->getTextColours() }; + mSkillNameWidget->setTextColour(selected ? textColours.link : textColours.normal); + } + void MWSkill::onClicked(MyGUI::Widget* _sender) { eventClicked(this); @@ -150,6 +158,12 @@ namespace MWGui::Widgets } } + void MWAttribute::setStateSelected(bool selected) + { + const TextColours& textColours{ MWBase::Environment::get().getWindowManager()->getTextColours() }; + mAttributeNameWidget->setTextColour(selected ? textColours.link : textColours.normal); + } + void MWAttribute::initialiseOverride() { Base::initialiseOverride(); @@ -231,6 +245,12 @@ namespace MWGui::Widgets } } + void MWSpell::setStateSelected(bool selected) + { + const TextColours& textColours{ MWBase::Environment::get().getWindowManager()->getTextColours() }; + mSpellNameWidget->setTextColour(selected ? textColours.link : textColours.normal); + } + void MWSpell::initialiseOverride() { Base::initialiseOverride(); @@ -461,6 +481,12 @@ namespace MWGui::Widgets MWSpellEffect::~MWSpellEffect() {} + void MWSpellEffect::setStateSelected(bool selected) + { + const TextColours& textColours{ MWBase::Environment::get().getWindowManager()->getTextColours() }; + mTextWidget->setTextColour(selected ? textColours.link : textColours.normal); + } + void MWSpellEffect::initialiseOverride() { Base::initialiseOverride(); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index d562e4e07f..c51846d9df 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -110,6 +110,8 @@ namespace MWGui */ EventHandle_SkillVoid eventClicked; + void setStateSelected(bool selected); + protected: virtual ~MWSkill(); @@ -149,6 +151,8 @@ namespace MWGui */ EventHandle_AttributeVoid eventClicked; + void setStateSelected(bool selected); + protected: ~MWAttribute() override = default; @@ -191,6 +195,8 @@ namespace MWGui const ESM::RefId& getSpellId() const { return mId; } + void setStateSelected(bool selected); + protected: virtual ~MWSpell(); @@ -256,6 +262,8 @@ namespace MWGui int getRequestedWidth() const { return mRequestedWidth; } + void setStateSelected(bool selected); + protected: virtual ~MWSpellEffect();