mirror of https://github.com/mgba-emu/mgba.git
Qt: Separate out shortcuts from controls, restore saving
This commit is contained in:
parent
495e98a83f
commit
bd31223831
|
@ -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();
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue