all repos — mgba @ 711c7e9903a1ffe9bc00d30bc1b3f51295aac747

mGBA Game Boy Advance Emulator

Qt: Refactor to make non-SDL gamepad input possible
Jeffrey Pfau jeffrey@endrift.com
Mon, 27 Apr 2015 01:40:00 -0700
commit

711c7e9903a1ffe9bc00d30bc1b3f51295aac747

parent

6ebef8dc167f862eaf84cb706c961a2f23fa722a

M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -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
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -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;
M src/platform/qt/GamepadAxisEvent.cppsrc/platform/qt/GamepadAxisEvent.cpp

@@ -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() {
M src/platform/qt/GamepadAxisEvent.hsrc/platform/qt/GamepadAxisEvent.h

@@ -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; }
M src/platform/qt/GamepadButtonEvent.cppsrc/platform/qt/GamepadButtonEvent.cpp

@@ -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() {
M src/platform/qt/GamepadButtonEvent.hsrc/platform/qt/GamepadButtonEvent.h

@@ -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; }
M src/platform/qt/InputController.cppsrc/platform/qt/InputController.cpp

@@ -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) {
M src/platform/qt/InputController.hsrc/platform/qt/InputController.h

@@ -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;