diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index e658001e5a..b1e6b77ca0 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -473,7 +473,8 @@ namespace MWGui { if (arg.button == SDL_CONTROLLER_BUTTON_A) { - onButtonClicked(mButtons[mControllerFocus]); + if (mControllerFocus >= 0 && mControllerFocus < mButtons.size()) + onButtonClicked(mButtons[mControllerFocus]); } else if (arg.button == SDL_CONTROLLER_BUTTON_B) { diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 94807dd54c..ec42993f4d 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -446,6 +446,7 @@ namespace MWGui { if (arg.button == SDL_CONTROLLER_BUTTON_A) { + mControllerFocus = std::clamp(mControllerFocus, 0, (int)mButtons.size() - 1); buttonActivated(mButtons[mControllerFocus]); } else if (arg.button == SDL_CONTROLLER_BUTTON_B) diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index e1f12ae6e0..1c986180a8 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -78,7 +78,7 @@ namespace MWGui toAdd->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onSpellButtonClick); mSpellsWidgetMap.insert(std::make_pair(toAdd, spell.mId)); if (price <= playerGold) - mSpellButtons.emplace_back(toAdd); + mSpellButtons.emplace_back(std::make_pair(toAdd, mSpellsWidgetMap.size())); } void SpellBuyingWindow::clearSpells() @@ -143,7 +143,7 @@ namespace MWGui { mControllerFocus = 0; if (mSpellButtons.size() > 0) - mSpellButtons[0]->setStateSelected(true); + mSpellButtons[0].first->setStateSelected(true); } // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the @@ -221,7 +221,8 @@ namespace MWGui { if (arg.button == SDL_CONTROLLER_BUTTON_A) { - onSpellButtonClick(mSpellButtons[mControllerFocus]); + if (mControllerFocus >= 0 && mControllerFocus < mSpellButtons.size()) + onSpellButtonClick(mSpellButtons[mControllerFocus].first); } else if (arg.button == SDL_CONTROLLER_BUTTON_B) { @@ -232,25 +233,29 @@ namespace MWGui if (mSpellButtons.size() <= 1) return true; - mSpellButtons[mControllerFocus]->setStateSelected(false); + mSpellButtons[mControllerFocus].first->setStateSelected(false); mControllerFocus = wrap(mControllerFocus - 1, mSpellButtons.size()); - mSpellButtons[mControllerFocus]->setStateSelected(true); + mSpellButtons[mControllerFocus].first->setStateSelected(true); } else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) { if (mSpellButtons.size() <= 1) return true; - mSpellButtons[mControllerFocus]->setStateSelected(false); + mSpellButtons[mControllerFocus].first->setStateSelected(false); mControllerFocus = wrap(mControllerFocus + 1, mSpellButtons.size()); - mSpellButtons[mControllerFocus]->setStateSelected(true); + mSpellButtons[mControllerFocus].first->setStateSelected(true); } // Scroll the list to keep the active item in view - if (mControllerFocus <= 5) + int line = mSpellButtons[mControllerFocus].second; + if (line <= 5) mSpellsView->setViewOffset(MyGUI::IntPoint(0, 0)); else - mSpellsView->setViewOffset(MyGUI::IntPoint(0, -10 * (mControllerFocus - 5))); + { + const int lineHeight = Settings::gui().mFontSize + 2; + mSpellsView->setViewOffset(MyGUI::IntPoint(0, -lineHeight * (line - 5))); + } return true; } diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index 234dcb5b9d..e67dfde76c 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -39,7 +39,8 @@ namespace MWGui MyGUI::ScrollView* mSpellsView; std::map mSpellsWidgetMap; - std::vector mSpellButtons; + /// List of enabled/purchasable spells and their index in the full list. + std::vector> mSpellButtons; void onCancelButtonClicked(MyGUI::Widget* _sender); void onSpellButtonClick(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/spellview.cpp b/apps/openmw/mwgui/spellview.cpp index 2ebd1751da..6ef73c7794 100644 --- a/apps/openmw/mwgui/spellview.cpp +++ b/apps/openmw/mwgui/spellview.cpp @@ -122,7 +122,7 @@ namespace MWGui t->setCaption(spell.mName + captionSuffix); t->setTextAlign(MyGUI::Align::Left); adjustSpellWidget(spell, i, t); - mButtons.emplace_back(t); + mButtons.emplace_back(std::make_pair(t, i)); if (!spell.mCostColumn.empty() && mShowCostColumn) { @@ -339,7 +339,7 @@ namespace MWGui // Select the focused item, if any. if (mControllerFocus >= 0 && mControllerFocus < mButtons.size()) { - onSpellSelected(mButtons.at(mControllerFocus)); + onSpellSelected(mButtons[mControllerFocus].first); MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Menu Click")); } } @@ -348,12 +348,16 @@ namespace MWGui // Toggle info tooltip mControllerTooltip = !mControllerTooltip; if (mControllerTooltip && mControllerFocus >= 0 && mControllerFocus < mButtons.size()) - MWBase::Environment::get().getInputManager()->warpMouseToWidget(mButtons.at(mControllerFocus)); + MWBase::Environment::get().getInputManager()->warpMouseToWidget(mButtons[mControllerFocus].first); } else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP) mControllerFocus--; else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) mControllerFocus++; + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) + mControllerFocus = std::max(0, mControllerFocus - 10); + else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) + mControllerFocus = std::min(mControllerFocus + 10, (int)mButtons.size() - 1); else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) { // Jump to first item in previous group @@ -380,10 +384,7 @@ namespace MWGui } } - if (mControllerFocus < 0) - mControllerFocus = mButtons.size() - 1; - else if (mControllerFocus >= mButtons.size()) - mControllerFocus = 0; + mControllerFocus = wrap(mControllerFocus, mButtons.size()); if (prevFocus != mControllerFocus) updateControllerFocus(prevFocus, mControllerFocus); @@ -396,19 +397,29 @@ namespace MWGui if (prevFocus >= 0 && prevFocus < mButtons.size()) { - Gui::SharedStateButton* prev = mButtons.at(prevFocus); + Gui::SharedStateButton* prev = mButtons[prevFocus].first; if (prev) prev->onMouseLostFocus(nullptr); } if (newFocus >= 0 && newFocus < mButtons.size()) { - Gui::SharedStateButton* focused = mButtons.at(newFocus); + Gui::SharedStateButton* focused = mButtons[newFocus].first; if (focused) { focused->onMouseSetFocus(nullptr); if (mControllerTooltip) MWBase::Environment::get().getInputManager()->warpMouseToWidget(focused); + + // Scroll the list to keep the active item in view + int line = mButtons[newFocus].second; + if (line <= 5) + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + else + { + const int lineHeight = focused->getHeight(); + mScrollView->setViewOffset(MyGUI::IntPoint(0, -lineHeight * (line - 5))); + } } } } diff --git a/apps/openmw/mwgui/spellview.hpp b/apps/openmw/mwgui/spellview.hpp index cf3a43354f..222d5f1ba3 100644 --- a/apps/openmw/mwgui/spellview.hpp +++ b/apps/openmw/mwgui/spellview.hpp @@ -94,8 +94,8 @@ namespace MWGui void addGroup(const std::string& label1, const std::string& label2); void adjustSpellWidget(const Spell& spell, SpellModel::ModelIndex index, MyGUI::Widget* widget); - /// Keep a list of buttons for controller navigation - std::vector mButtons; + /// Keep a list of buttons for controller navigation and their index in the full list. + std::vector> mButtons; /// Keep a list of group offsets for controller navigation std::vector mGroupIndices; diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 371f0e95aa..fcead9d543 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -251,7 +251,8 @@ namespace MWGui { if (arg.button == SDL_CONTROLLER_BUTTON_A) { - onTrainingSelected(mTrainingButtons[mControllerFocus]); + if (mControllerFocus >= 0 && mControllerFocus < mTrainingButtons.size()) + onTrainingSelected(mTrainingButtons[mControllerFocus]); } else if (arg.button == SDL_CONTROLLER_BUTTON_B) { diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index f954daafff..083bba391b 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -258,7 +258,8 @@ namespace MWGui { if (arg.button == SDL_CONTROLLER_BUTTON_A) { - onTravelButtonClick(mDestinationButtons[mControllerFocus]); + if (mControllerFocus >= 0 && mControllerFocus < mDestinationButtons.size()) + onTravelButtonClick(mDestinationButtons[mControllerFocus]); } else if (arg.button == SDL_CONTROLLER_BUTTON_B) {