diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bf160665..3f2ff4686 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ if(NOT MSVC) # TODO: Remove this once mScript KV pairs support const correctness set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=incompatible-pointer-types") endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -Woverloaded-virtual") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -Woverloaded-virtual -Werror=reorder") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-") diff --git a/src/platform/qt/GBAKeyEditor.cpp b/src/platform/qt/GBAKeyEditor.cpp index 2afb546ad..8a8427973 100644 --- a/src/platform/qt/GBAKeyEditor.cpp +++ b/src/platform/qt/GBAKeyEditor.cpp @@ -122,6 +122,7 @@ GBAKeyEditor::GBAKeyEditor(InputController* controller, int type, const QString& connect(key, &KeyEditor::valueChanged, this, &GBAKeyEditor::setNext); connect(key, &KeyEditor::axisChanged, this, &GBAKeyEditor::setNext); connect(key, &KeyEditor::hatChanged, this, &GBAKeyEditor::setNext); + key->setInputController(m_controller); key->installEventFilter(this); } diff --git a/src/platform/qt/KeyEditor.cpp b/src/platform/qt/KeyEditor.cpp index 7d3ba1990..50702da73 100644 --- a/src/platform/qt/KeyEditor.cpp +++ b/src/platform/qt/KeyEditor.cpp @@ -5,6 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "KeyEditor.h" +#include "InputController.h" +#include "input/Gamepad.h" #include "input/GamepadAxisEvent.h" #include "input/GamepadButtonEvent.h" #include "ShortcutController.h" @@ -18,6 +20,7 @@ using namespace QGBA; KeyEditor::KeyEditor(QWidget* parent) : QLineEdit(parent) + , m_controller(nullptr) , m_direction(GamepadAxisEvent::NEUTRAL) , m_hatDirection(GamepadHatEvent::CENTER) { @@ -26,6 +29,13 @@ KeyEditor::KeyEditor(QWidget* parent) m_lastKey.setSingleShot(true); } +void KeyEditor::setInputController(InputController* controller) { + m_controller = controller; + if (m_button) { + updateButtonText(); + } +} + void KeyEditor::setValue(int key) { m_key = key; if (m_button) { @@ -204,10 +214,28 @@ void KeyEditor::updateButtonText() { } } if (m_key >= 0) { - text.append(QString::number(m_key)); + std::shared_ptr gamepad; + if (m_controller && m_controller->gamepadDriver()) { + gamepad = m_controller->gamepadDriver()->activeGamepad(); + } + if (!gamepad) { + text.append(QString::number(m_key)); + } else { + text.append(gamepad->buttonHumanName(m_key)); + } } if (m_direction != GamepadAxisEvent::NEUTRAL) { - text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + QString::number(m_axis)); + QString name; + std::shared_ptr gamepad; + if (m_controller && m_controller->gamepadDriver()) { + gamepad = m_controller->gamepadDriver()->activeGamepad(); + } + if (!gamepad) { + name = QString::number(m_axis); + } else { + name = gamepad->axisHumanName(m_axis); + } + text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + name); } if (text.isEmpty()) { setText(tr("---")); diff --git a/src/platform/qt/KeyEditor.h b/src/platform/qt/KeyEditor.h index c1bb56fae..93af927ac 100644 --- a/src/platform/qt/KeyEditor.h +++ b/src/platform/qt/KeyEditor.h @@ -13,12 +13,16 @@ namespace QGBA { +class InputController; + class KeyEditor : public QLineEdit { Q_OBJECT public: KeyEditor(QWidget* parent = nullptr); + void setInputController(InputController* controller); + int value() const { return m_key; } GamepadAxisEvent::Direction direction() const { return m_direction; } @@ -57,6 +61,7 @@ private: int m_axis = -1; int m_hat = -1; bool m_button = false; + InputController* m_controller; GamepadAxisEvent::Direction m_direction; GamepadHatEvent::Direction m_hatDirection; QTimer m_lastKey; diff --git a/src/platform/qt/ShortcutView.cpp b/src/platform/qt/ShortcutView.cpp index 5efbc4d62..f457263c5 100644 --- a/src/platform/qt/ShortcutView.cpp +++ b/src/platform/qt/ShortcutView.cpp @@ -54,6 +54,7 @@ void ShortcutView::setInputController(InputController* controller) { } m_input = controller; m_input->stealFocus(this); + m_ui.keyEdit->setInputController(controller); } void ShortcutView::load(const QModelIndex& index) { diff --git a/src/platform/qt/input/Gamepad.h b/src/platform/qt/input/Gamepad.h index 1781885cd..9a1cf19ec 100644 --- a/src/platform/qt/input/Gamepad.h +++ b/src/platform/qt/input/Gamepad.h @@ -22,6 +22,9 @@ public: virtual QList currentAxes() = 0; virtual QList currentHats() = 0; + virtual QString buttonHumanName(int) const = 0; + virtual QString axisHumanName(int) const = 0; + virtual int buttonCount() const = 0; virtual int axisCount() const = 0; virtual int hatCount() const = 0; diff --git a/src/platform/qt/input/SDLInputDriver.cpp b/src/platform/qt/input/SDLInputDriver.cpp index e3a77094f..72d148057 100644 --- a/src/platform/qt/input/SDLInputDriver.cpp +++ b/src/platform/qt/input/SDLInputDriver.cpp @@ -257,13 +257,20 @@ QList SDLGamepad::currentButtons() { return {}; } - SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; QList buttons; +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) { + buttons.append(SDL_GameControllerGetButton(controller, static_cast(i))); + } +#else + SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; int numButtons = SDL_JoystickNumButtons(joystick); for (int i = 0; i < numButtons; ++i) { buttons.append(SDL_JoystickGetButton(joystick, i)); } +#endif return buttons; } @@ -273,13 +280,20 @@ QList SDLGamepad::currentAxes() { return {}; } - SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; QList axes; +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + for (int i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) { + axes.append(SDL_GameControllerGetAxis(controller, static_cast(i))); + } +#else + SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; int numAxes = SDL_JoystickNumAxes(joystick); for (int i = 0; i < numAxes; ++i) { axes.append(SDL_JoystickGetAxis(joystick, i)); } +#endif return axes; } @@ -289,24 +303,52 @@ QList SDLGamepad::currentHats() { return {}; } - SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; QList hats; +#if !SDL_VERSION_ATLEAST(2, 0, 0) + SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; int numHats = SDL_JoystickNumHats(joystick); for (int i = 0; i < numHats; ++i) { hats.append(static_cast(SDL_JoystickGetHat(joystick, i))); } +#endif return hats; } +QString SDLGamepad::buttonHumanName(int button) const { +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + const char* name = mSDLButtonName(controller, static_cast(button)); + if (name) { + return QString::fromUtf8(name); + } +#endif + return QString::number(button); +} + +QString SDLGamepad::axisHumanName(int axis) const { +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + const char* name = mSDLAxisName(controller, static_cast(axis)); + if (name) { + return QString::fromUtf8(name); + } +#endif + return QString::number(axis); +} + int SDLGamepad::buttonCount() const { if (!verify()) { return -1; } +#if SDL_VERSION_ATLEAST(2, 0, 0) + return SDL_CONTROLLER_BUTTON_MAX; +#else SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; return SDL_JoystickNumButtons(joystick); +#endif } int SDLGamepad::axisCount() const { @@ -314,8 +356,12 @@ int SDLGamepad::axisCount() const { return -1; } +#if SDL_VERSION_ATLEAST(2, 0, 0) + return SDL_CONTROLLER_AXIS_MAX; +#else SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; return SDL_JoystickNumAxes(joystick); +#endif } int SDLGamepad::hatCount() const { @@ -323,8 +369,12 @@ int SDLGamepad::hatCount() const { return -1; } +#if SDL_VERSION_ATLEAST(2, 0, 0) + return 0; +#else SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; return SDL_JoystickNumHats(joystick); +#endif } QString SDLGamepad::name() const { diff --git a/src/platform/qt/input/SDLInputDriver.h b/src/platform/qt/input/SDLInputDriver.h index d10661ed7..217dc40a7 100644 --- a/src/platform/qt/input/SDLInputDriver.h +++ b/src/platform/qt/input/SDLInputDriver.h @@ -93,6 +93,9 @@ public: int axisCount() const override; int hatCount() const override; + QString buttonHumanName(int) const override; + QString axisHumanName(int) const override; + QString name() const override; QString visibleName() const override; diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index e146bfd90..383775636 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -886,4 +886,211 @@ void mSDLSetScreensaverSuspendable(struct mSDLEvents* events, bool suspendable) SDL_EnableScreenSaver(); } } + +static const char* const buttonNamesXbox360[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "Back", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Xbox", + [SDL_CONTROLLER_BUTTON_START] = "Start", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "LB", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "RB", + [SDL_CONTROLLER_BUTTON_MISC1] = "Misc", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +}; + +#if SDL_VERSION_ATLEAST(2, 0, 12) +static const char* const buttonNamesXboxOne[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "View", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Xbox", + [SDL_CONTROLLER_BUTTON_START] = "Menu", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "LB", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "RB", + [SDL_CONTROLLER_BUTTON_MISC1] = "Share", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +}; + +static const char* const buttonNamesPlayStation[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "×", + [SDL_CONTROLLER_BUTTON_B] = "○", + [SDL_CONTROLLER_BUTTON_X] = "□", + [SDL_CONTROLLER_BUTTON_Y] = "△", + [SDL_CONTROLLER_BUTTON_BACK] = "Share", + [SDL_CONTROLLER_BUTTON_GUIDE] = "PS", + [SDL_CONTROLLER_BUTTON_START] = "Options", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "L3", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "R3", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "L1", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "R1", + [SDL_CONTROLLER_BUTTON_MISC1] = "Misc", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +}; + +static const char* const buttonNamesNintedo[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "-", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Home", + [SDL_CONTROLLER_BUTTON_START] = "+", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "L", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "R", + [SDL_CONTROLLER_BUTTON_MISC1] = "Share", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +}; + +static const char* const buttonNamesGeneric[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "Select", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Guide", + [SDL_CONTROLLER_BUTTON_START] = "Start", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "LB", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "RB", + [SDL_CONTROLLER_BUTTON_MISC1] = "Misc", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +}; +#endif + +const char* mSDLButtonName(SDL_GameController* controller, SDL_GameControllerButton button) { + const char* const* buttonNames = buttonNamesXbox360; + +#if SDL_VERSION_ATLEAST(2, 0, 12) + switch (SDL_GameControllerGetType(controller)) { + case SDL_CONTROLLER_TYPE_XBOX360: + buttonNames = buttonNamesXbox360; + break; + case SDL_CONTROLLER_TYPE_XBOXONE: + buttonNames = buttonNamesXboxOne; + break; + case SDL_CONTROLLER_TYPE_PS3: + case SDL_CONTROLLER_TYPE_PS4: +#if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_PS5: +#endif + buttonNames = buttonNamesPlayStation; + break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + buttonNames = buttonNamesNintedo; + break; + default: + buttonNames = buttonNamesGeneric; + break; + } +#endif + + switch (button) { + case SDL_CONTROLLER_BUTTON_DPAD_UP: + return "D↑"; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + return "D↓"; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + return "D←"; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + return "D→"; + default: + return buttonNames[button]; + case SDL_CONTROLLER_BUTTON_INVALID: + case SDL_CONTROLLER_BUTTON_MAX: + break; + } + return NULL; +} + +static const char* const axisNamesXbox[SDL_CONTROLLER_AXIS_MAX] = { + [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = "LT", + [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = "RT", +}; + +#if SDL_VERSION_ATLEAST(2, 0, 12) +static const char* const axisNamesPlayStation[SDL_CONTROLLER_AXIS_MAX] = { + [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = "L3", + [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = "R3", +}; + +static const char* const axisNamesNintendo[SDL_CONTROLLER_AXIS_MAX] = { + [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = "ZL", + [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = "ZR", +}; +#endif + +const char* mSDLAxisName(SDL_GameController* controller, SDL_GameControllerAxis axis) { + const char* const* axisNames = axisNamesXbox; + +#if SDL_VERSION_ATLEAST(2, 0, 12) + switch (SDL_GameControllerGetType(controller)) { + case SDL_CONTROLLER_TYPE_XBOX360: + case SDL_CONTROLLER_TYPE_XBOXONE: + default: + axisNames = axisNamesXbox; + break; + case SDL_CONTROLLER_TYPE_PS3: + case SDL_CONTROLLER_TYPE_PS4: +#if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_PS5: +#endif + axisNames = axisNamesPlayStation; + break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + axisNames = axisNamesNintendo; + break; + } +#endif + + switch (axis) { + case SDL_CONTROLLER_AXIS_LEFTX: + return "X"; + case SDL_CONTROLLER_AXIS_LEFTY: + return "Y"; + case SDL_CONTROLLER_AXIS_RIGHTX: + return "RX"; + case SDL_CONTROLLER_AXIS_RIGHTY: + return "RY"; + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: + return axisNames[axis]; + case SDL_CONTROLLER_AXIS_INVALID: + case SDL_CONTROLLER_AXIS_MAX: + break; + } + return NULL; +} + #endif diff --git a/src/platform/sdl/sdl-events.h b/src/platform/sdl/sdl-events.h index e49613932..741503be4 100644 --- a/src/platform/sdl/sdl-events.h +++ b/src/platform/sdl/sdl-events.h @@ -126,6 +126,9 @@ void mSDLHandleEvent(struct mCoreThread* context, struct mSDLPlayer* sdlContext, void mSDLSuspendScreensaver(struct mSDLEvents*); void mSDLResumeScreensaver(struct mSDLEvents*); void mSDLSetScreensaverSuspendable(struct mSDLEvents*, bool suspendable); + +const char* mSDLButtonName(SDL_GameController*, SDL_GameControllerButton); +const char* mSDLAxisName(SDL_GameController*, SDL_GameControllerAxis); #endif CXX_GUARD_END