1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-10-16 13:16:33 +00:00

Add overlay showing what controller buttons do

This commit is contained in:
Andrew Lanzone 2025-05-16 21:41:28 -07:00
parent 8c2ecc2a88
commit c0694d3c0e
40 changed files with 330 additions and 27 deletions

View file

@ -44,7 +44,7 @@ add_openmw_dir (mwgui
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours statswatcher draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours statswatcher
postprocessorhud settings postprocessorhud settings controllerbuttonsoverlay
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

View file

@ -386,6 +386,7 @@ namespace MWBase
virtual MWGui::WindowBase* getActiveControllerWindow() = 0; virtual MWGui::WindowBase* getActiveControllerWindow() = 0;
/// Cycle to the next window to receive controller events /// Cycle to the next window to receive controller events
virtual void cycleActiveControllerWindow(bool next) = 0; virtual void cycleActiveControllerWindow(bool next) = 0;
virtual void updateControllerButtonsOverlay() = 0;
// Used in Lua bindings // Used in Lua bindings
virtual const std::vector<MWGui::GuiMode>& getGuiModeStack() const = 0; virtual const std::vector<MWGui::GuiMode>& getGuiModeStack() const = 0;

View file

@ -273,6 +273,11 @@ namespace MWGui
mSpellArea->setViewOffset(MyGUI::IntPoint(0, 0)); mSpellArea->setViewOffset(MyGUI::IntPoint(0, 0));
} }
std::string BirthDialog::getButtonStr()
{
return "(A) #{sSelect} (X) #{sDone} (B) #{sBack}";
}
bool BirthDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool BirthDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -290,6 +295,10 @@ namespace MWGui
{ {
onBackClicked(mBackButton); onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
{
onOkClicked(mOkButton);
}
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();

View file

@ -38,6 +38,8 @@ namespace MWGui
*/ */
EventHandle_WindowBase eventDone; EventHandle_WindowBase eventDone;
std::string getButtonStr() override;
protected: protected:
void onSelectBirth(MyGUI::ListBox* _sender, size_t _index); void onSelectBirth(MyGUI::ListBox* _sender, size_t _index);

View file

@ -222,6 +222,14 @@ namespace MWGui
} }
} }
std::string BookWindow::getButtonStr()
{
if (mTakeButton->getVisible())
return "(A) #{sTake} (LB) #{sPrev} (RB) #{sNext} (B) #{sClose}";
else
return "(LB) #{sPrev} (RB) #{sNext} (B) #{sClose}";
}
bool BookWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool BookWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)

View file

@ -21,6 +21,7 @@ namespace MWGui
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
std::string_view getWindowIdForLua() const override { return "Book"; } std::string_view getWindowIdForLua() const override { return "Book"; }
std::string getButtonStr() override;
protected: protected:
void onNextPageButtonClicked(MyGUI::Widget* sender); void onNextPageButtonClicked(MyGUI::Widget* sender);

View file

@ -77,6 +77,11 @@ namespace MWGui
center(); center();
} }
std::string GenerateClassResultDialog::getButtonStr()
{
return "(A) #{sSelect} (B) #{sBack}";
}
bool GenerateClassResultDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool GenerateClassResultDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -312,6 +317,11 @@ namespace MWGui
setClassImage(mClassImage, mCurrentClassId); setClassImage(mClassImage, mCurrentClassId);
} }
std::string PickClassDialog::getButtonStr()
{
return "(A) #{sSelect} (X) #{sDone} (B) #{sBack}";
}
bool PickClassDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool PickClassDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -329,6 +339,10 @@ namespace MWGui
{ {
onBackClicked(mBackButton); onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
{
onOkClicked(mOkButton);
}
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();
@ -476,6 +490,11 @@ namespace MWGui
} }
} }
std::string InfoBoxDialog::getButtonStr()
{
return "(A) #{sSelect}";
}
bool InfoBoxDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool InfoBoxDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -699,6 +718,11 @@ namespace MWGui
MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {}))); MyGUI::UString(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", {})));
} }
std::string CreateClassDialog::getButtonStr()
{
return "(A) #{sSelect} (X) #{sDone} (B) #{sCancel}";
}
bool CreateClassDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool CreateClassDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -718,6 +742,10 @@ namespace MWGui
{ {
onBackClicked(mButtons[1]); onBackClicked(mButtons[1]);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
{
onOkClicked(mButtons[2]);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP ||
arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
{ {
@ -942,6 +970,11 @@ namespace MWGui
return true; return true;
} }
std::string SelectSpecializationDialog::getButtonStr()
{
return "(A) #{sSelect} (B) #{sCancel}";
}
bool SelectSpecializationDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool SelectSpecializationDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_B) if (arg.button == SDL_CONTROLLER_BUTTON_B)
@ -1004,6 +1037,11 @@ namespace MWGui
return true; return true;
} }
std::string SelectAttributeDialog::getButtonStr()
{
return "(A) #{sSelect} (B) #{sCancel}";
}
bool SelectAttributeDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool SelectAttributeDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_B) if (arg.button == SDL_CONTROLLER_BUTTON_B)
@ -1078,6 +1116,11 @@ namespace MWGui
return true; return true;
} }
std::string SelectSkillDialog::getButtonStr()
{
return "(A) #{sSelect} (B) #{sCancel}";
}
bool SelectSkillDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool SelectSkillDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_B) if (arg.button == SDL_CONTROLLER_BUTTON_B)

View file

@ -40,6 +40,8 @@ namespace MWGui
*/ */
EventHandle_Int eventButtonSelected; EventHandle_Int eventButtonSelected;
std::string getButtonStr() override;
protected: protected:
void onButtonClicked(MyGUI::Widget* _sender); void onButtonClicked(MyGUI::Widget* _sender);
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
@ -91,6 +93,8 @@ namespace MWGui
*/ */
EventHandle_WindowBase eventDone; EventHandle_WindowBase eventDone;
std::string getButtonStr() override;
protected: protected:
void onOkClicked(MyGUI::Widget* _sender); void onOkClicked(MyGUI::Widget* _sender);
void onBackClicked(MyGUI::Widget* _sender); void onBackClicked(MyGUI::Widget* _sender);
@ -132,6 +136,8 @@ namespace MWGui
*/ */
EventHandle_WindowBase eventDone; EventHandle_WindowBase eventDone;
std::string getButtonStr() override;
protected: protected:
void onSelectClass(MyGUI::ListBox* _sender, size_t _index); void onSelectClass(MyGUI::ListBox* _sender, size_t _index);
void onAccept(MyGUI::ListBox* _sender, size_t _index); void onAccept(MyGUI::ListBox* _sender, size_t _index);
@ -183,6 +189,8 @@ namespace MWGui
*/ */
EventHandle_Void eventItemSelected; EventHandle_Void eventItemSelected;
std::string getButtonStr() override;
protected: protected:
void onSpecializationClicked(MyGUI::Widget* _sender); void onSpecializationClicked(MyGUI::Widget* _sender);
void onCancelClicked(MyGUI::Widget* _sender); void onCancelClicked(MyGUI::Widget* _sender);
@ -217,6 +225,8 @@ namespace MWGui
*/ */
EventHandle_Void eventItemSelected; EventHandle_Void eventItemSelected;
std::string getButtonStr() override;
protected: protected:
void onAttributeClicked(Widgets::MWAttributePtr _sender); void onAttributeClicked(Widgets::MWAttributePtr _sender);
void onCancelClicked(MyGUI::Widget* _sender); void onCancelClicked(MyGUI::Widget* _sender);
@ -249,6 +259,8 @@ namespace MWGui
*/ */
EventHandle_Void eventItemSelected; EventHandle_Void eventItemSelected;
std::string getButtonStr() override;
protected: protected:
void onSkillClicked(Widgets::MWSkillPtr _sender); void onSkillClicked(Widgets::MWSkillPtr _sender);
void onCancelClicked(MyGUI::Widget* _sender); void onCancelClicked(MyGUI::Widget* _sender);
@ -310,6 +322,8 @@ namespace MWGui
*/ */
EventHandle_WindowBase eventDone; EventHandle_WindowBase eventDone;
std::string getButtonStr() override;
protected: protected:
void onOkClicked(MyGUI::Widget* _sender); void onOkClicked(MyGUI::Widget* _sender);
void onBackClicked(MyGUI::Widget* _sender); void onBackClicked(MyGUI::Widget* _sender);

View file

@ -72,6 +72,11 @@ namespace MWGui
eventOkClicked(); eventOkClicked();
} }
std::string ConfirmationDialog::getButtonStr()
{
return "(A) #{sOk} (B) #{sCancel}";
}
bool ConfirmationDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool ConfirmationDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)

View file

@ -20,6 +20,8 @@ namespace MWGui
EventHandle_Void eventOkClicked; EventHandle_Void eventOkClicked;
EventHandle_Void eventCancelClicked; EventHandle_Void eventCancelClicked;
std::string getButtonStr() override;
private: private:
MyGUI::EditBox* mMessage; MyGUI::EditBox* mMessage;
MyGUI::Button* mOkButton; MyGUI::Button* mOkButton;

View file

@ -352,6 +352,14 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
} }
std::string ContainerWindow::getButtonStr()
{
if (mDisposeCorpseButton->getVisible())
return "(A) #{sTake} (X) #{sTakeAll} (LB) #{sDisposeofCorpse} (Y) #{sInfo} [LT] #{sInventory} (B) #{sClose}";
else
return "(A) #{sTake} (X) #{sTakeAll} (Y) #{sInfo} [LT] #{sInventory} (B) #{sClose}";
}
bool ContainerWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool ContainerWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)

View file

@ -40,6 +40,7 @@ namespace MWGui
std::string_view getWindowIdForLua() const override { return "Container"; } std::string_view getWindowIdForLua() const override { return "Container"; }
std::string getButtonStr() override;
void setActiveControllerWindow(bool active) override; void setActiveControllerWindow(bool active) override;
private: private:

View file

@ -0,0 +1,26 @@
#include "controllerbuttonsoverlay.hpp"
#include <MyGUI_Button.h>
#include <MyGUI_EditBox.h>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
namespace MWGui
{
ControllerButtonsOverlay::ControllerButtonsOverlay()
: WindowBase("openmw_controllerbuttons.layout")
{
getWidget(mButtonStr, "ButtonStr");
}
void ControllerButtonsOverlay::setButtonStr(const std::string& buttonStr)
{
mButtonStr->setCaptionWithReplacing(buttonStr);
// int height = mMessage->getTextSize().height + 60;
// int width = mMessage->getTextSize().width + 24;
// mMainWidget->setSize(width, height);
// mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height + 24);
}
}

View file

@ -0,0 +1,20 @@
#ifndef MWGUI_CONTROLLERBUTTONSOVERLAY_H
#define MWGUI_CONTROLLERBUTTONSOVERLAY_H
#include "windowbase.hpp"
namespace MWGui
{
class ControllerButtonsOverlay : public WindowBase
{
public:
ControllerButtonsOverlay();
void setButtonStr(const std::string& buttonStr);
private:
MyGUI::TextBox* mButtonStr;
};
}
#endif

View file

@ -309,6 +309,8 @@ namespace
notifyQuests(getWidget<MyGUI::Widget>(QuestsList)); notifyQuests(getWidget<MyGUI::Widget>(QuestsList));
else else
notifyTopics(getWidget<MyGUI::Widget>(TopicsList)); notifyTopics(getWidget<MyGUI::Widget>(TopicsList));
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
} }
void pushBook(Book& book, unsigned int page) void pushBook(Book& book, unsigned int page)
@ -340,6 +342,7 @@ namespace
{ {
setVisible(CloseBTN, mStates.size() < 2); setVisible(CloseBTN, mStates.size() < 2);
setVisible(JournalBTN, mStates.size() >= 2); setVisible(JournalBTN, mStates.size() >= 2);
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
} }
void updateShowingPages() void updateShowingPages()
@ -382,6 +385,8 @@ namespace
setText(PageOneNum, page + 1); setText(PageOneNum, page + 1);
setText(PageTwoNum, page + 2); setText(PageTwoNum, page + 2);
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
} }
void notifyKeyPress(MyGUI::Widget* sender, MyGUI::KeyCode key, MyGUI::Char character) void notifyKeyPress(MyGUI::Widget* sender, MyGUI::KeyCode key, MyGUI::Char character)
@ -409,6 +414,7 @@ namespace
mTopicsMode = false; mTopicsMode = false;
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page")); MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
} }
void notifyTopicSelected(const std::string& topicIdString, int id) void notifyTopicSelected(const std::string& topicIdString, int id)
@ -441,6 +447,7 @@ namespace
mOptionsMode = false; mOptionsMode = false;
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page")); MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
} }
void notifyOptions(MyGUI::Widget* _sender) void notifyOptions(MyGUI::Widget* _sender)
@ -662,6 +669,16 @@ namespace
} }
} }
std::string getButtonStr() override
{
if (mOptionsMode)
return "(A) #{sSelect} (X) Quests (Y) #{sTopics} (B) #{sBack}";
else if (mStates.size() > 1)
return "(A) #{sSelect} (LB) #{sPrev} (RB) #{sNext} (X) Quests (Y) #{sTopics} (B) #{sBack}";
else
return "(A) #{sSelect} (LB) #{sPrev} (RB) #{sNext} (X) Quests (Y) #{sTopics} (B) #{sClose}";
}
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) // A: Mouse click or Select if (arg.button == SDL_CONTROLLER_BUTTON_A) // A: Mouse click or Select

View file

@ -207,6 +207,11 @@ namespace MWGui
} }
} }
std::string MainMenu::getButtonStr()
{
return "";
}
bool MainMenu::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool MainMenu::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
// REMOVEME // REMOVEME

View file

@ -55,6 +55,8 @@ namespace MWGui
bool exit() override; bool exit() override;
std::string getButtonStr() override;
private: private:
const VFS::Manager* mVFS; const VFS::Manager* mVFS;

View file

@ -439,6 +439,11 @@ namespace MWGui
return mButtonPressed; return mButtonPressed;
} }
std::string InteractiveMessageBox::getButtonStr()
{
return "InteractiveMessageBox (A) #{sOk}";
}
bool InteractiveMessageBox::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool InteractiveMessageBox::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)

View file

@ -103,6 +103,7 @@ namespace MWGui
bool mMarkedToDelete; bool mMarkedToDelete;
std::string getButtonStr() override;
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
private: private:

View file

@ -463,6 +463,11 @@ namespace MWGui
} }
} }
std::string RaceDialog::getButtonStr()
{
return "(A) #{sSelect} (Y) #{sSex} (LB) #{sHair} (RB) #{sFace} (X) #{sDone} (B) #{sBack}";
}
bool RaceDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool RaceDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -481,6 +486,10 @@ namespace MWGui
onBackClicked(mBackButton); onBackClicked(mBackButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_X) else if (arg.button == SDL_CONTROLLER_BUTTON_X)
{
onOkClicked(mOkButton);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_Y)
{ {
onSelectNextGender(nullptr); onSelectNextGender(nullptr);
} }

View file

@ -65,6 +65,8 @@ namespace MWGui
*/ */
EventHandle_WindowBase eventDone; EventHandle_WindowBase eventDone;
std::string getButtonStr() override;
protected: protected:
void onPreviewScroll(MyGUI::Widget* _sender, int _delta); void onPreviewScroll(MyGUI::Widget* _sender, int _delta);
void onHeadRotate(MyGUI::ScrollBar* _sender, size_t _position); void onHeadRotate(MyGUI::ScrollBar* _sender, size_t _position);

View file

@ -537,6 +537,11 @@ namespace MWGui
MyGUI::IntPoint(0, static_cast<int>(mSkillView->getViewOffset().top + _rel * 0.3))); MyGUI::IntPoint(0, static_cast<int>(mSkillView->getViewOffset().top + _rel * 0.3)));
} }
std::string ReviewDialog::getButtonStr()
{
return "(A) #{sSelect} (X) #{sDone} (B) #{sBack}";
}
bool ReviewDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool ReviewDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -567,14 +572,14 @@ namespace MWGui
} }
return true; return true;
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_START)
{
onOkClicked(mButtons[5]);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_B) else if (arg.button == SDL_CONTROLLER_BUTTON_B)
{ {
onBackClicked(mButtons[4]); onBackClicked(mButtons[4]);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_X)
{
onOkClicked(mButtons[5]);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP || else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP ||
arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) arg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
{ {

View file

@ -62,6 +62,8 @@ namespace MWGui
EventHandle_Int eventActivateDialog; EventHandle_Int eventActivateDialog;
std::string getButtonStr() override;
protected: protected:
void onOkClicked(MyGUI::Widget* _sender); void onOkClicked(MyGUI::Widget* _sender);
void onBackClicked(MyGUI::Widget* _sender); void onBackClicked(MyGUI::Widget* _sender);

View file

@ -504,6 +504,14 @@ namespace MWGui
mScreenshot->setRenderItemTexture(mScreenshotTexture.get()); mScreenshot->setRenderItemTexture(mScreenshotTexture.get());
} }
std::string SaveGameDialog::getButtonStr()
{
if (mSaving)
return "(A) #{sSelect} (B) #{sClose}";
else
return "(A) #{sSelect} (Y) Select Character (B) #{sClose}";
}
bool SaveGameDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool SaveGameDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)
@ -521,6 +529,16 @@ namespace MWGui
{ {
onCancelButtonClicked(mCancelButton); onCancelButtonClicked(mCancelButton);
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_Y)
{
uint32_t index = mCharacterSelection->getIndexSelected();
if (index >= mCharacterSelection->getItemCount() - 1)
index = 0;
else
index++;
mCharacterSelection->setIndexSelected(index);
mUsingGamepadGuiCursor = false;
}
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();
@ -543,26 +561,6 @@ namespace MWGui
mCancelButton->setStateSelected(!mOkButtonFocus); mCancelButton->setStateSelected(!mOkButtonFocus);
mUsingGamepadGuiCursor = false; mUsingGamepadGuiCursor = false;
} }
else if (arg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
{
uint32_t index = mCharacterSelection->getIndexSelected();
if (index <= 0)
index = mCharacterSelection->getItemCount() - 1;
else
index--;
mCharacterSelection->setIndexSelected(index);
mUsingGamepadGuiCursor = false;
}
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
{
uint32_t index = mCharacterSelection->getIndexSelected();
if (index >= mCharacterSelection->getItemCount() - 1)
index = 0;
else
index++;
mCharacterSelection->setIndexSelected(index);
mUsingGamepadGuiCursor = false;
}
return true; return true;
} }

View file

@ -24,6 +24,8 @@ namespace MWGui
void setLoadOrSave(bool load); void setLoadOrSave(bool load);
std::string getButtonStr() override;
private: private:
void confirmDeleteSave(); void confirmDeleteSave();

View file

@ -126,6 +126,14 @@ namespace MWGui
BookWindowBase::onClose(); BookWindowBase::onClose();
} }
std::string ScrollWindow::getButtonStr()
{
if (mTakeButton->getVisible())
return "(A) #{sTake} (RS) #{sScrolldown} (B) #{sClose}";
else
return "(A) #{sTake} (RS) #{sScrolldown} (B) #{sClose}";
}
bool ScrollWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool ScrollWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)

View file

@ -25,6 +25,8 @@ namespace MWGui
std::string_view getWindowIdForLua() const override { return "Scroll"; } std::string_view getWindowIdForLua() const override { return "Scroll"; }
std::string getButtonStr() override;
protected: protected:
void onCloseButtonClicked(MyGUI::Widget* _sender); void onCloseButtonClicked(MyGUI::Widget* _sender);
void onTakeButtonClicked(MyGUI::Widget* _sender); void onTakeButtonClicked(MyGUI::Widget* _sender);

View file

@ -468,7 +468,7 @@ namespace MWGui
void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender)
{ {
setVisible(false); MWBase::Environment::get().getWindowManager()->toggleSettingsWindow();
} }
void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index) void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index)
@ -1129,6 +1129,11 @@ namespace MWGui
mControlsBox->setViewOffset(MyGUI::IntPoint(0, 0)); mControlsBox->setViewOffset(MyGUI::IntPoint(0, 0));
} }
std::string SettingsWindow::getButtonStr()
{
return "(A) #{sSelect} (LB) #{sPrev} Tab (RB) #{sNext} Tab (B) #{sOk}";
}
bool SettingsWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool SettingsWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_B) if (arg.button == SDL_CONTROLLER_BUTTON_B)

View file

@ -26,6 +26,7 @@ namespace MWGui
void onResChange(int, int) override; void onResChange(int, int) override;
std::string getButtonStr() override;
bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override; bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) override;
protected: protected:

View file

@ -83,6 +83,11 @@ namespace MWGui
mTextEdit->setCaption(text); mTextEdit->setCaption(text);
} }
std::string TextInputDialog::getButtonStr()
{
return "(A) #{sOk}";
}
bool TextInputDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool TextInputDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)

View file

@ -24,6 +24,8 @@ namespace MWGui
*/ */
EventHandle_WindowBase eventDone; EventHandle_WindowBase eventDone;
std::string getButtonStr() override;
protected: protected:
void onOkClicked(MyGUI::Widget* _sender); void onOkClicked(MyGUI::Widget* _sender);
void onTextAccepted(MyGUI::EditBox* _sender); void onTextAccepted(MyGUI::EditBox* _sender);

View file

@ -332,6 +332,19 @@ namespace MWGui
} }
} }
std::string WaitDialog::getButtonStr()
{
if (mSleeping)
{
if (mUntilHealedButton->getVisible())
return "(X) #{sUntilHealed} (A) #{sRest} (B) #{sCancel}";
else
return "(A) #{sRest} (B) #{sCancel}";
}
else
return "(A) #{sWait} (B) #{sCancel}";
}
bool WaitDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) bool WaitDialog::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{ {
if (arg.button == SDL_CONTROLLER_BUTTON_A) if (arg.button == SDL_CONTROLLER_BUTTON_A)

View file

@ -47,6 +47,8 @@ namespace MWGui
std::string_view getWindowIdForLua() const override { return "WaitDialog"; } std::string_view getWindowIdForLua() const override { return "WaitDialog"; }
std::string getButtonStr() override;
protected: protected:
MyGUI::TextBox* mDateTimeText; MyGUI::TextBox* mDateTimeText;
MyGUI::TextBox* mRestText; MyGUI::TextBox* mRestText;

View file

@ -147,6 +147,7 @@ void WindowModal::onOpen()
void WindowModal::onClose() void WindowModal::onClose()
{ {
MWBase::Environment::get().getWindowManager()->removeCurrentModal(this); MWBase::Environment::get().getWindowManager()->removeCurrentModal(this);
MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay();
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget); MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
} }

View file

@ -62,6 +62,7 @@ namespace MWGui
// REMOVEME // REMOVEME
// virtual bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) = 0; // virtual bool onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) = 0;
// virtual bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) = 0; // virtual bool onControllerThumbstickEvent(const SDL_ControllerAxisEvent& arg) = 0;
virtual std::string getButtonStr() { return ""; }
virtual void setActiveControllerWindow(bool active) { mActiveControllerWindow = active; } virtual void setActiveControllerWindow(bool active) { mActiveControllerWindow = active; }
protected: protected:

View file

@ -181,6 +181,7 @@ namespace MWGui
, mPostProcessorHud(nullptr) , mPostProcessorHud(nullptr)
, mJailScreen(nullptr) , mJailScreen(nullptr)
, mContainerWindow(nullptr) , mContainerWindow(nullptr)
, mControllerButtonsOverlay(nullptr)
, mTranslationDataStorage(translationDataStorage) , mTranslationDataStorage(translationDataStorage)
, mInputBlocker(nullptr) , mInputBlocker(nullptr)
, mHudEnabled(true) , mHudEnabled(true)
@ -505,6 +506,10 @@ namespace MWGui
mWindows.push_back(std::move(postProcessorHud)); mWindows.push_back(std::move(postProcessorHud));
trackWindow(mPostProcessorHud, makePostprocessorWindowSettingValues()); trackWindow(mPostProcessorHud, makePostprocessorWindowSettingValues());
auto controllerButtonsOverlay = std::make_unique<ControllerButtonsOverlay>();
mControllerButtonsOverlay = controllerButtonsOverlay.get();
mWindows.push_back(std::move(controllerButtonsOverlay));
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>( mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>(
{}, 0, 0, w, h, MyGUI::Align::Stretch, "InputBlocker"); {}, 0, 0, w, h, MyGUI::Align::Stretch, "InputBlocker");
@ -662,6 +667,9 @@ namespace MWGui
&& !(mForceHidden & GW_Inventory) && (mAllowed & GW_Inventory)); && !(mForceHidden & GW_Inventory) && (mAllowed & GW_Inventory));
mSpellWindow->setVisible( mSpellWindow->setVisible(
mSpellWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Magic) && (mAllowed & GW_Magic)); mSpellWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Magic) && (mAllowed & GW_Magic));
if (Settings::gui().mControllerMenus && mControllerButtonsOverlay)
mControllerButtonsOverlay->setVisible(false);
return; return;
} }
else if (getMode() != GM_Inventory) else if (getMode() != GM_Inventory)
@ -691,6 +699,8 @@ namespace MWGui
mStatsWindow->setVisible(eff & GW_Stats); mStatsWindow->setVisible(eff & GW_Stats);
} }
updateControllerButtonsOverlay();
switch (mode) switch (mode)
{ {
// FIXME: refactor chargen windows to use modes properly (or not use them at all) // FIXME: refactor chargen windows to use modes properly (or not use them at all)
@ -720,6 +730,7 @@ namespace MWGui
return; return;
dialog->setVisible(false); dialog->setVisible(false);
mGarbageDialogs.push_back(std::move(dialog)); mGarbageDialogs.push_back(std::move(dialog));
updateControllerButtonsOverlay();
} }
void WindowManager::exitCurrentGuiMode() void WindowManager::exitCurrentGuiMode()
@ -871,10 +882,13 @@ namespace MWGui
{ {
GuiMode mode = mGuiModes.back(); GuiMode mode = mGuiModes.back();
GuiModeState& state = mGuiModeStates[mode]; GuiModeState& state = mGuiModeStates[mode];
if (state.mWindows.size() == 0)
return nullptr;
int activeIndex = std::clamp(mActiveControllerWindows[mode], 0, (int)state.mWindows.size() - 1); int activeIndex = std::clamp(mActiveControllerWindows[mode], 0, (int)state.mWindows.size() - 1);
// REMOVEME // REMOVEME
Log(Debug::Error) << "getActiveControllerWindow: " << state.mWindows.size() << " windows in state, mActiveControllerWindows[mode] = " << mActiveControllerWindows[mode]; Log(Debug::Error) << "getActiveControllerWindow: " << state.mWindows.size() << " windows in state, mActiveControllerWindows[mode] = " << mActiveControllerWindows[mode] << ", activeIndex=" << activeIndex;
// If the active window is no longer visible, find the next visible window. // If the active window is no longer visible, find the next visible window.
if (!state.mWindows[activeIndex]->isVisible()) if (!state.mWindows[activeIndex]->isVisible())
@ -1001,6 +1015,9 @@ namespace MWGui
if (isSettingsWindowVisible()) if (isSettingsWindowVisible())
mSettingsWindow->onFrame(frameDuration); mSettingsWindow->onFrame(frameDuration);
if (mControllerButtonsOverlay && mControllerButtonsOverlay->isVisible())
mControllerButtonsOverlay->onFrame(frameDuration);
if (!gameRunning) if (!gameRunning)
return; return;
@ -2046,6 +2063,7 @@ namespace MWGui
if (!window->exit()) if (!window->exit())
return; return;
window->setVisible(false); window->setVisible(false);
updateControllerButtonsOverlay();
} }
} }
@ -2059,6 +2077,8 @@ namespace MWGui
mKeyboardNavigation->setModalWindow(input->mMainWidget); mKeyboardNavigation->setModalWindow(input->mMainWidget);
mKeyboardNavigation->setDefaultFocus(input->mMainWidget, input->getDefaultKeyFocus()); mKeyboardNavigation->setDefaultFocus(input->mMainWidget, input->getDefaultKeyFocus());
updateControllerButtonsOverlay();
} }
void WindowManager::removeCurrentModal(WindowModal* input) void WindowManager::removeCurrentModal(WindowModal* input)
@ -2526,4 +2546,34 @@ namespace MWGui
} }
return res; return res;
} }
void WindowManager::updateControllerButtonsOverlay()
{
if (!Settings::gui().mControllerMenus ||!mControllerButtonsOverlay)
return;
WindowBase* topWin = this->getActiveControllerWindow();
if (!topWin || !topWin->isVisible())
{
// REMOVEME
Log(Debug::Error) << "WindowManager::updateControllerButtonsOverlay: hiding overlay";
mControllerButtonsOverlay->setVisible(false);
return;
}
std::string buttonStr = topWin->getButtonStr();
// REMOVEME
Log(Debug::Error) << "WindowManager::updateControllerButtonsOverlay: showing overlay: " << buttonStr;
if (buttonStr.length() > 0)
{
mControllerButtonsOverlay->setButtonStr(buttonStr);
mControllerButtonsOverlay->setVisible(true);
}
else
{
// REMOVEME
Log(Debug::Error) << "WindowManager::updateControllerButtonsOverlay: ...psych, hiding it";
mControllerButtonsOverlay->setVisible(false);
}
}
} }

View file

@ -25,6 +25,7 @@
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
#include "charactercreation.hpp" #include "charactercreation.hpp"
#include "controllerbuttonsoverlay.hpp"
#include "draganddrop.hpp" #include "draganddrop.hpp"
#include "mapwindow.hpp" #include "mapwindow.hpp"
#include "messagebox.hpp" #include "messagebox.hpp"
@ -118,6 +119,7 @@ namespace MWGui
class PostProcessorHud; class PostProcessorHud;
class JailScreen; class JailScreen;
class KeyboardNavigation; class KeyboardNavigation;
class ControllerButtonsOverlay;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -389,6 +391,7 @@ namespace MWGui
WindowBase* getActiveControllerWindow() override; WindowBase* getActiveControllerWindow() override;
void cycleActiveControllerWindow(bool next) override; void cycleActiveControllerWindow(bool next) override;
void updateControllerButtonsOverlay() override;
// Used in Lua bindings // Used in Lua bindings
const std::vector<GuiMode>& getGuiModeStack() const override { return mGuiModes; } const std::vector<GuiMode>& getGuiModeStack() const override { return mGuiModes; }
@ -457,6 +460,7 @@ namespace MWGui
PostProcessorHud* mPostProcessorHud; PostProcessorHud* mPostProcessorHud;
JailScreen* mJailScreen; JailScreen* mJailScreen;
ContainerWindow* mContainerWindow; ContainerWindow* mContainerWindow;
ControllerButtonsOverlay* mControllerButtonsOverlay;
std::vector<std::unique_ptr<WindowBase>> mWindows; std::vector<std::unique_ptr<WindowBase>> mWindows;

View file

@ -147,6 +147,7 @@ set(BUILTIN_DATA_FILES
mygui/openmw_console.layout mygui/openmw_console.layout
mygui/openmw_console.skin.xml mygui/openmw_console.skin.xml
mygui/openmw_container_window.layout mygui/openmw_container_window.layout
mygui/openmw_controllerbuttons.layout
mygui/openmw_count_window.layout mygui/openmw_count_window.layout
mygui/openmw_dialogue_window.layout mygui/openmw_dialogue_window.layout
mygui/openmw_dialogue_window.skin.xml mygui/openmw_dialogue_window.skin.xml

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="BlackBG" layer="ControllerButtons" position="0 0 800 48" align="HStretch Bottom" name="_Main">
<Property key="Visible" value="false"/>
<Widget type="HBox" position="0 0 800 48" align="Center Bottom">
<Widget type="Spacer"/>
<Widget type="TextBox" skin="HeaderText" position="0 0 800 48" name="ButtonStr" align="HStretch">
<Property key="Caption" value="[LT] #{sMenuPrevXbox} (LB) #{sPrev} (A) #{sSelect} (B) #{sBack} (RB) #{sNext} [RT] #{sMenuNextXbox}"/>
<Property key="TextAlign" value="Center"/>
<Property key="TextShadow" value="true"/>
<Property key="TextShadowColour" value="0 0 0"/>
<Property key="ReadOnly" value="true"/>
</Widget>
<Widget type="Spacer"/>
</Widget>
</Widget>
</MyGUI>

View file

@ -20,6 +20,7 @@
<Layer name="Console" overlapped="true" pick="true"/> <Layer name="Console" overlapped="true" pick="true"/>
<Layer name="Modal" overlapped="true" pick="true"/> <Layer name="Modal" overlapped="true" pick="true"/>
<Layer name="Popup" overlapped="true" pick="true"/> <Layer name="Popup" overlapped="true" pick="true"/>
<Layer name="ControllerButtons" overlapped="true" pick="false"/>
<Layer name="Notification" overlapped="false" pick="false"/> <Layer name="Notification" overlapped="false" pick="false"/>
<Layer name="Video" overlapped="false" pick="true"/> <Layer name="Video" overlapped="false" pick="true"/>
<Layer name="InputBlocker" overlapped="false" pick="true"/> <Layer name="InputBlocker" overlapped="false" pick="true"/>