Update character creation controller support to work better with gamepad mouse mode

This commit is contained in:
Andrew Lanzone 2025-05-12 02:20:28 -07:00
parent 83162477ec
commit 4bad7a3074
6 changed files with 168 additions and 52 deletions

View File

@ -50,15 +50,16 @@ namespace MWGui
mBirthList->eventListSelectAccept += MyGUI::newDelegate(this, &BirthDialog::onAccept); mBirthList->eventListSelectAccept += MyGUI::newDelegate(this, &BirthDialog::onAccept);
mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth); mBirthList->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
MyGUI::Button* backButton; getWidget(mBackButton, "BackButton");
getWidget(backButton, "BackButton"); mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
MyGUI::Button* okButton; getWidget(mOkButton, "OKButton");
getWidget(okButton, "OKButton"); mOkButton->setCaption(
okButton->setCaption(
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
if (Settings::gui().mControllerMenus)
mOkButton->setStateSelected(true);
updateBirths(); updateBirths();
updateSpells(); updateSpells();
@ -277,29 +278,50 @@ namespace MWGui
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
{ {
// Have A button do nothing so mouse controller still works. // Have A button do nothing so mouse controller still works.
if (mUsingGamepadGuiCursor)
return false; return false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_START) if (mOkButtonFocus)
{ onOkClicked(mOkButton);
onOkClicked(nullptr); else
onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_B) else if (arg.button == SDL_CONTROLLER_BUTTON_B)
{ {
onBackClicked(nullptr); onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP) else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
{ {
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mBirthList); winMgr->setKeyFocusWidget(mBirthList);
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false); winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
mUsingGamepadGuiCursor = false;
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
{ {
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mBirthList); winMgr->setKeyFocusWidget(mBirthList);
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false); winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
mUsingGamepadGuiCursor = false;
}
else if ((arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && mOkButtonFocus) ||
(arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && !mOkButtonFocus))
{
mOkButtonFocus = !mOkButtonFocus;
mOkButton->setStateSelected(mOkButtonFocus);
mBackButton->setStateSelected(!mOkButtonFocus);
mUsingGamepadGuiCursor = false;
} }
return true; return true;
} }
bool BirthDialog::onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg)
{
if (arg.axis == SDL_CONTROLLER_AXIS_LEFTX || arg.axis == SDL_CONTROLLER_AXIS_LEFTY)
{
mUsingGamepadGuiCursor = true;
}
return false;
}
} }

View File

@ -53,10 +53,15 @@ namespace MWGui
MyGUI::ScrollView* mSpellArea; MyGUI::ScrollView* mSpellArea;
MyGUI::ImageBox* mBirthImage; MyGUI::ImageBox* mBirthImage;
std::vector<MyGUI::Widget*> mSpellItems; std::vector<MyGUI::Widget*> mSpellItems;
MyGUI::Button* mBackButton;
MyGUI::Button* mOkButton;
ESM::RefId mCurrentBirthId; ESM::RefId mCurrentBirthId;
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override;
bool mOkButtonFocus = true;
bool mUsingGamepadGuiCursor = false;
}; };
} }
#endif #endif

View File

@ -143,13 +143,14 @@ namespace MWGui
getWidget(mClassImage, "ClassImage"); getWidget(mClassImage, "ClassImage");
MyGUI::Button* backButton; getWidget(mBackButton, "BackButton");
getWidget(backButton, "BackButton"); mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
MyGUI::Button* okButton; getWidget(mOkButton, "OKButton");
getWidget(okButton, "OKButton"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
if (Settings::gui().mControllerMenus)
mOkButton->setStateSelected(true);
updateClasses(); updateClasses();
updateStats(); updateStats();
@ -316,32 +317,53 @@ namespace MWGui
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
{ {
// Have A button do nothing so mouse controller still works. // Have A button do nothing so mouse controller still works.
if (mUsingGamepadGuiCursor)
return false; return false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_START) if (mOkButtonFocus)
{ onOkClicked(mOkButton);
onOkClicked(nullptr); else
onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_B) else if (arg.button == SDL_CONTROLLER_BUTTON_B)
{ {
onBackClicked(nullptr); onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP) else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
{ {
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mClassList); winMgr->setKeyFocusWidget(mClassList);
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false); winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
mUsingGamepadGuiCursor = false;
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
{ {
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mClassList); winMgr->setKeyFocusWidget(mClassList);
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false); winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
mUsingGamepadGuiCursor = false;
}
else if ((arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && mOkButtonFocus) ||
(arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && !mOkButtonFocus))
{
mOkButtonFocus = !mOkButtonFocus;
mOkButton->setStateSelected(mOkButtonFocus);
mBackButton->setStateSelected(!mOkButtonFocus);
mUsingGamepadGuiCursor = false;
} }
return true; return true;
} }
bool PickClassDialog::onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg)
{
if (arg.axis == SDL_CONTROLLER_AXIS_LEFTX || arg.axis == SDL_CONTROLLER_AXIS_LEFTY)
{
mUsingGamepadGuiCursor = true;
}
return false;
}
/* InfoBoxDialog */ /* InfoBoxDialog */
void InfoBoxDialog::fitToText(MyGUI::TextBox* widget) void InfoBoxDialog::fitToText(MyGUI::TextBox* widget)
@ -569,14 +591,20 @@ namespace MWGui
MyGUI::Button* descriptionButton; MyGUI::Button* descriptionButton;
getWidget(descriptionButton, "DescriptionButton"); getWidget(descriptionButton, "DescriptionButton");
descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked); descriptionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onDescriptionClicked);
mButtons.push_back(descriptionButton);
MyGUI::Button* backButton; MyGUI::Button* backButton;
getWidget(backButton, "BackButton"); getWidget(backButton, "BackButton");
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked); backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked);
mButtons.push_back(backButton);
MyGUI::Button* okButton; MyGUI::Button* okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onOkClicked);
mButtons.push_back(okButton);
if (Settings::gui().mControllerMenus)
okButton->setStateSelected(true);
// Set default skills, attributes // Set default skills, attributes
@ -676,19 +704,57 @@ namespace MWGui
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
{ {
// Have A button do nothing so mouse controller still works. // Have A button do nothing so mouse controller still works.
if (mUsingGamepadGuiCursor)
return false; return false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_START) if (mControllerFocus == 0)
{ onDescriptionClicked(mButtons[0]);
onOkClicked(nullptr); else if (mControllerFocus == 1)
onBackClicked(mButtons[1]);
else
onOkClicked(mButtons[2]);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_B) else if (arg.button == SDL_CONTROLLER_BUTTON_B)
{ {
onBackClicked(nullptr); onBackClicked(mButtons[1]);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP ||
arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
{
mUsingGamepadGuiCursor = false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
{
mButtons[mControllerFocus]->setStateSelected(false);
if (mControllerFocus == 0)
mControllerFocus = mButtons.size() - 1;
else
mControllerFocus--;
mButtons[mControllerFocus]->setStateSelected(true);
mUsingGamepadGuiCursor = false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
{
mButtons[mControllerFocus]->setStateSelected(false);
if (mControllerFocus == mButtons.size() - 1)
mControllerFocus = 0;
else
mControllerFocus++;
mButtons[mControllerFocus]->setStateSelected(true);
mUsingGamepadGuiCursor = false;
} }
return true; return true;
} }
bool CreateClassDialog::onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg)
{
if (arg.axis == SDL_CONTROLLER_AXIS_LEFTX || arg.axis == SDL_CONTROLLER_AXIS_LEFTY)
{
mUsingGamepadGuiCursor = true;
}
return false;
}
// widget controls // widget controls
void CreateClassDialog::onDialogCancel() void CreateClassDialog::onDialogCancel()

View File

@ -138,7 +138,6 @@ namespace MWGui
void onOkClicked(MyGUI::Widget* _sender); void onOkClicked(MyGUI::Widget* _sender);
void onBackClicked(MyGUI::Widget* _sender); void onBackClicked(MyGUI::Widget* _sender);
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
private: private:
void updateClasses(); void updateClasses();
@ -147,11 +146,18 @@ namespace MWGui
MyGUI::ImageBox* mClassImage; MyGUI::ImageBox* mClassImage;
MyGUI::ListBox* mClassList; MyGUI::ListBox* mClassList;
MyGUI::TextBox* mSpecializationName; MyGUI::TextBox* mSpecializationName;
MyGUI::Button* mBackButton;
MyGUI::Button* mOkButton;
Widgets::MWAttributePtr mFavoriteAttribute[2]; Widgets::MWAttributePtr mFavoriteAttribute[2];
Widgets::MWSkillPtr mMajorSkill[5]; Widgets::MWSkillPtr mMajorSkill[5];
Widgets::MWSkillPtr mMinorSkill[5]; Widgets::MWSkillPtr mMinorSkill[5];
ESM::RefId mCurrentClassId; ESM::RefId mCurrentClassId;
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override;
bool mOkButtonFocus = true;
bool mUsingGamepadGuiCursor = false;
}; };
class SelectSpecializationDialog : public WindowModal class SelectSpecializationDialog : public WindowModal
@ -325,6 +331,7 @@ namespace MWGui
private: private:
MyGUI::EditBox* mEditName; MyGUI::EditBox* mEditName;
MyGUI::TextBox* mSpecializationName; MyGUI::TextBox* mSpecializationName;
std::vector<MyGUI::Button*> mButtons;
Widgets::MWAttributePtr mFavoriteAttribute0, mFavoriteAttribute1; Widgets::MWAttributePtr mFavoriteAttribute0, mFavoriteAttribute1;
std::array<Widgets::MWSkillPtr, 5> mMajorSkill; std::array<Widgets::MWSkillPtr, 5> mMajorSkill;
std::array<Widgets::MWSkillPtr, 5> mMinorSkill; std::array<Widgets::MWSkillPtr, 5> mMinorSkill;
@ -342,6 +349,9 @@ namespace MWGui
Widgets::MWSkillPtr mAffectedSkill; Widgets::MWSkillPtr mAffectedSkill;
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override;
int mControllerFocus = 2;
bool mUsingGamepadGuiCursor = false;
}; };
} }
#endif #endif

View File

@ -108,15 +108,16 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu7", "Specials")); MWBase::Environment::get().getWindowManager()->getGameSettingString("sRaceMenu7", "Specials"));
getWidget(mSpellPowerList, "SpellPowerList"); getWidget(mSpellPowerList, "SpellPowerList");
MyGUI::Button* backButton; getWidget(mBackButton, "BackButton");
getWidget(backButton, "BackButton"); mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
MyGUI::Button* okButton; getWidget(mOkButton, "OKButton");
getWidget(okButton, "OKButton"); mOkButton->setCaption(
okButton->setCaption(
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked);
if (Settings::gui().mControllerMenus)
mOkButton->setStateSelected(true);
updateRaces(); updateRaces();
updateSkills(); updateSkills();
@ -467,15 +468,17 @@ namespace MWGui
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
{ {
// Have A button do nothing so mouse controller still works. // Have A button do nothing so mouse controller still works.
if (mUsingGamepadGuiCursor)
return false; return false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_START) if (mOkButtonFocus)
{ onOkClicked(mOkButton);
onOkClicked(nullptr); else
onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_B) else if (arg.button == SDL_CONTROLLER_BUTTON_B)
{ {
onBackClicked(nullptr); onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_X) else if (arg.button == SDL_CONTROLLER_BUTTON_X)
{ {
@ -494,20 +497,22 @@ namespace MWGui
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mRaceList); winMgr->setKeyFocusWidget(mRaceList);
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false); winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
mUsingGamepadGuiCursor = false;
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
{ {
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mRaceList); winMgr->setKeyFocusWidget(mRaceList);
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false); winMgr->injectKeyPress(MyGUI::KeyCode::ArrowDown, 0, false);
mUsingGamepadGuiCursor = false;
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) else if ((arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT && mOkButtonFocus) ||
(arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && !mOkButtonFocus))
{ {
onPreviewScroll(nullptr, 5); mOkButtonFocus = !mOkButtonFocus;
} mOkButton->setStateSelected(mOkButtonFocus);
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) mBackButton->setStateSelected(!mOkButtonFocus);
{ mUsingGamepadGuiCursor = false;
onPreviewScroll(nullptr, -5);
} }
return true; return true;
@ -515,7 +520,11 @@ namespace MWGui
bool RaceDialog::onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) bool RaceDialog::onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg)
{ {
if (arg.axis == SDL_CONTROLLER_AXIS_RIGHTX) if (arg.axis == SDL_CONTROLLER_AXIS_LEFTX || arg.axis == SDL_CONTROLLER_AXIS_LEFTY)
{
mUsingGamepadGuiCursor = true;
}
else if (arg.axis == SDL_CONTROLLER_AXIS_RIGHTX)
{ {
if (arg.value < -1000 || arg.value > 1000) if (arg.value < -1000 || arg.value > 1000)
onPreviewScroll(nullptr, arg.value < 0 ? 1 : -1); onPreviewScroll(nullptr, arg.value < 0 ? 1 : -1);

View File

@ -102,6 +102,8 @@ namespace MWGui
MyGUI::ImageBox* mPreviewImage; MyGUI::ImageBox* mPreviewImage;
MyGUI::ListBox* mRaceList; MyGUI::ListBox* mRaceList;
Gui::ScrollBar* mHeadRotate; Gui::ScrollBar* mHeadRotate;
MyGUI::Button* mBackButton;
MyGUI::Button* mOkButton;
MyGUI::Widget* mSkillList; MyGUI::Widget* mSkillList;
std::vector<MyGUI::Widget*> mSkillItems; std::vector<MyGUI::Widget*> mSkillItems;
@ -122,6 +124,8 @@ namespace MWGui
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override; bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override;
bool mOkButtonFocus = true;
bool mUsingGamepadGuiCursor = false;
}; };
} }
#endif #endif