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->eventListChangePosition += MyGUI::newDelegate(this, &BirthDialog::onSelectBirth);
MyGUI::Button* backButton;
getWidget(backButton, "BackButton");
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
getWidget(mBackButton, "BackButton");
mBackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
MyGUI::Button* okButton;
getWidget(okButton, "OKButton");
okButton->setCaption(
getWidget(mOkButton, "OKButton");
mOkButton->setCaption(
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();
updateSpells();
@ -277,29 +278,50 @@ namespace MWGui
if (arg.button == SDL_CONTROLLER_BUTTON_A)
{
// Have A button do nothing so mouse controller still works.
return false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_START)
{
onOkClicked(nullptr);
if (mUsingGamepadGuiCursor)
return false;
if (mOkButtonFocus)
onOkClicked(mOkButton);
else
onBackClicked(mBackButton);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_B)
{
onBackClicked(nullptr);
onBackClicked(mBackButton);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
{
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mBirthList);
winMgr->injectKeyPress(MyGUI::KeyCode::ArrowUp, 0, false);
mUsingGamepadGuiCursor = false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
{
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setKeyFocusWidget(mBirthList);
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;
}
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::ImageBox* mBirthImage;
std::vector<MyGUI::Widget*> mSpellItems;
MyGUI::Button* mBackButton;
MyGUI::Button* mOkButton;
ESM::RefId mCurrentBirthId;
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) override;
bool mOkButtonFocus = true;
bool mUsingGamepadGuiCursor = false;
};
}
#endif

View File

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

View File

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

View File

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

View File

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