mirror of https://github.com/mgba-emu/mgba.git
Qt: Refactor to make non-SDL gamepad input possible
This commit is contained in:
parent
6ebef8dc16
commit
711c7e9903
|
@ -96,10 +96,8 @@ GameController::GameController(QObject* parent)
|
|||
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 @@ GameController::GameController(QObject* parent)
|
|||
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 @@ void GameController::openGame() {
|
|||
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::setFakeEpoch(const QDateTime& time) {
|
|||
|
||||
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 @@ void GameController::disableLogLevel(int 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 @@ public slots:
|
|||
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 @@ private:
|
|||
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 @@ GamepadAxisEvent::GamepadAxisEvent(int axis, Direction direction, bool isNew, In
|
|||
, 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 @@ public:
|
|||
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 @@ using namespace QGBA;
|
|||
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 @@ InputController::InputController(int playerId, QObject* parent)
|
|||
++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::loadConfiguration(uint32_t type) {
|
|||
|
||||
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,13 +146,11 @@ const char* InputController::profileForType(uint32_t type) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
QStringList InputController::connectedGamepads(uint32_t type) const {
|
||||
UNUSED(type);
|
||||
if (type != SDL_BINDING_BUTTON) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
if (type == SDL_BINDING_BUTTON) {
|
||||
QStringList pads;
|
||||
for (size_t i = 0; i < s_sdlEvents.nJoysticks; ++i) {
|
||||
const char* name;
|
||||
|
@ -167,51 +167,101 @@ QStringList InputController::connectedGamepads(uint32_t type) const {
|
|||
}
|
||||
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() {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
return &m_sdlPlayer.rumble.d;
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GBARotationSource* InputController::rotationSource() {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
return &m_sdlPlayer.rotation.d;
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void InputController::registerTiltAxisX(int axis) {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.axisX = axis;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::registerTiltAxisY(int axis) {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.axisY = axis;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::registerGyroAxisX(int axis) {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroX = axis;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::registerGyroAxisY(int axis) {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroY = axis;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float InputController::gyroSensitivity() const {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
return m_sdlPlayer.rotation.gyroSensitivity;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputController::setGyroSensitivity(float sensitivity) {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroSensitivity = sensitivity;
|
||||
}
|
||||
#else
|
||||
GBARumble* InputController::rumble() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GBARotationSource* InputController::rotationSource() {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
GBAKey InputController::mapKeyboard(int key) const {
|
||||
return GBAInputMapKey(&m_inputMap, KEYBOARD, key);
|
||||
|
@ -221,12 +271,13 @@ void InputController::bindKey(uint32_t type, int key, GBAKey gbaKey) {
|
|||
return GBAInputBindKey(&m_inputMap, type, key, gbaKey);
|
||||
}
|
||||
|
||||
int InputController::pollEvents() {
|
||||
int activeButtons = 0;
|
||||
#ifdef BUILD_SDL
|
||||
int InputController::testSDLEvents() {
|
||||
if (m_playerAttached) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numButtons = SDL_JoystickNumButtons(joystick);
|
||||
int activeButtons = 0;
|
||||
int i;
|
||||
for (i = 0; i < numButtons; ++i) {
|
||||
GBAKey key = GBAInputMapKey(&m_inputMap, SDL_BINDING_BUTTON, i);
|
||||
|
@ -266,24 +317,32 @@ int InputController::testSDLEvents() {
|
|||
activeButtons |= 1 << key;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return activeButtons;
|
||||
}
|
||||
|
||||
QSet<int> InputController::activeGamepadButtons() {
|
||||
QSet<int> InputController::activeGamepadButtons(int type) {
|
||||
QSet<int> activeButtons;
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached && type == SDL_BINDING_BUTTON) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numButtons = SDL_JoystickNumButtons(joystick);
|
||||
QSet<int> activeButtons;
|
||||
int i;
|
||||
for (i = 0; i < numButtons; ++i) {
|
||||
if (SDL_JoystickGetButton(joystick, i)) {
|
||||
activeButtons.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return activeButtons;
|
||||
}
|
||||
|
||||
void InputController::recalibrateAxes() {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numAxes = SDL_JoystickNumAxes(joystick);
|
||||
|
@ -296,12 +355,16 @@ void InputController::recalibrateAxes() {
|
|||
m_deadzones[i] = SDL_JoystickGetAxis(joystick, i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes() {
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes(int type) {
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> activeAxes;
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached && type == SDL_BINDING_BUTTON) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numAxes = SDL_JoystickNumAxes(joystick);
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> activeAxes;
|
||||
if (numAxes < 1) {
|
||||
return activeAxes;
|
||||
}
|
||||
|
@ -314,11 +377,13 @@ QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes
|
|||
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 @@ void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direct
|
|||
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 @@ void InputController::testGamepad() {
|
|||
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 @@ void InputController::testGamepad() {
|
|||
}
|
||||
}
|
||||
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 @@ void InputController::testGamepad() {
|
|||
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 @@ void InputController::testGamepad() {
|
|||
}
|
||||
}
|
||||
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 @@ public:
|
|||
|
||||
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 @@ public:
|
|||
|
||||
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,9 +95,10 @@ private:
|
|||
static GBASDLEvents s_sdlEvents;
|
||||
GBASDLPlayer m_sdlPlayer;
|
||||
bool m_playerAttached;
|
||||
QVector<int> m_deadzones;
|
||||
#endif
|
||||
|
||||
QVector<int> m_deadzones;
|
||||
|
||||
QSet<int> m_activeButtons;
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> m_activeAxes;
|
||||
QTimer* m_gamepadTimer;
|
||||
|
|
Loading…
Reference in New Issue