mirror of https://github.com/mgba-emu/mgba.git
Qt: Finish input driver separation
This commit is contained in:
parent
547c9269fa
commit
0c77227e06
|
@ -32,6 +32,10 @@
|
|||
#include "DiscordCoordinator.h"
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "input/SDLInputDriver.h"
|
||||
#endif
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
static GBAApp* g_app = nullptr;
|
||||
|
@ -309,6 +313,25 @@ bool GBAApp::waitOnJob(qint64 jobId, QObject* context, std::function<void ()> ca
|
|||
return true;
|
||||
}
|
||||
|
||||
void GBAApp::suspendScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
SDL::suspendScreensaver();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAApp::resumeScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
SDL::resumeScreensaver();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAApp::setScreensaverSuspendable(bool suspendable) {
|
||||
UNUSED(suspendable);
|
||||
#ifdef BUILD_SDL
|
||||
SDL::setScreensaverSuspendable(suspendable);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAApp::cleanupAfterUpdate() {
|
||||
// Remove leftover updater if there's one present
|
||||
QDir configDir(ConfigController::configDir());
|
||||
|
|
|
@ -86,6 +86,10 @@ public slots:
|
|||
void restartForUpdate();
|
||||
Window* newWindow();
|
||||
|
||||
void suspendScreensaver();
|
||||
void resumeScreensaver();
|
||||
void setScreensaverSuspendable(bool);
|
||||
|
||||
signals:
|
||||
void jobFinished(qint64 jobId);
|
||||
|
||||
|
|
|
@ -398,14 +398,13 @@ void GBAKeyEditor::setLocation(QWidget* widget, qreal x, qreal y) {
|
|||
|
||||
#ifdef BUILD_SDL
|
||||
void GBAKeyEditor::updateJoysticks() {
|
||||
m_controller->updateJoysticks();
|
||||
m_controller->recalibrateAxes();
|
||||
m_controller->update();
|
||||
|
||||
// Block the currentIndexChanged signal while rearranging the combo box
|
||||
auto wasBlocked = m_profileSelect->blockSignals(true);
|
||||
m_profileSelect->clear();
|
||||
m_profileSelect->addItems(m_controller->connectedGamepads(m_type));
|
||||
int activeGamepad = m_controller->gamepad(m_type);
|
||||
int activeGamepad = m_controller->gamepadIndex(m_type);
|
||||
m_profileSelect->setCurrentIndex(activeGamepad);
|
||||
m_profileSelect->blockSignals(wasBlocked);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "InputController.h"
|
||||
|
||||
#include "ConfigController.h"
|
||||
#include "input/Gamepad.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
#include "InputProfile.h"
|
||||
#include "LogController.h"
|
||||
|
@ -24,11 +25,6 @@
|
|||
|
||||
using namespace QGBA;
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
int InputController::s_sdlInited = 0;
|
||||
mSDLEvents InputController::s_sdlEvents;
|
||||
#endif
|
||||
|
||||
InputController::InputController(int playerId, QWidget* topLevel, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_playerId(playerId)
|
||||
|
@ -37,23 +33,17 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
|
|||
{
|
||||
mInputMapInit(&m_inputMap, &GBAInputInfo);
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
if (s_sdlInited == 0) {
|
||||
mSDLInitEvents(&s_sdlEvents);
|
||||
}
|
||||
++s_sdlInited;
|
||||
m_sdlPlayer.bindings = &m_inputMap;
|
||||
updateJoysticks();
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
connect(&m_gamepadTimer, &QTimer::timeout, [this]() {
|
||||
testGamepad(SDL_BINDING_BUTTON);
|
||||
for (auto& driver : m_inputDrivers) {
|
||||
if (driver->supportsPolling() && driver->supportsGamepads()) {
|
||||
testGamepad(driver->type());
|
||||
}
|
||||
}
|
||||
if (m_playerId == 0) {
|
||||
updateJoysticks();
|
||||
update();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
m_gamepadTimer.setInterval(50);
|
||||
m_gamepadTimer.start();
|
||||
|
||||
|
@ -140,43 +130,32 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
|
|||
|
||||
InputController::~InputController() {
|
||||
mInputMapDeinit(&m_inputMap);
|
||||
}
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
mSDLDetachPlayer(&s_sdlEvents, &m_sdlPlayer);
|
||||
void InputController::addInputDriver(std::shared_ptr<InputDriver> driver) {
|
||||
m_inputDrivers[driver->type()] = driver;
|
||||
if (!m_sensorDriver && driver->supportsSensors()) {
|
||||
m_sensorDriver = driver->type();
|
||||
}
|
||||
|
||||
--s_sdlInited;
|
||||
if (s_sdlInited == 0) {
|
||||
mSDLDeinitEvents(&s_sdlEvents);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::setConfiguration(ConfigController* config) {
|
||||
m_config = config;
|
||||
loadConfiguration(KEYBOARD);
|
||||
#ifdef BUILD_SDL
|
||||
mSDLEventsLoadConfig(&s_sdlEvents, config->input());
|
||||
if (!m_playerAttached) {
|
||||
m_playerAttached = mSDLAttachPlayer(&s_sdlEvents, &m_sdlPlayer);
|
||||
for (auto& driver : m_inputDrivers) {
|
||||
driver->loadConfiguration(config);
|
||||
}
|
||||
if (!loadConfiguration(SDL_BINDING_BUTTON)) {
|
||||
mSDLInitBindingsGBA(&m_inputMap);
|
||||
}
|
||||
loadProfile(SDL_BINDING_BUTTON, profileForType(SDL_BINDING_BUTTON));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool InputController::loadConfiguration(uint32_t type) {
|
||||
if (!mInputMapLoad(&m_inputMap, type, m_config->input())) {
|
||||
return false;
|
||||
}
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
mSDLPlayerLoadConfig(&m_sdlPlayer, m_config->input());
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
driver->loadConfiguration(m_config);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -185,7 +164,6 @@ bool InputController::loadProfile(uint32_t type, const QString& profile) {
|
|||
return false;
|
||||
}
|
||||
bool loaded = mInputProfileLoad(&m_inputMap, type, m_config->input(), profile.toUtf8().constData());
|
||||
recalibrateAxes();
|
||||
if (!loaded) {
|
||||
const InputProfile* ip = InputProfile::findProfile(profile);
|
||||
if (ip) {
|
||||
|
@ -199,18 +177,18 @@ bool InputController::loadProfile(uint32_t type, const QString& profile) {
|
|||
|
||||
void InputController::saveConfiguration() {
|
||||
saveConfiguration(KEYBOARD);
|
||||
#ifdef BUILD_SDL
|
||||
saveConfiguration(SDL_BINDING_BUTTON);
|
||||
saveProfile(SDL_BINDING_BUTTON, profileForType(SDL_BINDING_BUTTON));
|
||||
if (m_playerAttached) {
|
||||
mSDLPlayerSaveConfig(&m_sdlPlayer, m_config->input());
|
||||
for (auto& driver : m_inputDrivers) {
|
||||
driver->saveConfiguration(m_config);
|
||||
}
|
||||
#endif
|
||||
m_config->write();
|
||||
}
|
||||
|
||||
void InputController::saveConfiguration(uint32_t type) {
|
||||
mInputMapSave(&m_inputMap, type, m_config->input());
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (driver) {
|
||||
driver->saveConfiguration(m_config);
|
||||
}
|
||||
m_config->write();
|
||||
}
|
||||
|
||||
|
@ -222,313 +200,198 @@ void InputController::saveProfile(uint32_t type, const QString& profile) {
|
|||
m_config->write();
|
||||
}
|
||||
|
||||
const char* InputController::profileForType(uint32_t type) {
|
||||
UNUSED(type);
|
||||
#ifdef BUILD_SDL
|
||||
if (type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
return SDL_JoystickName(m_sdlPlayer.joystick->joystick);
|
||||
#else
|
||||
return SDL_JoystickName(SDL_JoystickIndex(m_sdlPlayer.joystick->joystick));
|
||||
#endif
|
||||
QString InputController::profileForType(uint32_t type) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return driver->currentProfile();
|
||||
}
|
||||
|
||||
QStringList InputController::connectedGamepads(uint32_t type) const {
|
||||
UNUSED(type);
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
if (type == SDL_BINDING_BUTTON) {
|
||||
QStringList pads;
|
||||
for (size_t i = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) {
|
||||
const char* name;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
name = SDL_JoystickName(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick);
|
||||
#else
|
||||
name = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick));
|
||||
#endif
|
||||
if (name) {
|
||||
pads.append(QString(name));
|
||||
} else {
|
||||
pads.append(QString());
|
||||
}
|
||||
}
|
||||
return pads;
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
|
||||
return QStringList();
|
||||
QStringList pads;
|
||||
for (auto pad : driver->connectedGamepads()) {
|
||||
pads.append(pad->visibleName());
|
||||
}
|
||||
return pads;
|
||||
}
|
||||
|
||||
int InputController::gamepad(uint32_t type) const {
|
||||
#ifdef BUILD_SDL
|
||||
if (type == SDL_BINDING_BUTTON) {
|
||||
return m_sdlPlayer.joystick ? m_sdlPlayer.joystick->index : 0;
|
||||
int InputController::gamepadIndex(uint32_t type) const {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return driver->activeGamepad();
|
||||
}
|
||||
|
||||
void InputController::setGamepad(uint32_t type, int index) {
|
||||
#ifdef BUILD_SDL
|
||||
if (type == SDL_BINDING_BUTTON) {
|
||||
mSDLPlayerChangeJoystick(&s_sdlEvents, &m_sdlPlayer, index);
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
driver->setActiveGamepad(index);
|
||||
}
|
||||
|
||||
void InputController::setPreferredGamepad(uint32_t type, int index) {
|
||||
if (!m_config) {
|
||||
return;
|
||||
}
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
char name[34] = {0};
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, index)->joystick), name, sizeof(name));
|
||||
#else
|
||||
const char* name = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, index)->joystick));
|
||||
if (!name) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
mInputSetPreferredDevice(m_config->input(), "gba", type, m_playerId, name);
|
||||
#else
|
||||
UNUSED(type);
|
||||
UNUSED(index);
|
||||
#endif
|
||||
|
||||
auto pads = driver->connectedGamepads();
|
||||
if (index >= pads.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString name = pads[index]->name();
|
||||
if (name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
mInputSetPreferredDevice(m_config->input(), "gba", type, m_playerId, name.toUtf8().constData());
|
||||
}
|
||||
|
||||
InputMapper InputController::mapper(uint32_t type) {
|
||||
return InputMapper(&m_inputMap, type);
|
||||
}
|
||||
|
||||
InputMapper InputController::mapper(InputSource* source) {
|
||||
return InputMapper(&m_inputMap, source->type());
|
||||
}
|
||||
|
||||
mRumble* InputController::rumble() {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (m_playerAttached) {
|
||||
return &m_sdlPlayer.rumble.d;
|
||||
auto driver = m_inputDrivers.value(m_sensorDriver);
|
||||
if (driver) {
|
||||
return driver->rumble();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mRotationSource* InputController::rotationSource() {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
return &m_sdlPlayer.rotation.d;
|
||||
auto driver = m_inputDrivers.value(m_sensorDriver);
|
||||
if (driver) {
|
||||
return driver->rotationSource();
|
||||
}
|
||||
#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;
|
||||
if (m_sdlPlayer.rotation.gyroY == axis) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
} else {
|
||||
m_sdlPlayer.rotation.gyroZ = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::registerGyroAxisY(int axis) {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroY = axis;
|
||||
if (m_sdlPlayer.rotation.gyroX == axis) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
} else {
|
||||
m_sdlPlayer.rotation.gyroZ = -1;
|
||||
}
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int InputController::mapKeyboard(int key) const {
|
||||
return mInputMapKey(&m_inputMap, KEYBOARD, key);
|
||||
}
|
||||
|
||||
void InputController::updateJoysticks() {
|
||||
#ifdef BUILD_SDL
|
||||
QString profile = profileForType(SDL_BINDING_BUTTON);
|
||||
mSDLUpdateJoysticks(&s_sdlEvents, m_config->input());
|
||||
QString newProfile = profileForType(SDL_BINDING_BUTTON);
|
||||
if (profile != newProfile) {
|
||||
loadProfile(SDL_BINDING_BUTTON, newProfile);
|
||||
void InputController::update() {
|
||||
for (auto& driver : m_inputDrivers) {
|
||||
QString profile = profileForType(driver->type());
|
||||
driver->update();
|
||||
QString newProfile = profileForType(driver->type());
|
||||
if (profile != newProfile) {
|
||||
loadProfile(driver->type(), newProfile);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int InputController::pollEvents() {
|
||||
int activeButtons = 0;
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached && m_sdlPlayer.joystick) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numButtons = SDL_JoystickNumButtons(joystick);
|
||||
int i;
|
||||
QReadLocker l(&m_eventsLock);
|
||||
for (i = 0; i < numButtons; ++i) {
|
||||
int key = mInputMapKey(&m_inputMap, SDL_BINDING_BUTTON, i);
|
||||
if (key == -1) {
|
||||
continue;
|
||||
}
|
||||
if (hasPendingEvent(key)) {
|
||||
continue;
|
||||
}
|
||||
if (SDL_JoystickGetButton(joystick, i)) {
|
||||
activeButtons |= 1 << key;
|
||||
}
|
||||
}
|
||||
l.unlock();
|
||||
int numHats = SDL_JoystickNumHats(joystick);
|
||||
for (i = 0; i < numHats; ++i) {
|
||||
int hat = SDL_JoystickGetHat(joystick, i);
|
||||
activeButtons |= mInputMapHat(&m_inputMap, SDL_BINDING_BUTTON, i, hat);
|
||||
}
|
||||
|
||||
int numAxes = SDL_JoystickNumAxes(joystick);
|
||||
for (i = 0; i < numAxes; ++i) {
|
||||
int value = SDL_JoystickGetAxis(joystick, i);
|
||||
|
||||
int key = mInputMapAxis(&m_inputMap, SDL_BINDING_BUTTON, i, value);
|
||||
if (key != -1) {
|
||||
activeButtons |= 1 << key;
|
||||
}
|
||||
for (auto pad : gamepads()) {
|
||||
InputMapper im(mapper(pad));
|
||||
activeButtons |= im.mapKeys(pad->currentButtons());
|
||||
activeButtons |= im.mapAxes(pad->currentAxes());
|
||||
activeButtons |= im.mapHats(pad->currentHats());
|
||||
}
|
||||
for (int i = 0; i < GBA_KEY_MAX; ++i) {
|
||||
if ((activeButtons & (1 << i)) && hasPendingEvent(i)) {
|
||||
activeButtons ^= 1 << i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return activeButtons;
|
||||
}
|
||||
|
||||
Gamepad* InputController::gamepad(uint32_t type) {
|
||||
auto driver = m_inputDrivers.value(type);
|
||||
if (!driver) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!driver->supportsGamepads()) {
|
||||
return nullptr;
|
||||
}
|
||||
QList<Gamepad*> driverPads(driver->connectedGamepads());
|
||||
int activeGamepad = driver->activeGamepad();
|
||||
if (activeGamepad < 0 || activeGamepad >= driverPads.count()) {
|
||||
return nullptr;
|
||||
}
|
||||
return driverPads[activeGamepad];
|
||||
}
|
||||
|
||||
QList<Gamepad*> InputController::gamepads() {
|
||||
QList<Gamepad*> pads;
|
||||
for (auto& driver : m_inputDrivers) {
|
||||
if (!driver->supportsGamepads()) {
|
||||
continue;
|
||||
}
|
||||
QList<Gamepad*> driverPads(driver->connectedGamepads());
|
||||
int activeGamepad = driver->activeGamepad();
|
||||
if (activeGamepad >= 0 && activeGamepad < driverPads.count()) {
|
||||
pads.append(driverPads[activeGamepad]);
|
||||
}
|
||||
}
|
||||
return pads;
|
||||
}
|
||||
|
||||
QSet<int> InputController::activeGamepadButtons(int type) {
|
||||
QSet<int> activeButtons;
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached && type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numButtons = SDL_JoystickNumButtons(joystick);
|
||||
int i;
|
||||
for (i = 0; i < numButtons; ++i) {
|
||||
if (SDL_JoystickGetButton(joystick, i)) {
|
||||
activeButtons.insert(i);
|
||||
}
|
||||
Gamepad* pad = gamepad(type);
|
||||
if (!pad) {
|
||||
return {};
|
||||
}
|
||||
auto allButtons = pad->currentButtons();
|
||||
for (int i = 0; i < allButtons.size(); ++i) {
|
||||
if (allButtons[i]) {
|
||||
activeButtons.insert(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return activeButtons;
|
||||
}
|
||||
|
||||
void InputController::recalibrateAxes() {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached && m_sdlPlayer.joystick) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick->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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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 && m_sdlPlayer.joystick) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numAxes = SDL_JoystickNumAxes(joystick);
|
||||
if (numAxes < 1) {
|
||||
return activeAxes;
|
||||
Gamepad* pad = gamepad(type);
|
||||
if (!pad) {
|
||||
return {};
|
||||
}
|
||||
InputMapper im(mapper(type));
|
||||
auto allAxes = pad->currentAxes();
|
||||
for (int i = 0; i < allAxes.size(); ++i) {
|
||||
if (allAxes[i] - im.axisCenter(i) >= im.axisThreshold(i)) {
|
||||
activeAxes.insert(qMakePair(i, GamepadAxisEvent::POSITIVE));
|
||||
continue;
|
||||
}
|
||||
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));
|
||||
}
|
||||
if (allAxes[i] - im.axisCenter(i) <= -im.axisThreshold(i)) {
|
||||
activeAxes.insert(qMakePair(i, GamepadAxisEvent::NEGATIVE));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return activeAxes;
|
||||
}
|
||||
|
||||
QSet<QPair<int, GamepadHatEvent::Direction>> InputController::activeGamepadHats(int type) {
|
||||
QSet<QPair<int, GamepadHatEvent::Direction>> activeHats;
|
||||
#ifdef BUILD_SDL
|
||||
if (m_playerAttached && type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) {
|
||||
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||
SDL_JoystickUpdate();
|
||||
int numHats = SDL_JoystickNumHats(joystick);
|
||||
if (numHats < 1) {
|
||||
return activeHats;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < numHats; ++i) {
|
||||
int hat = SDL_JoystickGetHat(joystick, i);
|
||||
if (hat & GamepadHatEvent::UP) {
|
||||
activeHats.insert(qMakePair(i, GamepadHatEvent::UP));
|
||||
}
|
||||
if (hat & GamepadHatEvent::RIGHT) {
|
||||
activeHats.insert(qMakePair(i, GamepadHatEvent::RIGHT));
|
||||
}
|
||||
if (hat & GamepadHatEvent::DOWN) {
|
||||
activeHats.insert(qMakePair(i, GamepadHatEvent::DOWN));
|
||||
}
|
||||
if (hat & GamepadHatEvent::LEFT) {
|
||||
activeHats.insert(qMakePair(i, GamepadHatEvent::LEFT));
|
||||
}
|
||||
Gamepad* pad = gamepad(type);
|
||||
if (!pad) {
|
||||
return {};
|
||||
}
|
||||
auto allHats = pad->currentHats();
|
||||
for (int i = 0; i < allHats.size(); ++i) {
|
||||
if (allHats[i] != GamepadHatEvent::CENTER) {
|
||||
activeHats.insert(qMakePair(i, allHats[i]));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return activeHats;
|
||||
}
|
||||
|
||||
|
@ -634,30 +497,6 @@ bool InputController::hasPendingEvent(int key) const {
|
|||
return m_pendingEvents.contains(key);
|
||||
}
|
||||
|
||||
void InputController::suspendScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
mSDLSuspendScreensaver(&s_sdlEvents);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::resumeScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
mSDLResumeScreensaver(&s_sdlEvents);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::setScreensaverSuspendable(bool suspendable) {
|
||||
#ifdef BUILD_SDL
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
mSDLSetScreensaverSuspendable(&s_sdlEvents, suspendable);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputController::stealFocus(QWidget* focus) {
|
||||
m_focusParent = focus;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
#include "input/GamepadHatEvent.h"
|
||||
#include "input/InputDriver.h"
|
||||
#include "input/InputMapper.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QImage>
|
||||
#include <QMutex>
|
||||
#include <QReadWriteLock>
|
||||
|
@ -22,11 +24,6 @@
|
|||
#include <mgba/core/input.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BUILD_QT_MULTIMEDIA
|
||||
#include "VideoDumper.h"
|
||||
#include <QCamera>
|
||||
|
@ -38,6 +35,8 @@ struct mRumble;
|
|||
namespace QGBA {
|
||||
|
||||
class ConfigController;
|
||||
class Gamepad;
|
||||
class InputSource;
|
||||
|
||||
class InputController : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -55,13 +54,15 @@ public:
|
|||
InputController(int playerId = 0, QWidget* topLevel = nullptr, QObject* parent = nullptr);
|
||||
~InputController();
|
||||
|
||||
void addInputDriver(std::shared_ptr<InputDriver>);
|
||||
|
||||
void setConfiguration(ConfigController* config);
|
||||
void saveConfiguration();
|
||||
bool loadConfiguration(uint32_t type);
|
||||
bool loadProfile(uint32_t type, const QString& profile);
|
||||
void saveConfiguration(uint32_t type);
|
||||
void saveProfile(uint32_t type, const QString& profile);
|
||||
const char* profileForType(uint32_t type);
|
||||
QString profileForType(uint32_t type);
|
||||
|
||||
int mapKeyboard(int key) const;
|
||||
|
||||
|
@ -71,25 +72,17 @@ public:
|
|||
int pollEvents();
|
||||
|
||||
static const int32_t AXIS_THRESHOLD = 0x3000;
|
||||
QSet<int> activeGamepadButtons(int type);
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(int type);
|
||||
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
|
||||
void recalibrateAxes();
|
||||
|
||||
QStringList connectedGamepads(uint32_t type) const;
|
||||
int gamepad(uint32_t type) const;
|
||||
int gamepadIndex(uint32_t type) const;
|
||||
void setGamepad(uint32_t type, int index);
|
||||
void setPreferredGamepad(uint32_t type, int index);
|
||||
|
||||
InputMapper mapper(uint32_t type);
|
||||
InputMapper mapper(InputSource*);
|
||||
|
||||
void registerTiltAxisX(int axis);
|
||||
void registerTiltAxisY(int axis);
|
||||
void registerGyroAxisX(int axis);
|
||||
void registerGyroAxisY(int axis);
|
||||
|
||||
float gyroSensitivity() const;
|
||||
void setGyroSensitivity(float sensitivity);
|
||||
const InputDriver* sensorDriver() const { return m_inputDrivers.value(m_sensorDriver).get(); }
|
||||
InputDriver* sensorDriver() { return m_inputDrivers.value(m_sensorDriver).get(); }
|
||||
|
||||
void stealFocus(QWidget* focus);
|
||||
void releaseFocus(QWidget* focus);
|
||||
|
@ -107,12 +100,7 @@ signals:
|
|||
|
||||
public slots:
|
||||
void testGamepad(int type);
|
||||
void updateJoysticks();
|
||||
|
||||
// TODO: Move these to somewhere that makes sense
|
||||
void suspendScreensaver();
|
||||
void resumeScreensaver();
|
||||
void setScreensaverSuspendable(bool);
|
||||
void update();
|
||||
|
||||
void increaseLuminanceLevel();
|
||||
void decreaseLuminanceLevel();
|
||||
|
@ -137,6 +125,13 @@ private:
|
|||
bool hasPendingEvent(int) const;
|
||||
void sendGamepadEvent(QEvent*);
|
||||
|
||||
Gamepad* gamepad(uint32_t type);
|
||||
QList<Gamepad*> gamepads();
|
||||
|
||||
QSet<int> activeGamepadButtons(int type);
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(int type);
|
||||
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
|
||||
|
||||
struct InputControllerLux : GBALuminanceSource {
|
||||
InputController* p;
|
||||
uint8_t value;
|
||||
|
@ -166,14 +161,8 @@ private:
|
|||
QWidget* m_topLevel;
|
||||
QWidget* m_focusParent;
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
static int s_sdlInited;
|
||||
static mSDLEvents s_sdlEvents;
|
||||
mSDLPlayer m_sdlPlayer{};
|
||||
bool m_playerAttached = false;
|
||||
#endif
|
||||
|
||||
QVector<int> m_deadzones;
|
||||
QHash<uint32_t, std::shared_ptr<InputDriver>> m_inputDrivers;
|
||||
uint32_t m_sensorDriver;
|
||||
|
||||
QSet<int> m_activeButtons;
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> m_activeAxes;
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
|
||||
#include <QRegExp>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
const InputProfile InputProfile::s_defaultMaps[] = {
|
||||
|
@ -218,11 +222,15 @@ void InputProfile::apply(InputController* controller) const {
|
|||
mapper.bindAxis(m_axes[i].axis, m_axes[i].direction, static_cast<GBAKey>(i));
|
||||
}
|
||||
#endif
|
||||
controller->registerTiltAxisX(m_tiltAxis.x);
|
||||
controller->registerTiltAxisY(m_tiltAxis.y);
|
||||
controller->registerGyroAxisX(m_gyroAxis.x);
|
||||
controller->registerGyroAxisY(m_gyroAxis.y);
|
||||
controller->setGyroSensitivity(m_gyroSensitivity);
|
||||
|
||||
InputDriver* sensorDriver = controller->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
sensorDriver->registerTiltAxisX(m_tiltAxis.x);
|
||||
sensorDriver->registerTiltAxisY(m_tiltAxis.y);
|
||||
sensorDriver->registerGyroAxisX(m_gyroAxis.x);
|
||||
sensorDriver->registerGyroAxisY(m_gyroAxis.y);
|
||||
sensorDriver->setGyroSensitivity(m_gyroSensitivity);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputProfile::lookupShortcutButton(const QString& shortcutName, int* button) const {
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#include <mgba-util/png-io.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
#include "CoreController.h"
|
||||
#include "GBAApp.h"
|
||||
#include "Window.h"
|
||||
|
@ -316,7 +320,7 @@ void ReportView::generateReport() {
|
|||
}
|
||||
#ifdef BUILD_SDL
|
||||
InputController* input = window->inputController();
|
||||
windowReport << QString("Active gamepad: %1").arg(input->gamepad(SDL_BINDING_BUTTON));
|
||||
windowReport << QString("Active gamepad: %1").arg(input->gamepadIndex(SDL_BINDING_BUTTON));
|
||||
#endif
|
||||
windowReport << QString("Configuration: %1").arg(configs.indexOf(config) + 1);
|
||||
addReport(QString("Window %1").arg(winId), windowReport.join('\n'));
|
||||
|
@ -490,7 +494,7 @@ void ReportView::addGamepadInfo(QStringList& report) {
|
|||
i = 0;
|
||||
for (Window* window : GBAApp::app()->windows()) {
|
||||
++i;
|
||||
report << QString("Window %1 gamepad: %2").arg(i).arg(window->inputController()->gamepad(SDL_BINDING_BUTTON));
|
||||
report << QString("Window %1 gamepad: %2").arg(i).arg(window->inputController()->gamepadIndex(SDL_BINDING_BUTTON));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "CoreController.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
#include "input/InputDriver.h"
|
||||
#include "InputController.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -47,14 +48,20 @@ SensorView::SensorView(InputController* input, QWidget* parent)
|
|||
m_timer.start();
|
||||
}
|
||||
|
||||
jiggerer(m_ui.tiltSetX, &InputController::registerTiltAxisX);
|
||||
jiggerer(m_ui.tiltSetY, &InputController::registerTiltAxisY);
|
||||
jiggerer(m_ui.gyroSetX, &InputController::registerGyroAxisX);
|
||||
jiggerer(m_ui.gyroSetY, &InputController::registerGyroAxisY);
|
||||
jiggerer(m_ui.tiltSetX, &InputDriver::registerTiltAxisX);
|
||||
jiggerer(m_ui.tiltSetY, &InputDriver::registerTiltAxisY);
|
||||
jiggerer(m_ui.gyroSetX, &InputDriver::registerGyroAxisX);
|
||||
jiggerer(m_ui.gyroSetY, &InputDriver::registerGyroAxisY);
|
||||
|
||||
m_ui.gyroSensitivity->setValue(m_input->gyroSensitivity() / 1e8f);
|
||||
InputDriver* sensorDriver = m_input->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
m_ui.gyroSensitivity->setValue(sensorDriver->gyroSensitivity() / 1e8f);
|
||||
}
|
||||
connect(m_ui.gyroSensitivity, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {
|
||||
m_input->setGyroSensitivity(value * 1e8f);
|
||||
InputDriver* sensorDriver = m_input->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
sensorDriver->setGyroSensitivity(value * 1e8f);
|
||||
}
|
||||
});
|
||||
m_input->stealFocus(this);
|
||||
connect(m_input, &InputController::luminanceValueChanged, this, &SensorView::luminanceValueChanged);
|
||||
|
@ -84,7 +91,7 @@ void SensorView::setController(std::shared_ptr<CoreController> controller) {
|
|||
});
|
||||
}
|
||||
|
||||
void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
|
||||
void SensorView::jiggerer(QAbstractButton* button, void (InputDriver::*setter)(int)) {
|
||||
connect(button, &QAbstractButton::toggled, [this, button, setter](bool checked) {
|
||||
if (!checked) {
|
||||
m_button = nullptr;
|
||||
|
@ -115,7 +122,10 @@ bool SensorView::eventFilter(QObject*, QEvent* event) {
|
|||
m_button->removeEventFilter(this);
|
||||
m_button->clearFocus();
|
||||
m_button->setChecked(false);
|
||||
(m_input->*m_setter)(gae->axis());
|
||||
InputDriver* sensorDriver = m_input->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
(sensorDriver->*m_setter)(gae->axis());
|
||||
}
|
||||
m_button = nullptr;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -21,6 +21,7 @@ class ConfigController;
|
|||
class CoreController;
|
||||
class GamepadAxisEvent;
|
||||
class InputController;
|
||||
class InputDriver;
|
||||
|
||||
class SensorView : public QDialog {
|
||||
Q_OBJECT
|
||||
|
@ -43,14 +44,14 @@ private:
|
|||
Ui::SensorView m_ui;
|
||||
|
||||
QAbstractButton* m_button = nullptr;
|
||||
void (InputController::*m_setter)(int);
|
||||
void (InputDriver::*m_setter)(int);
|
||||
|
||||
std::shared_ptr<CoreController> m_controller;
|
||||
InputController* m_input;
|
||||
mRotationSource* m_rotation;
|
||||
QTimer m_timer;
|
||||
|
||||
void jiggerer(QAbstractButton*, void (InputController::*)(int));
|
||||
void jiggerer(QAbstractButton*, void (InputDriver::*)(int));
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
#include <mgba/core/version.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent)
|
||||
|
@ -326,8 +330,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
|
||||
GBAKeyEditor* buttonEditor = nullptr;
|
||||
#ifdef BUILD_SDL
|
||||
inputController->recalibrateAxes();
|
||||
const char* profile = inputController->profileForType(SDL_BINDING_BUTTON);
|
||||
QString profile = inputController->profileForType(SDL_BINDING_BUTTON);
|
||||
buttonEditor = new GBAKeyEditor(inputController, SDL_BINDING_BUTTON, profile);
|
||||
addPage(tr("Controllers"), buttonEditor, Page::CONTROLLERS);
|
||||
connect(m_ui.buttonBox, &QDialogButtonBox::accepted, buttonEditor, &GBAKeyEditor::save);
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
#include "GDBController.h"
|
||||
#include "GDBWindow.h"
|
||||
#include "GIFView.h"
|
||||
#ifdef BUILD_SDL
|
||||
#include "input/SDLInputDriver.h"
|
||||
#endif
|
||||
#include "IOViewer.h"
|
||||
#include "LoadSaveState.h"
|
||||
#include "LogView.h"
|
||||
|
@ -171,6 +174,10 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi
|
|||
m_mustReset.setInterval(MUST_RESTART_TIMEOUT);
|
||||
m_mustReset.setSingleShot(true);
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
m_inputController.addInputDriver(std::make_shared<SDLInputDriver>(&m_inputController));
|
||||
#endif
|
||||
|
||||
m_shortcutController->setConfigController(m_config);
|
||||
m_shortcutController->setActionMapper(&m_actions);
|
||||
setupMenu(menuBar());
|
||||
|
@ -298,7 +305,7 @@ void Window::reloadConfig() {
|
|||
m_display->resizeContext();
|
||||
}
|
||||
|
||||
m_inputController.setScreensaverSuspendable(opts->suspendScreensaver);
|
||||
GBAApp::app()->setScreensaverSuspendable(opts->suspendScreensaver);
|
||||
}
|
||||
|
||||
void Window::saveConfig() {
|
||||
|
@ -2000,7 +2007,6 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
}
|
||||
|
||||
m_controller = std::shared_ptr<CoreController>(controller);
|
||||
m_inputController.recalibrateAxes();
|
||||
m_controller->setInputController(&m_inputController);
|
||||
m_controller->setLogger(&m_log);
|
||||
|
||||
|
@ -2013,14 +2019,14 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
});
|
||||
|
||||
connect(m_controller.get(), &CoreController::started, this, &Window::gameStarted);
|
||||
connect(m_controller.get(), &CoreController::started, &m_inputController, &InputController::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::started, GBAApp::app(), &GBAApp::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::stopping, this, &Window::gameStopped);
|
||||
{
|
||||
connect(m_controller.get(), &CoreController::stopping, [this]() {
|
||||
m_controller.reset();
|
||||
});
|
||||
}
|
||||
connect(m_controller.get(), &CoreController::stopping, &m_inputController, &InputController::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::stopping, GBAApp::app(), &GBAApp::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::paused, this, &Window::updateFrame);
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
|
@ -2032,14 +2038,14 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
});
|
||||
#endif
|
||||
|
||||
connect(m_controller.get(), &CoreController::paused, &m_inputController, &InputController::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::paused, GBAApp::app(), &GBAApp::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::paused, [this]() {
|
||||
emit paused(true);
|
||||
});
|
||||
connect(m_controller.get(), &CoreController::unpaused, [this]() {
|
||||
emit paused(false);
|
||||
});
|
||||
connect(m_controller.get(), &CoreController::unpaused, &m_inputController, &InputController::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::unpaused, GBAApp::app(), &GBAApp::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::frameAvailable, this, &Window::recordFrame);
|
||||
connect(m_controller.get(), &CoreController::crashed, this, &Window::gameCrashed);
|
||||
connect(m_controller.get(), &CoreController::failed, this, &Window::gameFailed);
|
||||
|
|
|
@ -17,6 +17,18 @@ void InputDriver::loadConfiguration(ConfigController*) {
|
|||
void InputDriver::saveConfiguration(ConfigController*) {
|
||||
}
|
||||
|
||||
bool InputDriver::supportsPolling() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputDriver::supportsGamepads() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputDriver::supportsSensors() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputDriver::bindDefaults(InputController*) {
|
||||
}
|
||||
|
||||
|
@ -28,6 +40,42 @@ QList<Gamepad*> InputDriver::connectedGamepads() const {
|
|||
return {};
|
||||
}
|
||||
|
||||
int InputDriver::activeKeySource() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int InputDriver::activeGamepad() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void InputDriver::setActiveKeySource(int) {
|
||||
}
|
||||
|
||||
void InputDriver::setActiveGamepad(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerTiltAxisX(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerTiltAxisY(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerGyroAxisX(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerGyroAxisY(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerGyroAxisZ(int) {
|
||||
}
|
||||
|
||||
float InputDriver::gyroSensitivity() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputDriver::setGyroSensitivity(float) {
|
||||
}
|
||||
|
||||
mRumble* InputDriver::rumble() {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ public:
|
|||
|
||||
virtual uint32_t type() const = 0;
|
||||
virtual QString visibleName() const = 0;
|
||||
virtual QString currentProfile() const = 0;
|
||||
|
||||
virtual bool supportsPolling() const;
|
||||
virtual bool supportsGamepads() const;
|
||||
virtual bool supportsSensors() const;
|
||||
|
||||
virtual void loadConfiguration(ConfigController*);
|
||||
virtual void saveConfiguration(ConfigController*);
|
||||
|
@ -39,6 +44,21 @@ public:
|
|||
virtual QList<KeySource*> connectedKeySources() const;
|
||||
virtual QList<Gamepad*> connectedGamepads() const;
|
||||
|
||||
virtual int activeKeySource() const;
|
||||
virtual int activeGamepad() const;
|
||||
|
||||
virtual void setActiveKeySource(int);
|
||||
virtual void setActiveGamepad(int);
|
||||
|
||||
virtual void registerTiltAxisX(int axis);
|
||||
virtual void registerTiltAxisY(int axis);
|
||||
virtual void registerGyroAxisX(int axis);
|
||||
virtual void registerGyroAxisY(int axis);
|
||||
virtual void registerGyroAxisZ(int axis);
|
||||
|
||||
virtual float gyroSensitivity() const;
|
||||
virtual void setGyroSensitivity(float sensitivity);
|
||||
|
||||
virtual mRumble* rumble();
|
||||
virtual mRotationSource* rotationSource();
|
||||
};
|
||||
|
|
|
@ -15,18 +15,65 @@ InputMapper::InputMapper(mInputMap* map, uint32_t type)
|
|||
{
|
||||
}
|
||||
|
||||
int InputMapper::mapKey(int key) {
|
||||
int InputMapper::mapKey(int key) const {
|
||||
return mInputMapKey(m_map, m_type, key);
|
||||
}
|
||||
|
||||
int InputMapper::mapAxis(int axis, int16_t value) {
|
||||
int InputMapper::mapAxis(int axis, int16_t value) const {
|
||||
return mInputMapAxis(m_map, m_type, axis, value);
|
||||
}
|
||||
|
||||
int InputMapper::mapHat(int hat, GamepadHatEvent::Direction direction) {
|
||||
int InputMapper::mapHat(int hat, GamepadHatEvent::Direction direction) const {
|
||||
return mInputMapHat(m_map, m_type, hat, direction);
|
||||
}
|
||||
|
||||
int InputMapper::mapKeys(QList<bool> keys) const {
|
||||
int platformKeys = 0;
|
||||
for (int i = 0; i < keys.count(); ++i) {
|
||||
if (!keys[i]) {
|
||||
continue;
|
||||
}
|
||||
int platformKey = mInputMapKey(m_map, m_type, i);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
int InputMapper::mapKeys(QSet<int> keys) const {
|
||||
int platformKeys = 0;
|
||||
for (int key : keys) {
|
||||
int platformKey = mInputMapKey(m_map, m_type, key);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
int InputMapper::mapAxes(QList<int16_t> axes) const {
|
||||
int platformKeys = 0;
|
||||
for (int i = 0; i < axes.count(); ++i) {
|
||||
int platformKey = mInputMapAxis(m_map, m_type, i, axes[i]);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
int InputMapper::mapHats(QList<GamepadHatEvent::Direction> hats) const {
|
||||
int platformKeys = 0;
|
||||
for (int i = 0; i < hats.count(); ++i) {
|
||||
int platformKey = mInputMapHat(m_map, m_type, i, hats[i]);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
void InputMapper::bindKey(int key, int platformKey) {
|
||||
mInputBindKey(m_map, m_type, key, platformKey);
|
||||
}
|
||||
|
|
|
@ -24,9 +24,14 @@ public:
|
|||
mInputMap* inputMap() const { return m_map; }
|
||||
uint32_t type() const { return m_type; }
|
||||
|
||||
int mapKey(int key);
|
||||
int mapAxis(int axis, int16_t value);
|
||||
int mapHat(int hat, GamepadHatEvent::Direction);
|
||||
int mapKey(int key) const;
|
||||
int mapAxis(int axis, int16_t value) const;
|
||||
int mapHat(int hat, GamepadHatEvent::Direction) const;
|
||||
|
||||
int mapKeys(QList<bool> keys) const;
|
||||
int mapKeys(QSet<int> keys) const;
|
||||
int mapAxes(QList<int16_t> axes) const;
|
||||
int mapHats(QList<GamepadHatEvent::Direction> hats) const;
|
||||
|
||||
void bindKey(int key, int platformKey);
|
||||
void bindAxis(int axis, GamepadAxisEvent::Direction, int platformKey);
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
namespace QGBA {
|
||||
#include "input/InputDriver.h"
|
||||
|
||||
class InputDriver;
|
||||
namespace QGBA {
|
||||
|
||||
class InputSource : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -20,6 +20,7 @@ public:
|
|||
virtual ~InputSource() = default;
|
||||
|
||||
InputDriver* driver() { return m_driver; }
|
||||
uint32_t type() { return m_driver->type(); }
|
||||
|
||||
virtual QString name() const = 0;
|
||||
virtual QString visibleName() const = 0;
|
||||
|
|
|
@ -15,6 +15,30 @@ using namespace QGBA;
|
|||
int s_sdlInited = 0;
|
||||
mSDLEvents s_sdlEvents;
|
||||
|
||||
void SDL::suspendScreensaver() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (s_sdlInited) {
|
||||
mSDLSuspendScreensaver(&s_sdlEvents);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL::resumeScreensaver() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (s_sdlInited) {
|
||||
mSDLResumeScreensaver(&s_sdlEvents);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL::setScreensaverSuspendable(bool suspendable) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (s_sdlInited) {
|
||||
mSDLSetScreensaverSuspendable(&s_sdlEvents, suspendable);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SDLInputDriver::SDLInputDriver(InputController* controller, QObject* parent)
|
||||
: InputDriver(parent)
|
||||
, m_controller(controller)
|
||||
|
@ -41,6 +65,29 @@ SDLInputDriver::~SDLInputDriver() {
|
|||
}
|
||||
}
|
||||
|
||||
bool SDLInputDriver::supportsPolling() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDLInputDriver::supportsGamepads() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDLInputDriver::supportsSensors() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString SDLInputDriver::currentProfile() const {
|
||||
if (m_sdlPlayer.joystick) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
return SDL_JoystickName(m_sdlPlayer.joystick->joystick);
|
||||
#else
|
||||
return SDL_JoystickName(SDL_JoystickIndex(m_sdlPlayer.joystick->joystick));
|
||||
#endif
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void SDLInputDriver::loadConfiguration(ConfigController* config) {
|
||||
mSDLEventsLoadConfig(&s_sdlEvents, config->input());
|
||||
if (!m_playerAttached) {
|
||||
|
@ -126,6 +173,69 @@ void SDLInputDriver::updateGamepads() {
|
|||
}
|
||||
#endif
|
||||
|
||||
int SDLInputDriver::activeGamepad() const {
|
||||
return m_sdlPlayer.joystick ? m_sdlPlayer.joystick->index : 0;
|
||||
}
|
||||
|
||||
void SDLInputDriver::setActiveGamepad(int index) {
|
||||
mSDLPlayerChangeJoystick(&s_sdlEvents, &m_sdlPlayer, index);
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerTiltAxisX(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.axisX = axis;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerTiltAxisY(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.axisY = axis;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerGyroAxisX(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroX = axis;
|
||||
if (m_sdlPlayer.rotation.gyroY == axis) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
} else {
|
||||
m_sdlPlayer.rotation.gyroZ = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerGyroAxisY(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroY = axis;
|
||||
if (m_sdlPlayer.rotation.gyroX == axis) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
} else {
|
||||
m_sdlPlayer.rotation.gyroZ = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerGyroAxisZ(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
m_sdlPlayer.rotation.gyroX = -1;
|
||||
m_sdlPlayer.rotation.gyroY = -1;
|
||||
}
|
||||
}
|
||||
|
||||
float SDLInputDriver::gyroSensitivity() const {
|
||||
if (m_playerAttached) {
|
||||
return m_sdlPlayer.rotation.gyroSensitivity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDLInputDriver::setGyroSensitivity(float sensitivity) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroSensitivity = sensitivity;
|
||||
}
|
||||
}
|
||||
|
||||
SDLGamepad::SDLGamepad(SDLInputDriver* driver, int index, QObject* parent)
|
||||
: Gamepad(driver, parent)
|
||||
, m_index(index)
|
||||
|
|
|
@ -16,6 +16,12 @@ namespace QGBA {
|
|||
|
||||
class SDLGamepad;
|
||||
|
||||
namespace SDL {
|
||||
void suspendScreensaver();
|
||||
void resumeScreensaver();
|
||||
void setScreensaverSuspendable(bool);
|
||||
}
|
||||
|
||||
class SDLInputDriver : public InputDriver {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -25,6 +31,11 @@ public:
|
|||
|
||||
uint32_t type() const override { return SDL_BINDING_BUTTON; }
|
||||
QString visibleName() const override { return QLatin1String("SDL"); }
|
||||
QString currentProfile() const override;
|
||||
|
||||
bool supportsPolling() const override;
|
||||
bool supportsGamepads() const override;
|
||||
bool supportsSensors() const override;
|
||||
|
||||
void loadConfiguration(ConfigController* config) override;
|
||||
void saveConfiguration(ConfigController* config) override;
|
||||
|
@ -35,6 +46,18 @@ public:
|
|||
|
||||
QList<Gamepad*> connectedGamepads() const override;
|
||||
|
||||
int activeGamepad() const override;
|
||||
void setActiveGamepad(int) override;
|
||||
|
||||
void registerTiltAxisX(int axis) override;
|
||||
void registerTiltAxisY(int axis) override;
|
||||
void registerGyroAxisX(int axis) override;
|
||||
void registerGyroAxisY(int axis) override;
|
||||
void registerGyroAxisZ(int axis) override;
|
||||
|
||||
float gyroSensitivity() const override;
|
||||
void setGyroSensitivity(float sensitivity) override;
|
||||
|
||||
mRumble* rumble() override;
|
||||
mRotationSource* rotationSource() override;
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#include <mgba/core/version.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
#include <QLibraryInfo>
|
||||
#include <QTranslator>
|
||||
|
||||
|
|
Loading…
Reference in New Issue