From ac2e7b644792c2bbde411d6433cc16ca27f71591 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Jul 2017 22:05:03 -0700 Subject: [PATCH] Qt: Begin revamping profiles --- src/platform/qt/input/InputController.cpp | 13 +- src/platform/qt/input/InputIndex.cpp | 29 +- src/platform/qt/input/InputIndex.h | 9 - src/platform/qt/input/InputProfile.cpp | 307 +++++---------------- src/platform/qt/input/InputProfile.h | 87 ++---- src/platform/qt/input/default-profiles.ini | 114 ++++++++ src/platform/qt/resources.qrc | 1 + src/platform/sdl/sdl-events.c | 4 +- 8 files changed, 218 insertions(+), 346 deletions(-) create mode 100644 src/platform/qt/input/default-profiles.ini diff --git a/src/platform/qt/input/InputController.cpp b/src/platform/qt/input/InputController.cpp index a9678a902..b241f8e1f 100644 --- a/src/platform/qt/input/InputController.cpp +++ b/src/platform/qt/input/InputController.cpp @@ -185,18 +185,11 @@ void InputController::loadConfiguration(uint32_t type) { } void InputController::loadProfile(uint32_t type, const QString& profile) { - if (m_activeKeyInfo) { - bool loaded = mInputProfileLoad(&m_inputMap, type, m_config->input(), profile.toUtf8().constData()); - if (!loaded) { - const InputProfile* ip = InputProfile::findProfile(profile); - if (ip) { - ip->apply(this); - } - } + const InputProfile* ip = InputProfile::findProfile(profile); + if (ip) { + ip->apply(this); } recalibrateAxes(); - m_inputIndex.loadProfile(profile); - m_keyIndex.loadProfile(profile); emit profileLoaded(profile); } diff --git a/src/platform/qt/input/InputIndex.cpp b/src/platform/qt/input/InputIndex.cpp index d72d67189..b3c9d557b 100644 --- a/src/platform/qt/input/InputIndex.cpp +++ b/src/platform/qt/input/InputIndex.cpp @@ -6,7 +6,6 @@ #include "InputIndex.h" #include "ConfigController.h" -#include "InputProfile.h" using namespace QGBA; @@ -62,6 +61,9 @@ void InputIndex::rebuild(const InputIndex* root) { break; } } + if (!newItem) { + continue; + } newItem->setShortcut(item->shortcut()); newItem->setButton(item->button()); newItem->setAxis(item->axis(), item->direction()); @@ -121,29 +123,16 @@ void InputIndex::loadGamepadShortcuts(InputItem* item) { if (item->name().isNull()) { return; } - QVariant button = m_config->getQtOption(item->name(), !m_profileName.isNull() ? BUTTON_PROFILE_SECTION + m_profileName : BUTTON_SECTION); - if (button.isNull() && m_profile) { - int buttonInt; - if (m_profile->lookupShortcutButton(item->name(), &buttonInt)) { - button = buttonInt; - } - } + QVariant button = m_config->getQtOption(item->name(), BUTTON_SECTION); if (!button.isNull()) { item->setButton(button.toInt()); } - QVariant axis = m_config->getQtOption(item->name(), !m_profileName.isNull() ? AXIS_PROFILE_SECTION + m_profileName : AXIS_SECTION); + QVariant axis = m_config->getQtOption(item->name(), AXIS_SECTION); int oldAxis = item->axis(); if (oldAxis >= 0) { item->setAxis(-1, GamepadAxisEvent::NEUTRAL); } - if (axis.isNull() && m_profile) { - int axisInt; - GamepadAxisEvent::Direction direction; - if (m_profile->lookupShortcutAxis(item->name(), &axisInt, &direction)) { - axis = QLatin1String(direction == GamepadAxisEvent::Direction::NEGATIVE ? "-" : "+") + QString::number(axisInt); - } - } if (!axis.isNull()) { QString axisDesc = axis.toString(); if (axisDesc.size() >= 2) { @@ -240,14 +229,6 @@ int InputIndex::toModifierKey(int key) { return modifiers; } -void InputIndex::loadProfile(const QString& profile) { - m_profileName = profile; - m_profile = InputProfile::findProfile(profile); - for (auto& item : m_items) { - loadShortcuts(item); - } -} - void InputIndex::saveConfig() { for (auto& item : m_items) { m_config->setQtOption(item->name(), QKeySequence(item->shortcut()).toString(), KEY_SECTION); diff --git a/src/platform/qt/input/InputIndex.h b/src/platform/qt/input/InputIndex.h index 0c9cd5b89..2d5190851 100644 --- a/src/platform/qt/input/InputIndex.h +++ b/src/platform/qt/input/InputIndex.h @@ -17,7 +17,6 @@ class QMenu; namespace QGBA { class ConfigController; -class InputProfile; class InputIndex { private: @@ -25,10 +24,6 @@ private: constexpr static const char* const BUTTON_SECTION = "shortcutButton"; constexpr static const char* const AXIS_SECTION = "shortcutAxis"; constexpr static const char* const HAT_SECTION = "shortcutHat"; - constexpr static const char* const KEY_PROFILE_SECTION = "shortcutProfileKey."; - constexpr static const char* const BUTTON_PROFILE_SECTION = "shortcutProfileButton."; - constexpr static const char* const AXIS_PROFILE_SECTION = "shortcutProfileAxis."; - constexpr static const char* const HAT_PROFILE_SECTION = "shortcutProfileHat."; public: void setConfigController(ConfigController* controller); @@ -60,8 +55,6 @@ public: static bool isModifierKey(int key); static int toModifierKey(int key); - void loadProfile(const QString& profile); - void saveConfig(); private: @@ -79,8 +72,6 @@ private: QMap, InputItem*> m_axes; ConfigController* m_config = nullptr; - QString m_profileName; - const InputProfile* m_profile = nullptr; }; } diff --git a/src/platform/qt/input/InputProfile.cpp b/src/platform/qt/input/InputProfile.cpp index 743baa70f..3cb1f80ba 100644 --- a/src/platform/qt/input/InputProfile.cpp +++ b/src/platform/qt/input/InputProfile.cpp @@ -7,262 +7,93 @@ #include "InputController.h" -#include +#include using namespace QGBA; -const InputProfile InputProfile::s_defaultMaps[] = { - { - "XInput Controller #\\d+", // XInput (Windows) - { - /*keyA */ 11, - /*keyB */ 10, - /*keySelect */ 5, - /*keyStart */ 4, - /*keyRight */ 3, - /*keyLeft */ 2, - /*keyUp */ 0, - /*keyDown */ 1, - /*keyR */ 9, - /*keyL */ 8 - }, - { - /*loadState */ 12, - /*saveState */ 13, - /*holdFastForward */ -1, - /*holdRewind */ -1, - }, - { - /*loadState */ {GamepadAxisEvent::Direction::NEUTRAL, -1}, - /*saveState */ {GamepadAxisEvent::Direction::NEUTRAL, -1}, - /*holdFastForward */ {GamepadAxisEvent::Direction::POSITIVE, 5}, - /*holdRewind */ {GamepadAxisEvent::Direction::POSITIVE, 4}, - } - }, - { - "(Microsoft X-Box 360 pad|Xbox Gamepad \\(userspace driver\\))", // Linux - { - /*keyA */ 1, - /*keyB */ 0, - /*keySelect */ 6, - /*keyStart */ 7, - /*keyRight */ -1, - /*keyLeft */ -1, - /*keyUp */ -1, - /*keyDown */ -1, - /*keyR */ 5, - /*keyL */ 4 - }, - { - /*loadState */ 2, - /*saveState */ 3, - /*holdFastForward */ -1, - /*holdRewind */ -1, - }, - { - /*loadState */ {GamepadAxisEvent::Direction::NEUTRAL, -1}, - /*saveState */ {GamepadAxisEvent::Direction::NEUTRAL, -1}, - /*holdFastForward */ {GamepadAxisEvent::Direction::POSITIVE, 5}, - /*holdRewind */ {GamepadAxisEvent::Direction::POSITIVE, 2}, - } - }, - { - "Xbox 360 Wired Controller", // OS X - { - /*keyA */ 1, - /*keyB */ 0, - /*keySelect */ 9, - /*keyStart */ 8, - /*keyRight */ 14, - /*keyLeft */ 13, - /*keyUp */ 11, - /*keyDown */ 12, - /*keyR */ 5, - /*keyL */ 4 - }, - { - /*loadState */ 2, - /*saveState */ 3, - /*holdFastForward */ -1, - /*holdRewind */ -1, - }, - { - /*loadState */ {GamepadAxisEvent::Direction::NEUTRAL, -1}, - /*saveState */ {GamepadAxisEvent::Direction::NEUTRAL, -1}, - /*holdFastForward */ {GamepadAxisEvent::Direction::POSITIVE, 5}, - /*holdRewind */ {GamepadAxisEvent::Direction::POSITIVE, 2}, - } - }, - { - "(Sony Computer Entertainment )?Wireless Controller", // The DualShock 4 device ID is cut off on Windows - { - /*keyA */ 1, - /*keyB */ 2, - /*keySelect */ 8, - /*keyStart */ 9, - /*keyRight */ -1, - /*keyLeft */ -1, - /*keyUp */ -1, - /*keyDown */ -1, - /*keyR */ 5, - /*keyL */ 4 - }, - { - /*loadState */ 0, - /*saveState */ 3, - /*holdFastForward */ 7, - /*holdRewind */ 6, - }, - }, - { - "PLAYSTATION\\(R\\)3 Controller", // DualShock 3 (OS X) - { - /*keyA */ 13, - /*keyB */ 14, - /*keySelect */ 0, - /*keyStart */ 3, - /*keyRight */ 5, - /*keyLeft */ 7, - /*keyUp */ 4, - /*keyDown */ 6, - /*keyR */ 11, - /*keyL */ 10 - }, - { - /*loadState */ 15, - /*saveState */ 12, - /*holdFastForward */ 9, - /*holdRewind */ 8, - }, - }, - { - "Wiimote \\(..-..-..-..-..-..\\)", // WJoy (OS X) - { - /*keyA */ 15, - /*keyB */ 16, - /*keySelect */ 7, - /*keyStart */ 6, - /*keyRight */ 14, - /*keyLeft */ 13, - /*keyUp */ 11, - /*keyDown */ 12, - /*keyR */ 20, - /*keyL */ 19 - }, - { - /*loadState */ 18, - /*saveState */ 17, - /*holdFastForward */ 22, - /*holdRewind */ 21, - }, - }, -}; +QList InputProfile::s_profiles; -constexpr InputProfile::InputProfile(const char* name, - const KeyList keys, - const Shortcuts shortcutButtons, - const Shortcuts shortcutAxes, - const KeyList axes, - const struct Coord& tiltAxis, - const struct Coord& gyroAxis, - float gyroSensitivity) +InputProfile::InputProfile(const QString& name) : m_profileName(name) - , m_keys { - keys.keyA, - keys.keyB, - keys.keySelect, - keys.keyStart, - keys.keyRight, - keys.keyLeft, - keys.keyUp, - keys.keyDown, - keys.keyR, - keys.keyL, - } - , m_axes { - axes.keyA, - axes.keyB, - axes.keySelect, - axes.keyStart, - axes.keyRight, - axes.keyLeft, - axes.keyUp, - axes.keyDown, - axes.keyR, - axes.keyL, - } - , m_shortcutButtons(shortcutButtons) - , m_shortcutAxes(shortcutAxes) - , m_tiltAxis(tiltAxis) - , m_gyroAxis(gyroAxis) - , m_gyroSensitivity(gyroSensitivity) { } +void InputProfile::loadDefaultProfiles() { + loadProfiles(":/input/default-profiles.ini"); +} + +void InputProfile::loadProfiles(const QString& path) { + QSettings profileIni(path, QSettings::IniFormat); + + for (const auto& group : profileIni.childGroups()) { + } + profileIni.beginGroup(PROFILE_SECTION); + for (const auto& group : profileIni.childGroups()) { + loadProfile(profileIni, group); + } + profileIni.endGroup(); +} + +void InputProfile::loadProfile(QSettings& profileIni, const QString& name) { + profileIni.beginGroup(name); + s_profiles.append(name); + InputProfile& profile = s_profiles.last(); + for (const auto& group : profileIni.childGroups()) { + profileIni.beginGroup(group); + if (group == MATCH_SECTION) { + for (const auto& key : profileIni.childKeys()) { + profile.m_match.append(QRegExp(profileIni.value(key).toString())); + } + } + for (const auto& key : profileIni.childKeys()) { + InputItem* item = profile.m_inputIndex.itemAt(key); + if (!item) { + item = profile.m_inputIndex.addItem(QString(), key); + } + if (group == BUTTON_SECTION) { + item->setButton(profileIni.value(key).toInt()); + } + if (group == AXIS_SECTION) { + QString axisDescription = profileIni.value(key).toString(); + GamepadAxisEvent::Direction direction = GamepadAxisEvent::POSITIVE; + int axis = profileIni.value(key).toInt(); + if (axisDescription[0] == '-') { + direction = GamepadAxisEvent::NEGATIVE; + axis = -axis; + } + + item->setAxis(axis, direction); + } + if (group == KEY_SECTION) { + item->setShortcut(profileIni.value(key).toInt()); + } + } + profileIni.endGroup(); + } + profile.m_inputIndex.rebuild(); + profileIni.endGroup(); +} + const InputProfile* InputProfile::findProfile(const QString& name) { - for (size_t i = 0; i < sizeof(s_defaultMaps) / sizeof(*s_defaultMaps); ++i) { - QRegExp re(s_defaultMaps[i].m_profileName); - if (re.exactMatch(name)) { - return &s_defaultMaps[i]; + if (s_profiles.isEmpty()) { + loadDefaultProfiles(); + } + for (const InputProfile& profile : s_profiles) { + for (const auto& match : profile.m_match) { + if (match.exactMatch(name)) { + return &profile; + } } } return nullptr; } void InputProfile::apply(InputController* controller) const { - for (size_t i = 0; i < GBA_KEY_MAX; ++i) { -#ifdef BUILD_SDL - controller->bindKey(SDL_BINDING_BUTTON, m_keys[i], GBAInputInfo.keyId[i]); - controller->bindAxis(SDL_BINDING_BUTTON, m_axes[i].axis, m_axes[i].direction, GBAInputInfo.keyId[i]); -#endif - } + controller->rebuildIndex(&m_inputIndex); + controller->rebuildKeyIndex(&m_inputIndex); controller->registerTiltAxisX(m_tiltAxis.x); controller->registerTiltAxisY(m_tiltAxis.y); controller->registerGyroAxisX(m_gyroAxis.x); controller->registerGyroAxisY(m_gyroAxis.y); controller->setGyroSensitivity(m_gyroSensitivity); } - -bool InputProfile::lookupShortcutButton(const QString& shortcutName, int* button) const { - if (shortcutName == QLatin1String("loadState")) { - *button = m_shortcutButtons.loadState; - return true; - } - if (shortcutName == QLatin1String("saveState")) { - *button = m_shortcutButtons.saveState; - return true; - } - if (shortcutName == QLatin1String("holdFastForward")) { - *button = m_shortcutButtons.holdFastForward; - return true; - } - if (shortcutName == QLatin1String("holdRewind")) { - *button = m_shortcutButtons.holdRewind; - return true; - } - return false; -} - -bool InputProfile::lookupShortcutAxis(const QString& shortcutName, int* axis, GamepadAxisEvent::Direction* direction) const { - if (shortcutName == QLatin1String("loadState")) { - *axis = m_shortcutAxes.loadState.axis; - *direction = m_shortcutAxes.loadState.direction; - return true; - } - if (shortcutName == QLatin1String("saveState")) { - *axis = m_shortcutAxes.saveState.axis; - *direction = m_shortcutAxes.saveState.direction; - return true; - } - if (shortcutName == QLatin1String("holdFastForward")) { - *axis = m_shortcutAxes.holdFastForward.axis; - *direction = m_shortcutAxes.holdFastForward.direction; - return true; - } - if (shortcutName == QLatin1String("holdRewind")) { - *axis = m_shortcutAxes.holdRewind.axis; - *direction = m_shortcutAxes.holdRewind.direction; - return true; - } - return false; -} diff --git a/src/platform/qt/input/InputProfile.h b/src/platform/qt/input/InputProfile.h index 748987d20..8a7270e10 100644 --- a/src/platform/qt/input/InputProfile.h +++ b/src/platform/qt/input/InputProfile.h @@ -7,91 +7,52 @@ #define QGBA_INPUT_PROFILE #include "GamepadAxisEvent.h" +#include "InputIndex.h" #include #include +#include + +class QSettings; + namespace QGBA { class InputController; class InputProfile { public: + constexpr static const char* const PROFILE_SECTION = "profiles"; + constexpr static const char* const MATCH_SECTION = "match"; + constexpr static const char* const KEY_SECTION = "keys"; + constexpr static const char* const BUTTON_SECTION = "buttons"; + constexpr static const char* const AXIS_SECTION = "axes"; + constexpr static const char* const HAT_SECTION = "hats"; + static const InputProfile* findProfile(const QString& name); + static void loadProfiles(const QString& path); void apply(InputController*) const; - bool lookupShortcutButton(const QString& shortcut, int* button) const; - bool lookupShortcutAxis(const QString& shortcut, int* axis, GamepadAxisEvent::Direction* direction) const; - private: + InputProfile(const QString&); + struct Coord { int x; int y; }; - struct AxisValue { - GamepadAxisEvent::Direction direction; - int axis; - }; + static void loadDefaultProfiles(); + static void loadProfile(QSettings&, const QString& name); - template struct Shortcuts { - T loadState; - T saveState; - T holdFastForward; - T holdRewind; - }; + static QList s_profiles; - struct Axis { - GamepadAxisEvent::Direction direction; - int axis; - }; + QString m_profileName; + QList m_match; - template struct KeyList { - T keyA; - T keyB; - T keySelect; - T keyStart; - T keyRight; - T keyLeft; - T keyUp; - T keyDown; - T keyR; - T keyL; - }; - - constexpr InputProfile(const char* name, - const KeyList keys, - const Shortcuts shortcutButtons = { -1, -1, -1, -1}, - const Shortcuts shortcutAxes = { - {GamepadAxisEvent::Direction::NEUTRAL, -1}, - {GamepadAxisEvent::Direction::NEUTRAL, -1}, - {GamepadAxisEvent::Direction::NEUTRAL, -1}, - {GamepadAxisEvent::Direction::NEUTRAL, -1}}, - const KeyList axes = { - { GamepadAxisEvent::Direction::NEUTRAL, -1 }, - { GamepadAxisEvent::Direction::NEUTRAL, -1 }, - { GamepadAxisEvent::Direction::NEUTRAL, -1 }, - { GamepadAxisEvent::Direction::NEUTRAL, -1 }, - { GamepadAxisEvent::Direction::POSITIVE, 0 }, - { GamepadAxisEvent::Direction::NEGATIVE, 0 }, - { GamepadAxisEvent::Direction::NEGATIVE, 1 }, - { GamepadAxisEvent::Direction::POSITIVE, 1 }, - { GamepadAxisEvent::Direction::NEUTRAL, -1 }, - { GamepadAxisEvent::Direction::NEUTRAL, -1 }}, - const struct Coord& tiltAxis = { 2, 3 }, - const struct Coord& gyroAxis = { 0, 1 }, - float gyroSensitivity = 2e+09f); - - static const InputProfile s_defaultMaps[]; - - const char* m_profileName; - const int m_keys[GBA_KEY_MAX]; - const AxisValue m_axes[GBA_KEY_MAX]; - const Shortcuts m_shortcutButtons; - const Shortcuts m_shortcutAxes; - Coord m_tiltAxis; - Coord m_gyroAxis; - float m_gyroSensitivity; + Coord m_tiltAxis = { 2, 3 }; + Coord m_gyroAxis = { 0, 1 }; + float m_gyroSensitivity = 2e+09f; + InputIndex m_inputIndex; }; } diff --git a/src/platform/qt/input/default-profiles.ini b/src/platform/qt/input/default-profiles.ini new file mode 100644 index 000000000..5504cabbc --- /dev/null +++ b/src/platform/qt/input/default-profiles.ini @@ -0,0 +1,114 @@ +[profiles/XInput (Windows)/match] +0=XInput Controller #\\d+ + +[profiles/XInput (Windows)/buttons] +keyA=11 +keyB=10 +keySelect=5 +keyStart=4 +keyRight=3 +keyLeft=2 +keyUp=0 +keyDown=1 +keyR=9 +keyL=8 +loadState=12 +saveState=13 + +[profiles/XInput (Windows)/axes] +holdFastForward=+5 +holdRewind=+4 + +[profiles/XInput (Linux)/match] +0=Microsoft X-Box 360 pad +1=Xbox Gamepad \\(userspace driver\\) + +[profiles/XInput (Linux)/buttons] +keyA=1 +keyB=0 +keySelect=6 +keyStart=7 +keyR=5 +keyL=4 +loadState=2 +saveState=3 + +[profiles/XInput (Linux)/axes] +holdFastForward=+5 +holdRewind=+2 + +[profiles/XInput (macOS)/match] +0=Xbox 360 Wired Controller + +[profiles/XInput (macOS)/buttons] +keyA=1 +keyB=0 +keySelect=9 +keyStart=8 +keyRight=14 +keyLeft=13 +keyUp=11 +keyDown=12 +keyR=5 +keyL=4 +loadState=2 +saveState=3 + +[profiles/XInput (macOS)/axes] +holdFastForward=+5 +holdRewind=+2 + + +[profiles/DualShock 4/match] +0=Sony Computer Entertainment Wireless Controller +1=Wireless Controller + +[profiles/DualShock 4/buttons] +keyA=1 +keyB=2 +keySelect=8 +keyStart=9 +keyR=5 +keyL=4 +loadState=0 +saveState=3 +holdFastForward=7 +holdRewind=6 + +[profiles/DualShock 3/match] +0=PLAYSTATION\\(R\\)3 Controller + +[profiles/DualShock 3/buttons] +keyA=13 +keyB=14 +keySelect=0 +keyStart=3 +keyRight=5 +keyLeft=7 +keyUp=4 +keyDown=6 +keyR=11 +keyL=10 +loadState=15 +saveState=12 +holdFastForward=9 +holdRewind=8 + +[profiles/Wii Remote/match] +0=Wiimote \\(..-..-..-..-..-..\\) + +[profiles/Wii Remote/buttons] +keyA=15 +keyB=16 +keySelect=7 +keyStart=6 +keyRight=14 +keyLeft=13 +keyUp=11 +keyDown=12 +keyR=20 +keyL=19 +loadState=18 +saveState=17 +holdFastForward=22 +holdRewind=21 diff --git a/src/platform/qt/resources.qrc b/src/platform/qt/resources.qrc index 1629b7eaf..9e5d434ef 100644 --- a/src/platform/qt/resources.qrc +++ b/src/platform/qt/resources.qrc @@ -3,5 +3,6 @@ ../../../res/mgba-1024.png ../../../res/keymap.qpic ../../../res/patrons.txt + input/default-profiles.ini diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index b9f765aec..c059082f8 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -350,7 +350,7 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration* } if (events->preferredJoysticks[i] && strcmp(events->preferredJoysticks[i], joystickName) == 0) { events->players[i]->joystick = joystick; - if (config) { + if (config && events->players[i]->bindings) { mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); } return; @@ -361,7 +361,7 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration* continue; } events->players[i]->joystick = joystick; - if (config) { + if (config && events->players[i]->bindings) { mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); } break;