Qt: Refactor to make non-SDL gamepad input possible
@@ -96,10 +96,8 @@ GameController* controller = static_cast<GameController*>(context->userData);
controller->m_audioProcessor->setInput(context); context->gba->luminanceSource = &controller->m_lux; context->gba->rtcSource = &controller->m_rtc; -#ifdef BUILD_SDL context->gba->rumble = controller->m_inputController->rumble(); context->gba->rotationSource = controller->m_inputController->rotationSource(); -#endif controller->gameStarted(context); };@@ -154,10 +152,7 @@ connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start()));
connect(this, SIGNAL(gameStopped(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gameUnpaused(GBAThread*)), m_audioProcessor, SLOT(start())); - -#ifdef BUILD_SDL - connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(testSDLEvents())); -#endif + connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents())); } GameController::~GameController() {@@ -283,9 +278,7 @@ if (!m_patch.isNull()) {
m_threadContext.patch = VFileOpen(m_patch.toLocal8Bit().constData(), O_RDONLY); } -#ifdef BUILD_SDL m_inputController->recalibrateAxes(); -#endif if (!GBAThreadStart(&m_threadContext)) { m_gameOpen = false;@@ -663,9 +656,7 @@ }
void GameController::updateKeys() { int activeKeys = m_activeKeys; -#ifdef BUILD_SDL activeKeys |= m_activeButtons; -#endif activeKeys &= ~m_inactiveKeys; m_threadContext.activeKeys = activeKeys; }@@ -705,13 +696,11 @@ m_logLevels &= ~levels;
threadContinue(); } -#ifdef BUILD_SDL -void GameController::testSDLEvents() { +void GameController::pollEvents() { if (!m_inputController) { return; } - m_activeButtons = m_inputController->testSDLEvents(); + m_activeButtons = m_inputController->pollEvents(); updateKeys(); } -#endif
@@ -146,13 +146,7 @@
private slots: void crashGame(const QString& crashMessage); -#ifdef BUILD_SDL - void testSDLEvents(); - -private: - GBASDLEvents m_sdlEvents; - int m_activeButtons; -#endif + void pollEvents(); private: void updateKeys();@@ -163,6 +157,7 @@ GBAThread m_threadContext;
GBAVideoSoftwareRenderer* m_renderer; GBACheatDevice m_cheatDevice; int m_activeKeys; + int m_activeButtons; int m_inactiveKeys; int m_logLevels;
@@ -11,7 +11,7 @@ using namespace QGBA;
QEvent::Type GamepadAxisEvent::s_type = QEvent::None; -GamepadAxisEvent::GamepadAxisEvent(int axis, Direction direction, bool isNew, InputController* controller) +GamepadAxisEvent::GamepadAxisEvent(int axis, Direction direction, bool isNew, int type, InputController* controller) : QEvent(Type()) , m_axis(axis) , m_direction(direction)@@ -20,11 +20,9 @@ , m_controller(controller)
, m_key(GBA_KEY_NONE) { ignore(); -#ifdef BUILD_SDL if (controller) { - m_key = GBAInputMapAxis(controller->map(), SDL_BINDING_BUTTON, axis, direction * INT_MAX); + m_key = GBAInputMapAxis(controller->map(), type, axis, direction * INT_MAX); } -#endif } QEvent::Type GamepadAxisEvent::Type() {
@@ -24,7 +24,7 @@ POSITIVE = 1,
NEGATIVE = -1 }; - GamepadAxisEvent(int axis, Direction direction, bool isNew, InputController* controller = nullptr); + GamepadAxisEvent(int axis, Direction direction, bool isNew, int type, InputController* controller = nullptr); int axis() const { return m_axis; } Direction direction() const { return m_direction; }
@@ -12,18 +12,16 @@
QEvent::Type GamepadButtonEvent::s_downType = QEvent::None; QEvent::Type GamepadButtonEvent::s_upType = QEvent::None; -GamepadButtonEvent::GamepadButtonEvent(QEvent::Type type, int button, InputController* controller) - : QEvent(type) +GamepadButtonEvent::GamepadButtonEvent(QEvent::Type pressType, int button, int type, InputController* controller) + : QEvent(pressType) , m_button(button) , m_controller(controller) , m_key(GBA_KEY_NONE) { ignore(); -#ifdef BUILD_SDL if (controller) { - m_key = GBAInputMapKey(controller->map(), SDL_BINDING_BUTTON, button); + m_key = GBAInputMapKey(controller->map(), type, button); } -#endif } QEvent::Type GamepadButtonEvent::Down() {
@@ -18,7 +18,7 @@ class InputController;
class GamepadButtonEvent : public QEvent { public: - GamepadButtonEvent(Type type, int button, InputController* controller = nullptr); + GamepadButtonEvent(Type pressType, int button, int type, InputController* controller = nullptr); int value() const { return m_button; } GBAKey gbaKey() const { return m_key; }
@@ -43,12 +43,16 @@ }
++s_sdlInited; m_sdlPlayer.bindings = &m_inputMap; GBASDLInitBindings(&m_inputMap); +#endif m_gamepadTimer = new QTimer(this); - connect(m_gamepadTimer, SIGNAL(timeout()), this, SLOT(testGamepad())); +#ifdef BUILD_SDL + connect(m_gamepadTimer, &QTimer::timeout, [this]() { + testGamepad(SDL_BINDING_BUTTON); + }); +#endif m_gamepadTimer->setInterval(50); m_gamepadTimer->start(); -#endif GBAInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_X, GBA_KEY_A); GBAInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Z, GBA_KEY_B);@@ -103,9 +107,7 @@ }
void InputController::loadProfile(uint32_t type, const QString& profile) { GBAInputProfileLoad(&m_inputMap, type, m_config->input(), profile.toLocal8Bit().constData()); -#ifdef BUILD_SDL recalibrateAxes(); -#endif } void InputController::saveConfiguration() {@@ -144,74 +146,122 @@ #endif
return 0; } -#ifdef BUILD_SDL QStringList InputController::connectedGamepads(uint32_t type) const { UNUSED(type); - if (type != SDL_BINDING_BUTTON) { - return QStringList(); - } - QStringList pads; - for (size_t i = 0; i < s_sdlEvents.nJoysticks; ++i) { - const char* name; +#ifdef BUILD_SDL + if (type == SDL_BINDING_BUTTON) { + QStringList pads; + for (size_t i = 0; i < s_sdlEvents.nJoysticks; ++i) { + const char* name; #if SDL_VERSION_ATLEAST(2, 0, 0) - name = SDL_JoystickName(s_sdlEvents.joysticks[i]); + name = SDL_JoystickName(s_sdlEvents.joysticks[i]); #else - name = SDL_JoystickName(SDL_JoystickIndex(s_sdlEvents.joysticks[i])); + name = SDL_JoystickName(SDL_JoystickIndex(s_sdlEvents.joysticks[i])); #endif - if (name) { - pads.append(QString(name)); - } else { - pads.append(QString()); + if (name) { + pads.append(QString(name)); + } else { + pads.append(QString()); + } } + return pads; } - return pads; +#endif + + return QStringList(); +} + +int InputController::gamepad(uint32_t type) const { +#ifdef BUILD_SDL + if (type == SDL_BINDING_BUTTON) { + return m_sdlPlayer.joystickIndex; + } +#endif + return 0; +} + +void InputController::setGamepad(uint32_t type, int index) { +#ifdef BUILD_SDL + if (type == SDL_BINDING_BUTTON) { + GBASDLPlayerChangeJoystick(&s_sdlEvents, &m_sdlPlayer, index); + } +#endif } void InputController::setPreferredGamepad(uint32_t type, const QString& device) { if (!m_config) { return; } - GBAInputSetPreferredDevice(m_config->input(), type, m_sdlPlayer.playerId, device.toLocal8Bit().constData()); + GBAInputSetPreferredDevice(m_config->input(), type, m_playerId, device.toLocal8Bit().constData()); } GBARumble* InputController::rumble() { - return &m_sdlPlayer.rumble.d; +#ifdef BUILD_SDL + if (m_playerAttached) { + return &m_sdlPlayer.rumble.d; + } +#endif + return nullptr; } GBARotationSource* InputController::rotationSource() { - return &m_sdlPlayer.rotation.d; +#ifdef BUILD_SDL + if (m_playerAttached) { + return &m_sdlPlayer.rotation.d; + } +#endif + return nullptr; } void InputController::registerTiltAxisX(int axis) { - m_sdlPlayer.rotation.axisX = axis; +#ifdef BUILD_SDL + if (m_playerAttached) { + m_sdlPlayer.rotation.axisX = axis; + } +#endif } + void InputController::registerTiltAxisY(int axis) { - m_sdlPlayer.rotation.axisY = axis; +#ifdef BUILD_SDL + if (m_playerAttached) { + m_sdlPlayer.rotation.axisY = axis; + } +#endif } + void InputController::registerGyroAxisX(int axis) { - m_sdlPlayer.rotation.gyroX = axis; +#ifdef BUILD_SDL + if (m_playerAttached) { + m_sdlPlayer.rotation.gyroX = axis; + } +#endif } + void InputController::registerGyroAxisY(int axis) { - m_sdlPlayer.rotation.gyroY = axis; +#ifdef BUILD_SDL + if (m_playerAttached) { + m_sdlPlayer.rotation.gyroY = axis; + } +#endif } float InputController::gyroSensitivity() const { - return m_sdlPlayer.rotation.gyroSensitivity; +#ifdef BUILD_SDL + if (m_playerAttached) { + return m_sdlPlayer.rotation.gyroSensitivity; + } +#endif + return 0; } void InputController::setGyroSensitivity(float sensitivity) { - m_sdlPlayer.rotation.gyroSensitivity = sensitivity; -} -#else -GBARumble* InputController::rumble() { - return nullptr; -} - -GBARotationSource* InputController::rotationSource() { - return nullptr; -} +#ifdef BUILD_SDL + if (m_playerAttached) { + m_sdlPlayer.rotation.gyroSensitivity = sensitivity; + } #endif +} GBAKey InputController::mapKeyboard(int key) const { return GBAInputMapKey(&m_inputMap, KEYBOARD, key);@@ -221,104 +271,119 @@ void InputController::bindKey(uint32_t type, int key, GBAKey gbaKey) {
return GBAInputBindKey(&m_inputMap, type, key, gbaKey); } -#ifdef BUILD_SDL -int InputController::testSDLEvents() { - SDL_Joystick* joystick = m_sdlPlayer.joystick; - SDL_JoystickUpdate(); - int numButtons = SDL_JoystickNumButtons(joystick); +int InputController::pollEvents() { int activeButtons = 0; - int i; - for (i = 0; i < numButtons; ++i) { - GBAKey key = GBAInputMapKey(&m_inputMap, SDL_BINDING_BUTTON, i); - if (key == GBA_KEY_NONE) { - continue; - } - if (hasPendingEvent(key)) { - continue; - } - if (SDL_JoystickGetButton(joystick, i)) { - activeButtons |= 1 << key; - } - } - int numHats = SDL_JoystickNumHats(joystick); - for (i = 0; i < numHats; ++i) { - int hat = SDL_JoystickGetHat(joystick, i); - if (hat & SDL_HAT_UP) { - activeButtons |= 1 << GBA_KEY_UP; - } - if (hat & SDL_HAT_LEFT) { - activeButtons |= 1 << GBA_KEY_LEFT; - } - if (hat & SDL_HAT_DOWN) { - activeButtons |= 1 << GBA_KEY_DOWN; +#ifdef BUILD_SDL + if (m_playerAttached) { + SDL_Joystick* joystick = m_sdlPlayer.joystick; + SDL_JoystickUpdate(); + int numButtons = SDL_JoystickNumButtons(joystick); + int i; + for (i = 0; i < numButtons; ++i) { + GBAKey key = GBAInputMapKey(&m_inputMap, SDL_BINDING_BUTTON, i); + if (key == GBA_KEY_NONE) { + continue; + } + if (hasPendingEvent(key)) { + continue; + } + if (SDL_JoystickGetButton(joystick, i)) { + activeButtons |= 1 << key; + } } - if (hat & SDL_HAT_RIGHT) { - activeButtons |= 1 << GBA_KEY_RIGHT; + int numHats = SDL_JoystickNumHats(joystick); + for (i = 0; i < numHats; ++i) { + int hat = SDL_JoystickGetHat(joystick, i); + if (hat & SDL_HAT_UP) { + activeButtons |= 1 << GBA_KEY_UP; + } + if (hat & SDL_HAT_LEFT) { + activeButtons |= 1 << GBA_KEY_LEFT; + } + if (hat & SDL_HAT_DOWN) { + activeButtons |= 1 << GBA_KEY_DOWN; + } + if (hat & SDL_HAT_RIGHT) { + activeButtons |= 1 << GBA_KEY_RIGHT; + } } - } - int numAxes = SDL_JoystickNumAxes(joystick); - for (i = 0; i < numAxes; ++i) { - int value = SDL_JoystickGetAxis(joystick, i); + int numAxes = SDL_JoystickNumAxes(joystick); + for (i = 0; i < numAxes; ++i) { + int value = SDL_JoystickGetAxis(joystick, i); - enum GBAKey key = GBAInputMapAxis(&m_inputMap, SDL_BINDING_BUTTON, i, value); - if (key != GBA_KEY_NONE) { - activeButtons |= 1 << key; + enum GBAKey key = GBAInputMapAxis(&m_inputMap, SDL_BINDING_BUTTON, i, value); + if (key != GBA_KEY_NONE) { + activeButtons |= 1 << key; + } } } +#endif return activeButtons; } -QSet<int> InputController::activeGamepadButtons() { - SDL_Joystick* joystick = m_sdlPlayer.joystick; - SDL_JoystickUpdate(); - int numButtons = SDL_JoystickNumButtons(joystick); +QSet<int> InputController::activeGamepadButtons(int type) { QSet<int> activeButtons; - int i; - for (i = 0; i < numButtons; ++i) { - if (SDL_JoystickGetButton(joystick, i)) { - activeButtons.insert(i); +#ifdef BUILD_SDL + if (m_playerAttached && type == SDL_BINDING_BUTTON) { + SDL_Joystick* joystick = m_sdlPlayer.joystick; + SDL_JoystickUpdate(); + int numButtons = SDL_JoystickNumButtons(joystick); + int i; + for (i = 0; i < numButtons; ++i) { + if (SDL_JoystickGetButton(joystick, i)) { + activeButtons.insert(i); + } } } +#endif return activeButtons; } void InputController::recalibrateAxes() { - SDL_Joystick* joystick = m_sdlPlayer.joystick; - SDL_JoystickUpdate(); - int numAxes = SDL_JoystickNumAxes(joystick); - if (numAxes < 1) { - return; +#ifdef BUILD_SDL + if (m_playerAttached) { + SDL_Joystick* joystick = m_sdlPlayer.joystick; + SDL_JoystickUpdate(); + int numAxes = SDL_JoystickNumAxes(joystick); + if (numAxes < 1) { + return; + } + m_deadzones.resize(numAxes); + int i; + for (i = 0; i < numAxes; ++i) { + m_deadzones[i] = SDL_JoystickGetAxis(joystick, i); + } } - m_deadzones.resize(numAxes); - int i; - for (i = 0; i < numAxes; ++i) { - m_deadzones[i] = SDL_JoystickGetAxis(joystick, i); - } +#endif } -QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes() { - SDL_Joystick* joystick = m_sdlPlayer.joystick; - SDL_JoystickUpdate(); - int numAxes = SDL_JoystickNumAxes(joystick); +QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes(int type) { QSet<QPair<int, GamepadAxisEvent::Direction>> activeAxes; - if (numAxes < 1) { - return activeAxes; - } - m_deadzones.resize(numAxes); - int i; - for (i = 0; i < numAxes; ++i) { - int32_t axis = SDL_JoystickGetAxis(joystick, i); - axis -= m_deadzones[i]; - if (axis >= AXIS_THRESHOLD || axis <= -AXIS_THRESHOLD) { - activeAxes.insert(qMakePair(i, axis > 0 ? GamepadAxisEvent::POSITIVE : GamepadAxisEvent::NEGATIVE)); +#ifdef BUILD_SDL + if (m_playerAttached && type == SDL_BINDING_BUTTON) { + SDL_Joystick* joystick = m_sdlPlayer.joystick; + SDL_JoystickUpdate(); + int numAxes = SDL_JoystickNumAxes(joystick); + if (numAxes < 1) { + return activeAxes; + } + m_deadzones.resize(numAxes); + int i; + for (i = 0; i < numAxes; ++i) { + int32_t axis = SDL_JoystickGetAxis(joystick, i); + axis -= m_deadzones[i]; + if (axis >= AXIS_THRESHOLD || axis <= -AXIS_THRESHOLD) { + activeAxes.insert(qMakePair(i, axis > 0 ? GamepadAxisEvent::POSITIVE : GamepadAxisEvent::NEGATIVE)); + } } } +#endif return activeAxes; } void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction direction, GBAKey key) { - const GBAAxis* old = GBAInputQueryAxis(&m_inputMap, SDL_BINDING_BUTTON, axis); + const GBAAxis* old = GBAInputQueryAxis(&m_inputMap, type, axis); GBAAxis description = { GBA_KEY_NONE, GBA_KEY_NONE, -AXIS_THRESHOLD, AXIS_THRESHOLD }; if (old) { description = *old;@@ -335,17 +400,15 @@ break;
default: return; } - GBAInputBindAxis(&m_inputMap, SDL_BINDING_BUTTON, axis, &description); + GBAInputBindAxis(&m_inputMap, type, axis, &description); } -#endif -void InputController::testGamepad() { -#ifdef BUILD_SDL - auto activeAxes = activeGamepadAxes(); +void InputController::testGamepad(int type) { + auto activeAxes = activeGamepadAxes(type); auto oldAxes = m_activeAxes; m_activeAxes = activeAxes; - auto activeButtons = activeGamepadButtons(); + auto activeButtons = activeGamepadButtons(type); auto oldButtons = m_activeButtons; m_activeButtons = activeButtons;@@ -359,7 +422,7 @@
for (auto& axis : m_activeAxes) { bool newlyAboveThreshold = activeAxes.contains(axis); if (newlyAboveThreshold) { - GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, newlyAboveThreshold, this); + GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, newlyAboveThreshold, type, this); postPendingEvent(event->gbaKey()); QApplication::sendEvent(QApplication::focusWidget(), event); if (!event->isAccepted()) {@@ -368,7 +431,7 @@ }
} } for (auto axis : oldAxes) { - GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, false, this); + GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, false, type, this); clearPendingEvent(event->gbaKey()); QApplication::sendEvent(QApplication::focusWidget(), event); }@@ -381,7 +444,7 @@ activeButtons.subtract(oldButtons);
oldButtons.subtract(m_activeButtons); for (int button : activeButtons) { - GamepadButtonEvent* event = new GamepadButtonEvent(GamepadButtonEvent::Down(), button, this); + GamepadButtonEvent* event = new GamepadButtonEvent(GamepadButtonEvent::Down(), button, type, this); postPendingEvent(event->gbaKey()); QApplication::sendEvent(QApplication::focusWidget(), event); if (!event->isAccepted()) {@@ -389,11 +452,10 @@ clearPendingEvent(event->gbaKey());
} } for (int button : oldButtons) { - GamepadButtonEvent* event = new GamepadButtonEvent(GamepadButtonEvent::Up(), button, this); + GamepadButtonEvent* event = new GamepadButtonEvent(GamepadButtonEvent::Up(), button, type, this); clearPendingEvent(event->gbaKey()); QApplication::sendEvent(QApplication::focusWidget(), event); } -#endif } void InputController::postPendingEvent(GBAKey key) {
@@ -52,19 +52,18 @@ void bindKey(uint32_t type, int key, GBAKey);
const GBAInputMap* map() const { return &m_inputMap; } -#ifdef BUILD_SDL - static const int32_t AXIS_THRESHOLD = 0x3000; + int pollEvents(); - int testSDLEvents(); - QSet<int> activeGamepadButtons(); - QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(); + static const int32_t AXIS_THRESHOLD = 0x3000; + QSet<int> activeGamepadButtons(int type); + QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(int type); void recalibrateAxes(); void bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction, GBAKey); QStringList connectedGamepads(uint32_t type) const; - int gamepad(uint32_t type) const { return m_sdlPlayer.joystickIndex; } - void setGamepad(uint32_t type, int index) { GBASDLPlayerChangeJoystick(&s_sdlEvents, &m_sdlPlayer, index); } + int gamepad(uint32_t type) const; + void setGamepad(uint32_t type, int index); void setPreferredGamepad(uint32_t type, const QString& device); void registerTiltAxisX(int axis);@@ -74,13 +73,12 @@ void registerGyroAxisY(int axis);
float gyroSensitivity() const; void setGyroSensitivity(float sensitivity); -#endif GBARumble* rumble(); GBARotationSource* rotationSource(); public slots: - void testGamepad(); + void testGamepad(int type); private: void postPendingEvent(GBAKey);@@ -97,8 +95,9 @@ static int s_sdlInited;
static GBASDLEvents s_sdlEvents; GBASDLPlayer m_sdlPlayer; bool m_playerAttached; +#endif + QVector<int> m_deadzones; -#endif QSet<int> m_activeButtons; QSet<QPair<int, GamepadAxisEvent::Direction>> m_activeAxes;