Qt: Separate out shortcuts from controls, restore saving

This commit is contained in:
Vicki Pfau 2017-07-02 16:59:16 -07:00
parent 495e98a83f
commit bd31223831
11 changed files with 230 additions and 221 deletions

View File

@ -145,11 +145,16 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
}
});
m_keyView = new ShortcutView();
m_keyView->setModel(inputController->keyIndex());
m_keyView->setInputController(inputController);
m_shortcutView = new ShortcutView();
m_shortcutView->setModel(inputController->inputIndex());
m_shortcutView->setInputController(inputController);
m_ui.stackedWidget->addWidget(m_keyView);
m_ui.tabs->addItem(tr("Controls"));
m_ui.stackedWidget->addWidget(m_shortcutView);
m_ui.tabs->addItem(tr("Bindings"));
m_ui.tabs->addItem(tr("Shortcuts"));
}
void SettingsView::selectBios(QLineEdit* bios) {
@ -237,6 +242,7 @@ void SettingsView::updateConfig() {
m_controller->write();
m_input->rebuildIndex(m_shortcutView->root());
m_input->rebuildKeyIndex(m_keyView->root());
m_input->saveConfiguration();
emit pathsChanged();

View File

@ -43,6 +43,7 @@ private:
ConfigController* m_controller;
InputController* m_input;
ShortcutView* m_shortcutView;
ShortcutView* m_keyView;
void saveSetting(const char* key, const QAbstractButton*);
void saveSetting(const char* key, const QComboBox*);

View File

@ -175,6 +175,9 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
connect(this, &Window::audioBufferSamplesChanged, m_controller, &GameController::setAudioBufferSamples);
connect(this, &Window::sampleRateChanged, m_controller, &GameController::setAudioSampleRate);
connect(this, &Window::fpsTargetChanged, m_controller, &GameController::setFPSTarget);
connect(&m_inputController, &InputController::keyPressed, m_controller, &GameController::keyPressed);
connect(&m_inputController, &InputController::keyReleased, m_controller, &GameController::keyReleased);
connect(&m_inputController, &InputController::keyAutofire, m_controller, &GameController::setAutofire);
connect(&m_fpsTimer, &QTimer::timeout, this, &Window::showFPS);
connect(&m_focusCheck, &QTimer::timeout, this, &Window::focusCheck);
connect(m_display, &Display::hideCursor, [this]() {
@ -191,6 +194,13 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
m_focusCheck.setInterval(200);
setupMenu(menuBar());
#ifdef M_CORE_GBA
m_inputController.addPlatform(PLATFORM_GBA, &GBAInputInfo);
#endif
#ifdef M_CORE_GB
m_inputController.addPlatform(PLATFORM_GB, &GBInputInfo);
#endif
}
Window::~Window() {
@ -720,6 +730,8 @@ void Window::gameStarted(mCoreThread* context, const QString& fname) {
m_controller->threadInterrupt();
if (m_controller->isLoaded()) {
m_inputController.setPlatform(m_controller->platform());
mCore* core = m_controller->thread()->core;
const mCoreChannelInfo* videoLayers;
const mCoreChannelInfo* audioChannels;
@ -1466,130 +1478,6 @@ void Window::setupMenu(QMenuBar* menubar) {
exitFullScreen->setShortcut(QKeySequence("Esc"));
addHiddenAction(frameMenu, exitFullScreen, "exitFullScreen");
QMenu* autofireMenu = new QMenu(tr("Autofire"), this);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_A, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_A, false);
}), tr("Autofire A"), "autofireA", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_B, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_B, false);
}), tr("Autofire B"), "autofireB", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_L, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_L, false);
}), tr("Autofire L"), "autofireL", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_R, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_R, false);
}), tr("Autofire R"), "autofireR", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_START, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_START, false);
}), tr("Autofire Start"), "autofireStart", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_SELECT, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_SELECT, false);
}), tr("Autofire Select"), "autofireSelect", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_UP, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_UP, false);
}), tr("Autofire Up"), "autofireUp", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_RIGHT, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_RIGHT, false);
}), tr("Autofire Right"), "autofireRight", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_DOWN, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_DOWN, false);
}), tr("Autofire Down"), "autofireDown", autofireMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_LEFT, true);
}, [this]() {
m_controller->setAutofire(GBA_KEY_LEFT, false);
}), tr("Autofire Left"), "autofireLeft", autofireMenu);
QMenu* bindingsMenu = new QMenu(tr("Bindings"), this);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_A);
}, [this]() {
m_controller->keyReleased(GBA_KEY_A);
}), tr("A"), "keyA", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_B);
}, [this]() {
m_controller->keyReleased(GBA_KEY_B);
}), tr("B"), "keyB", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_START);
}, [this]() {
m_controller->keyReleased(GBA_KEY_START);
}), tr("Start"), "keyStart", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_SELECT);
}, [this]() {
m_controller->keyReleased(GBA_KEY_SELECT);
}), tr("Select"), "keySelect", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_L);
}, [this]() {
m_controller->keyReleased(GBA_KEY_L);
}), tr("L"), "keyL", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_R);
}, [this]() {
m_controller->keyReleased(GBA_KEY_R);
}), tr("R"), "keyR", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_UP);
}, [this]() {
m_controller->keyReleased(GBA_KEY_UP);
}), tr("Up"), "keyUp", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_DOWN);
}, [this]() {
m_controller->keyReleased(GBA_KEY_DOWN);
}), tr("Down"), "keyDown", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_LEFT);
}, [this]() {
m_controller->keyReleased(GBA_KEY_LEFT);
}), tr("Left"), "keyLeft", bindingsMenu);
m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_RIGHT);
}, [this]() {
m_controller->keyReleased(GBA_KEY_RIGHT);
}), tr("Right"), "keyRight", bindingsMenu);
for (QAction* action : m_gameActions) {
action->setDisabled(true);
}

View File

@ -22,6 +22,8 @@
#include <mgba/core/interface.h>
#include <mgba-util/configuration.h>
#include <initializer_list>
using namespace QGBA;
#ifdef BUILD_SDL
@ -34,6 +36,8 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
, m_playerId(playerId)
, m_topLevel(topLevel)
, m_focusParent(topLevel)
, m_bindings(new QMenu(tr("Controls")))
, m_autofire(new QMenu(tr("Autofire")))
{
#ifdef BUILD_SDL
if (s_sdlInited == 0) {
@ -54,26 +58,75 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
m_gamepadTimer.setInterval(50);
m_gamepadTimer.start();
mInputMapInit(&m_inputMap, &GBAInputInfo);
static QList<QPair<QString, int>> defaultBindings({
qMakePair(QLatin1String("A"), Qt::Key_Z),
qMakePair(QLatin1String("B"), Qt::Key_X),
qMakePair(QLatin1String("L"), Qt::Key_A),
qMakePair(QLatin1String("R"), Qt::Key_S),
qMakePair(QLatin1String("Start"), Qt::Key_Return),
qMakePair(QLatin1String("Select"), Qt::Key_Backspace),
qMakePair(QLatin1String("Up"), Qt::Key_Up),
qMakePair(QLatin1String("Down"), Qt::Key_Down),
qMakePair(QLatin1String("Left"), Qt::Key_Left),
qMakePair(QLatin1String("Right"), Qt::Key_Right)
});
for (auto k : defaultBindings) {
addKey(k.first);
}
m_keyIndex.rebuild();
for (auto k : defaultBindings) {
bindKey(KEYBOARD, k.second, k.first);
}
}
void InputController::addKey(const QString& name) {
if (itemForKey(name)) {
return;
}
m_keyIndex.addItem(qMakePair([this, name]() {
emit keyPressed(keyId(name));
}, [this, name]() {
emit keyReleased(keyId(name));
}), name, QString("key%0").arg(name), m_bindings.get());
m_keyIndex.addItem(qMakePair([this, name]() {
emit keyAutofire(keyId(name), true);
}, [this, name]() {
emit keyAutofire(keyId(name), false);
}), name, QString("autofire%1").arg(name), m_autofire.get());
}
void InputController::addPlatform(mPlatform platform, const mInputPlatformInfo* info) {
m_keyInfo[platform] = info;
for (size_t i = 0; i < info->nKeys; ++i) {
addKey(info->keyId[i]);
}
}
void InputController::setPlatform(mPlatform platform) {
if (m_activeKeyInfo) {
mInputMapDeinit(&m_inputMap);
}
m_sdlPlayer.bindings = &m_inputMap;
m_activeKeyInfo = m_keyInfo[platform];
mInputMapInit(&m_inputMap, m_activeKeyInfo);
loadConfiguration(KEYBOARD);
#ifdef BUILD_SDL
mSDLInitBindingsGBA(&m_inputMap);
loadConfiguration(SDL_BINDING_BUTTON);
#endif
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_X, GBA_KEY_A);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Z, GBA_KEY_B);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_A, GBA_KEY_L);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_S, GBA_KEY_R);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Return, GBA_KEY_START);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Backspace, GBA_KEY_SELECT);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Up, GBA_KEY_UP);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Down, GBA_KEY_DOWN);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Left, GBA_KEY_LEFT);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Right, GBA_KEY_RIGHT);
rebuildKeyIndex();
restoreModel();
}
InputController::~InputController() {
mInputMapDeinit(&m_inputMap);
if (m_activeKeyInfo) {
mInputMapDeinit(&m_inputMap);
}
#ifdef BUILD_SDL
if (m_playerAttached) {
@ -89,24 +142,25 @@ InputController::~InputController() {
void InputController::rebuildIndex(const InputIndex* index) {
m_inputIndex.rebuild(index);
}
rebindKey(GBA_KEY_A);
rebindKey(GBA_KEY_B);
rebindKey(GBA_KEY_L);
rebindKey(GBA_KEY_R);
rebindKey(GBA_KEY_START);
rebindKey(GBA_KEY_SELECT);
rebindKey(GBA_KEY_UP);
rebindKey(GBA_KEY_DOWN);
rebindKey(GBA_KEY_LEFT);
rebindKey(GBA_KEY_RIGHT);
void InputController::rebuildKeyIndex(const InputIndex* index) {
m_keyIndex.rebuild(index);
for (const InputItem* item : m_keyIndex.items()) {
if (!item->name().startsWith(QLatin1String("key"))) {
rebindKey(item->visibleName());
}
}
}
void InputController::setConfiguration(ConfigController* config) {
m_config = config;
m_inputIndex.setConfigController(config);
m_keyIndex.setConfigController(config);
setAllowOpposing(config->getOption("allowOpposingDirections").toInt());
loadConfiguration(KEYBOARD);
loadProfile(KEYBOARD, profileForType(KEYBOARD));
#ifdef BUILD_SDL
mSDLEventsLoadConfig(&s_sdlEvents, config->input());
if (!m_playerAttached) {
@ -119,27 +173,30 @@ void InputController::setConfiguration(ConfigController* config) {
}
void InputController::loadConfiguration(uint32_t type) {
if (!m_activeKeyInfo) {
return;
}
mInputMapLoad(&m_inputMap, type, m_config->input());
#ifdef BUILD_SDL
if (m_playerAttached) {
mInputMap* bindings = m_sdlPlayer.bindings;
m_sdlPlayer.bindings = &m_inputMap;
mSDLPlayerLoadConfig(&m_sdlPlayer, m_config->input());
m_sdlPlayer.bindings = bindings;
}
#endif
}
void InputController::loadProfile(uint32_t type, const QString& profile) {
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);
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);
}
}
}
recalibrateAxes();
m_inputIndex.loadProfile(profile);
m_keyIndex.loadProfile(profile);
emit profileLoaded(profile);
}
@ -151,17 +208,23 @@ void InputController::saveConfiguration() {
if (m_playerAttached) {
mSDLPlayerSaveConfig(&m_sdlPlayer, m_config->input());
}
m_config->write();
#endif
m_inputIndex.saveConfig();
m_keyIndex.saveConfig();
m_config->write();
}
void InputController::saveConfiguration(uint32_t type) {
mInputMapSave(&m_inputMap, type, m_config->input());
if (m_activeKeyInfo) {
mInputMapSave(&m_inputMap, type, m_config->input());
}
m_config->write();
}
void InputController::saveProfile(uint32_t type, const QString& profile) {
mInputProfileSave(&m_inputMap, type, m_config->input(), profile.toUtf8().constData());
if (m_activeKeyInfo) {
mInputProfileSave(&m_inputMap, type, m_config->input(), profile.toUtf8().constData());
}
m_config->write();
}
@ -413,20 +476,27 @@ QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes
return activeAxes;
}
void InputController::bindKey(uint32_t type, int key, int coreKey) {
InputItem* item = itemForKey(coreKey);
void InputController::bindKey(uint32_t type, int key, const QString& keyName) {
InputItem* item = itemForKey(keyName);
if (type != KEYBOARD) {
item->setButton(key);
} else {
item->setShortcut(key);
}
mInputBindKey(&m_inputMap, type, key, coreKey);
if (m_activeKeyInfo) {
int coreKey = keyId(keyName);
mInputBindKey(&m_inputMap, type, key, coreKey);
}
}
void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction direction, int key) {
void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction direction, const QString& key) {
InputItem* item = itemForKey(key);
item->setAxis(axis, direction);
if (!m_activeKeyInfo) {
return;
}
const mInputAxis* old = mInputQueryAxis(&m_inputMap, type, axis);
mInputAxis description = { GBA_KEY_NONE, GBA_KEY_NONE, -AXIS_THRESHOLD, AXIS_THRESHOLD };
if (old) {
@ -438,12 +508,12 @@ void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direct
}
switch (direction) {
case GamepadAxisEvent::NEGATIVE:
description.lowDirection = key;
description.lowDirection = keyId(key);
description.deadLow = deadzone - AXIS_THRESHOLD;
break;
case GamepadAxisEvent::POSITIVE:
description.highDirection = key;
description.highDirection = keyId(key);
description.deadHigh = deadzone + AXIS_THRESHOLD;
break;
default:
@ -484,23 +554,25 @@ QSet<QPair<int, GamepadHatEvent::Direction>> InputController::activeGamepadHats(
return activeHats;
}
void InputController::bindHat(uint32_t type, int hat, GamepadHatEvent::Direction direction, int coreKey) {
//m_inputModel->updateHat(index, hat, direction);
void InputController::bindHat(uint32_t type, int hat, GamepadHatEvent::Direction direction, const QString& key) {
if (!m_activeKeyInfo) {
return;
}
mInputHatBindings bindings{ -1, -1, -1, -1 };
mInputQueryHat(&m_inputMap, type, hat, &bindings);
switch (direction) {
case GamepadHatEvent::UP:
bindings.up = coreKey;
bindings.up = keyId(key);
break;
case GamepadHatEvent::RIGHT:
bindings.right = coreKey;
bindings.right = keyId(key);
break;
case GamepadHatEvent::DOWN:
bindings.down = coreKey;
bindings.down = keyId(key);
break;
case GamepadHatEvent::LEFT:
bindings.left = coreKey;
bindings.left = keyId(key);
break;
default:
return;
@ -644,6 +716,7 @@ void InputController::releaseFocus(QWidget* focus) {
}
bool InputController::eventFilter(QObject*, QEvent* event) {
event->ignore();
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
int key = keyEvent->key();
@ -658,11 +731,16 @@ bool InputController::eventFilter(QObject*, QEvent* event) {
return true;
}
event->ignore();
InputItem* item = m_inputIndex.itemForShortcut(key);
if (item) {
item->trigger(event->type() == QEvent::KeyPress);
event->accept();
return true;
}
item = m_keyIndex.itemForShortcut(key);
if (item) {
item->trigger(event->type() == QEvent::KeyPress);
event->accept();
}
}
@ -673,7 +751,11 @@ bool InputController::eventFilter(QObject*, QEvent* event) {
if (item) {
item->trigger(event->type() == GamepadButtonEvent::Down());
event->accept();
return true;
}
item = m_keyIndex.itemForButton(gbe->value());
if (item) {
item->trigger(event->type() == GamepadButtonEvent::Down());
event->accept();
}
}
if (event->type() == GamepadAxisEvent::Type()) {
@ -682,23 +764,37 @@ bool InputController::eventFilter(QObject*, QEvent* event) {
if (item) {
item->trigger(event->type() == gae->isNew());
event->accept();
return true;
}
item = m_keyIndex.itemForAxis(gae->axis(), gae->direction());
if (item) {
item->trigger(event->type() == gae->isNew());
event->accept();
}
}
return false;
return event->isAccepted();
}
InputItem* InputController::itemForKey(int key) {
if (key < 0 || key >= m_inputMap.info->nKeys) {
return nullptr;
InputItem* InputController::itemForKey(const QString& key) {
return m_keyIndex.itemAt(QString("key%0").arg(key));
}
int InputController::keyId(const QString& key) {
for (int i = 0; i < m_activeKeyInfo->nKeys; ++i) {
if (m_activeKeyInfo->keyId[i] == key) {
return i;
}
}
return m_inputIndex.itemAt(QString("key%0").arg(m_inputMap.info->keyId[key]));
return -1;
}
void InputController::restoreModel() {
if (!m_activeKeyInfo) {
return;
}
int nKeys = m_inputMap.info->nKeys;
for (int i = 0; i < nKeys; ++i) {
InputItem* item = itemForKey(i);
const QString& keyName = m_inputMap.info->keyId[i];
InputItem* item = itemForKey(keyName);
if (item) {
int key = mInputQueryBinding(&m_inputMap, KEYBOARD, i);
if (key >= 0) {
@ -717,36 +813,34 @@ void InputController::restoreModel() {
}
}
#ifdef BUILD_SDL
struct Context {
InputIndex* model;
InputController* controller;
} context {
&m_inputIndex,
this
};
mInputEnumerateAxes(&m_inputMap, SDL_BINDING_BUTTON, [](int axis, const struct mInputAxis* description, void* user) {
Context* context = static_cast<Context*>(user);
InputIndex* model = context->model;
InputController* controller = context->controller;
InputController* controller = static_cast<InputController*>(user);
InputItem* item;
const mInputPlatformInfo* inputMap = controller->m_inputMap.info;
if (description->highDirection >= 0 && description->highDirection < controller->m_inputMap.info->nKeys) {
item = controller->itemForKey(description->highDirection);
if (item) {
item->setAxis(axis, GamepadAxisEvent::POSITIVE);
int id = description->lowDirection;
if (id >= 0 && id < inputMap->nKeys) {
item = controller->itemForKey(inputMap->keyId[id]);
if (item) {
item->setAxis(axis, GamepadAxisEvent::POSITIVE);
}
}
}
if (description->lowDirection >= 0 && description->lowDirection < controller->m_inputMap.info->nKeys) {
item = controller->itemForKey(description->lowDirection);
if (item) {
item->setAxis(axis, GamepadAxisEvent::NEGATIVE);
int id = description->highDirection;
if (id >= 0 && id < inputMap->nKeys) {
item = controller->itemForKey(inputMap->keyId[id]);
if (item) {
item->setAxis(axis, GamepadAxisEvent::NEGATIVE);
}
}
}
}, &context);
}, this);
#endif
rebuildIndex();
rebuildKeyIndex();
}
void InputController::rebindKey(int key) {
void InputController::rebindKey(const QString& key) {
InputItem* item = itemForKey(key);
bindKey(KEYBOARD, item->shortcut(), key);
#ifdef BUILD_SDL

View File

@ -46,7 +46,13 @@ public:
~InputController();
InputIndex* inputIndex() { return &m_inputIndex; }
InputIndex* keyIndex() { return &m_keyIndex; }
void rebuildIndex(const InputIndex* = nullptr);
void rebuildKeyIndex(const InputIndex* = nullptr);
void addPlatform(mPlatform, const mInputPlatformInfo*);
void setPlatform(mPlatform);
void addKey(const QString& name);
void setConfiguration(ConfigController* config);
void saveConfiguration();
@ -69,9 +75,9 @@ public:
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
void recalibrateAxes();
void bindKey(uint32_t type, int key, int);
void bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction, int);
void bindHat(uint32_t type, int hat, GamepadHatEvent::Direction, int);
void bindKey(uint32_t type, int key, const QString&);
void bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction, const QString&);
void bindHat(uint32_t type, int hat, GamepadHatEvent::Direction, const QString&);
QStringList connectedGamepads(uint32_t type) const;
int gamepad(uint32_t type) const;
@ -94,6 +100,9 @@ public:
signals:
void profileLoaded(const QString& profile);
void keyPressed(int);
void keyReleased(int);
void keyAutofire(int, bool enabled);
public slots:
void testGamepad(int type);
@ -113,17 +122,24 @@ private:
bool hasPendingEvent(int key) const;
void sendGamepadEvent(QEvent*);
void restoreModel();
void rebindKey(int key);
void rebindKey(const QString& key);
InputItem* itemForKey(int key);
InputItem* itemForKey(const QString& key);
int keyId(const QString& key);
InputIndex m_inputIndex;
InputIndex m_keyIndex;
mInputMap m_inputMap;
ConfigController* m_config = nullptr;
int m_playerId;
bool m_allowOpposing = false;
QWidget* m_topLevel;
QWidget* m_focusParent;
QMap<mPlatform, const mInputPlatformInfo*> m_keyInfo;
const mInputPlatformInfo* m_activeKeyInfo = nullptr;
std::unique_ptr<QMenu> m_bindings;
std::unique_ptr<QMenu> m_autofire;
#ifdef BUILD_SDL
static int s_sdlInited;

View File

@ -12,6 +12,9 @@ using namespace QGBA;
void InputIndex::setConfigController(ConfigController* controller) {
m_config = controller;
for (auto& item : m_items) {
loadShortcuts(item);
}
}
void InputIndex::clone(InputIndex* root, bool actions) {
@ -241,7 +244,16 @@ void InputIndex::loadProfile(const QString& profile) {
m_profileName = profile;
m_profile = InputProfile::findProfile(profile);
for (auto& item : m_items) {
loadGamepadShortcuts(item);
loadShortcuts(item);
}
}
void InputIndex::saveConfig() {
for (auto& item : m_items) {
m_config->setQtOption(item->name(), QKeySequence(item->shortcut()).toString(), KEY_SECTION);
m_config->setQtOption(item->name(), item->button(), BUTTON_SECTION);
if (item->direction() != GamepadAxisEvent::NEUTRAL) {
m_config->setQtOption(item->name(), QString("%1%2").arg(GamepadAxisEvent::POSITIVE ? '+' : '-').arg(item->axis()), AXIS_SECTION);
}
}
}

View File

@ -24,8 +24,11 @@ private:
constexpr static const char* const KEY_SECTION = "shortcutKey";
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);
@ -59,6 +62,8 @@ public:
void loadProfile(const QString& profile);
void saveConfig();
private:
bool loadShortcuts(InputItem*);
void loadGamepadShortcuts(InputItem*);

View File

@ -34,15 +34,6 @@ InputItem::InputItem(InputItem::Functions functions, const QString& visibleName,
{
}
InputItem::InputItem(int key, const QString& visibleName, const QString& name, QMenu* parent)
: QObject(parent)
, m_key(key)
, m_name(name)
, m_visibleName(visibleName)
, m_menu(parent)
{
}
InputItem::InputItem(const QString& visibleName, const QString& name, QMenu* parent)
: QObject(parent)
, m_name(name)
@ -67,7 +58,6 @@ InputItem::InputItem(InputItem& other)
: QObject(other.m_menu)
, m_action(other.m_action)
, m_functions(other.m_functions)
, m_key(other.m_key)
, m_name(other.m_name)
, m_visibleName(other.m_visibleName)
, m_shortcut(other.m_shortcut)

View File

@ -24,7 +24,6 @@ public:
InputItem(QAction* action, const QString& name, QMenu* parent = nullptr);
InputItem(Functions functions, const QString& visibleName, const QString& name,
QMenu* parent = nullptr);
InputItem(int key, const QString& name, const QString& visibleName, QMenu* parent = nullptr);
InputItem(const QString& visibleName, const QString& name, QMenu* parent = nullptr);
InputItem();
@ -34,7 +33,6 @@ public:
QAction* action() { return m_action; }
const QAction* action() const { return m_action; }
Functions functions() const { return m_functions; }
int key() const { return m_key; }
QMenu* menu() { return m_menu; }
const QMenu* menu() const { return m_menu; }
@ -70,7 +68,6 @@ signals:
private:
QAction* m_action = nullptr;
Functions m_functions;
int m_key = -1;
QMenu* m_menu = nullptr;
QString m_name;

View File

@ -138,11 +138,11 @@ QModelIndex InputModel::parent(const QModelIndex& index) const {
}
QModelIndex InputModel::index(const QObject* item, int column) const {
if (!item || !item->parent()) {
if (!item) {
return QModelIndex();
}
const QObject* parent = item->parent();
if (m_tree.contains(parent)) {
if (parent && m_tree.contains(parent)) {
int index = m_tree[parent].indexOf(item);
return createIndex(index, column, const_cast<InputModelItem*>(&m_tree[parent][index]));
}

View File

@ -212,8 +212,8 @@ const InputProfile* InputProfile::findProfile(const QString& name) {
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], static_cast<GBAKey>(i));
controller->bindAxis(SDL_BINDING_BUTTON, m_axes[i].axis, m_axes[i].direction, static_cast<GBAKey>(i));
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->registerTiltAxisX(m_tiltAxis.x);