diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 7468bcb29..d086057e1 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -31,7 +31,6 @@ mSDLEvents InputController::s_sdlEvents; InputController::InputController(InputModel* model, int playerId, QWidget* topLevel, QObject* parent) : QObject(parent) , m_inputModel(model) - , m_platform(PLATFORM_NONE) , m_playerId(playerId) , m_topLevel(topLevel) , m_focusParent(topLevel) @@ -55,21 +54,29 @@ InputController::InputController(InputModel* model, int playerId, QWidget* topLe m_gamepadTimer.setInterval(50); m_gamepadTimer.start(); - m_autofireMenu = std::unique_ptr(new QMenu(tr("Autofire"))); - m_inputModel->addMenu(m_autofireMenu.get()); + m_autofireMenu = m_inputModel->root()->addItem(tr("Autofire"), "autofire"); + m_inputMenu = m_inputModel->root()->addItem(tr("Bindings"), "bindings"); - m_inputMenu = std::unique_ptr(new QMenu(tr("Bindings"))); - m_inputModel->addMenu(m_inputMenu.get()); + mInputMapInit(&m_inputMap, &GBAInputInfo); - connect(m_inputModel, SIGNAL(keyRebound(const QModelIndex&, int)), this, SLOT(bindKey(const QModelIndex&, int))); - connect(m_inputModel, SIGNAL(buttonRebound(const QModelIndex&, int)), this, SLOT(bindButton(const QModelIndex&, int))); - connect(m_inputModel, SIGNAL(axisRebound(const QModelIndex&, int, GamepadAxisEvent::Direction)), this, SLOT(bindAxis(const QModelIndex&, int, GamepadAxisEvent::Direction))); +#ifdef BUILD_SDL + mSDLInitBindingsGBA(&m_inputMap); +#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); } InputController::~InputController() { - for (auto& inputMap : m_inputMaps) { - mInputMapDeinit(&inputMap); - } + mInputMapDeinit(&m_inputMap); #ifdef BUILD_SDL if (m_playerAttached) { @@ -83,42 +90,6 @@ InputController::~InputController() { #endif } -void InputController::addPlatform(mPlatform platform, const QString& visibleName, const mInputPlatformInfo* info) { - mInputMap* inputMap = &m_inputMaps[platform]; - mInputMapInit(inputMap, info); - - QMenu* input = m_inputMenu->addMenu(visibleName); - QMenu* autofire = m_autofireMenu->addMenu(visibleName); - m_inputMenuIndices[platform] = m_inputModel->addMenu(input, m_inputMenu.get()); - m_inputModel->addMenu(autofire, m_autofireMenu.get()); - - for (size_t i = 0; i < info->nKeys; ++i) { - m_inputModel->addKey(input, platform, i, 0, info->keyId[i], QString("%1.%2").arg(info->platformName).arg(info->keyId[i])); - m_inputModel->addKey(autofire, platform, i, 0, info->keyId[i], QString("%1.autofire.%2").arg(info->platformName).arg(info->keyId[i])); - } - -#ifdef BUILD_SDL - mSDLInitBindingsGBA(inputMap); -#endif - mInputBindKey(inputMap, KEYBOARD, Qt::Key_X, GBA_KEY_A); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_Z, GBA_KEY_B); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_A, GBA_KEY_L); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_S, GBA_KEY_R); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_Return, GBA_KEY_START); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_Backspace, GBA_KEY_SELECT); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_Up, GBA_KEY_UP); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_Down, GBA_KEY_DOWN); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_Left, GBA_KEY_LEFT); - mInputBindKey(inputMap, KEYBOARD, Qt::Key_Right, GBA_KEY_RIGHT); -} - -void InputController::setPlatform(mPlatform platform) { -#ifdef BUILD_SDL - m_sdlPlayer.bindings = &m_inputMaps[platform]; -#endif - m_platform = platform; -} - void InputController::setConfiguration(ConfigController* config) { m_config = config; setAllowOpposing(config->getOption("allowOpposingDirections").toInt()); @@ -135,31 +106,27 @@ void InputController::setConfiguration(ConfigController* config) { } void InputController::loadConfiguration(uint32_t type) { - for (auto& inputMap : m_inputMaps) { - mInputMapLoad(&inputMap, type, m_config->input()); + mInputMapLoad(&m_inputMap, type, m_config->input()); #ifdef BUILD_SDL - if (m_playerAttached) { - mInputMap* bindings = m_sdlPlayer.bindings; - m_sdlPlayer.bindings = &inputMap; - mSDLPlayerLoadConfig(&m_sdlPlayer, m_config->input()); - m_sdlPlayer.bindings = bindings; - } -#endif + 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) { - for (auto iter = m_inputMaps.begin(); iter != m_inputMaps.end(); ++iter) { - bool loaded = mInputProfileLoad(&iter.value(), type, m_config->input(), profile.toUtf8().constData()); - if (!loaded) { - const InputProfile* ip = InputProfile::findProfile(iter.key(), profile); - if (ip) { - ip->apply(iter.key(), this); - } + 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_inputModel->loadProfile(PLATFORM_NONE, profile); // TODO + m_inputModel->loadProfile(profile); // TODO emit profileLoaded(profile); } @@ -176,19 +143,12 @@ void InputController::saveConfiguration() { } void InputController::saveConfiguration(uint32_t type) { - for (auto& inputMap : m_inputMaps) { - if (!inputMap.info) { - continue; - } - mInputMapSave(&inputMap, type, m_config->input()); - } + mInputMapSave(&m_inputMap, type, m_config->input()); m_config->write(); } void InputController::saveProfile(uint32_t type, const QString& profile) { - for (auto& inputMap : m_inputMaps) { - mInputProfileSave(&inputMap, type, m_config->input(), profile.toUtf8().constData()); - } + mInputProfileSave(&m_inputMap, type, m_config->input(), profile.toUtf8().constData()); m_config->write(); } @@ -337,7 +297,7 @@ void InputController::updateJoysticks() { } const mInputMap* InputController::map() { - return &m_inputMaps[m_platform]; + return &m_inputMap; } int InputController::pollEvents() { @@ -349,7 +309,7 @@ int InputController::pollEvents() { int numButtons = SDL_JoystickNumButtons(joystick); int i; for (i = 0; i < numButtons; ++i) { - GBAKey key = static_cast(mInputMapKey(&m_inputMaps[m_platform], SDL_BINDING_BUTTON, i)); + GBAKey key = static_cast(mInputMapKey(&m_inputMap, SDL_BINDING_BUTTON, i)); if (key == GBA_KEY_NONE) { continue; } @@ -363,14 +323,14 @@ int InputController::pollEvents() { int numHats = SDL_JoystickNumHats(joystick); for (i = 0; i < numHats; ++i) { int hat = SDL_JoystickGetHat(joystick, i); - activeButtons |= mInputMapHat(&m_inputMaps[m_platform], SDL_BINDING_BUTTON, i, hat); + 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); - enum GBAKey key = static_cast(mInputMapAxis(&m_inputMaps[m_platform], SDL_BINDING_BUTTON, i, value)); + enum GBAKey key = static_cast(mInputMapAxis(&m_inputMap, SDL_BINDING_BUTTON, i, value)); if (key != GBA_KEY_NONE) { activeButtons |= 1 << key; } @@ -440,31 +400,23 @@ QSet> InputController::activeGamepadAxes return activeAxes; } -void InputController::bindKey(mPlatform platform, uint32_t type, int key, int coreKey) { - if (m_inputMaps.find(platform) == m_inputMaps.end() || coreKey >= m_inputMaps[platform].info->nKeys) { - return; - } - QModelIndex index = m_inputModel->index(coreKey, 0, m_inputMenuIndices[platform]); - bool signalsBlocked = m_inputModel->blockSignals(true); +void InputController::bindKey(uint32_t type, int key, int coreKey) { + /*InputItem* item = m_inputModel->itemForKey(coreKey); if (type != KEYBOARD) { - m_inputModel->updateButton(index, key); + item->setButton(key); } else { - m_inputModel->updateKey(index, key); - } - m_inputModel->blockSignals(signalsBlocked); - mInputBindKey(&m_inputMaps[platform], type, key, coreKey); + item->setShortcut(key); + }*/ + mInputBindKey(&m_inputMap, type, key, coreKey); } -void InputController::bindAxis(mPlatform platform, uint32_t type, int axis, GamepadAxisEvent::Direction direction, int key) { - if (m_inputMaps.find(platform) == m_inputMaps.end() || key >= m_inputMaps[platform].info->nKeys) { - return; - } - QModelIndex index = m_inputModel->index(key, 0, m_inputMenuIndices[platform]); +void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction direction, int key) { + //InputItem* item = m_inputModel->itemForKey(key); bool signalsBlocked = m_inputModel->blockSignals(true); - m_inputModel->updateAxis(index, axis, direction); + //item->setAxis(axis, direction); m_inputModel->blockSignals(signalsBlocked); - const mInputAxis* old = mInputQueryAxis(&m_inputMaps[platform], type, axis); + const mInputAxis* old = mInputQueryAxis(&m_inputMap, type, axis); mInputAxis description = { GBA_KEY_NONE, GBA_KEY_NONE, -AXIS_THRESHOLD, AXIS_THRESHOLD }; if (old) { description = *old; @@ -486,7 +438,7 @@ void InputController::bindAxis(mPlatform platform, uint32_t type, int axis, Game default: return; } - mInputBindAxis(&m_inputMaps[platform], type, axis, &description); + mInputBindAxis(&m_inputMap, type, axis, &description); } QSet> InputController::activeGamepadHats(int type) { @@ -521,15 +473,11 @@ QSet> InputController::activeGamepadHats( return activeHats; } -void InputController::bindHat(mPlatform platform, uint32_t type, int hat, GamepadHatEvent::Direction direction, int coreKey) { - if (m_inputMaps.find(platform) == m_inputMaps.end() || coreKey >= m_inputMaps[platform].info->nKeys) { - return; - } - QModelIndex index = m_inputModel->index(coreKey, 0, m_inputMenuIndices[platform]); +void InputController::bindHat(uint32_t type, int hat, GamepadHatEvent::Direction direction, int coreKey) { //m_inputModel->updateHat(index, hat, direction); mInputHatBindings bindings{ -1, -1, -1, -1 }; - mInputQueryHat(&m_inputMaps[platform], type, hat, &bindings); + mInputQueryHat(&m_inputMap, type, hat, &bindings); switch (direction) { case GamepadHatEvent::UP: bindings.up = coreKey; @@ -546,7 +494,7 @@ void InputController::bindHat(mPlatform platform, uint32_t type, int hat, Gamepa default: return; } - mInputBindHat(&m_inputMaps[platform], type, hat, &bindings); + mInputBindHat(&m_inputMap, type, hat, &bindings); } void InputController::testGamepad(int type) { @@ -685,8 +633,8 @@ void InputController::releaseFocus(QWidget* focus) { } void InputController::setupCallback(GameController* controller) { - m_inputModel->setKeyCallback([this, controller](QMenu* menu, int key, bool down) { - if (menu->parent() == m_autofireMenu.get()) { + [this, controller](InputItem* item, int key, bool down) { + if (item->parent() == m_autofireMenu) { controller->setAutofire(key, down); } else { if (down) { @@ -695,44 +643,40 @@ void InputController::setupCallback(GameController* controller) { controller->keyReleased(key); } } - }); + }; } -void InputController::bindKey(const QModelIndex& index, int key) { - int coreKey = m_inputModel->keyAt(index); +void InputController::doBindKey(const QModelIndex& index, int key) { + int coreKey = m_inputModel->itemAt(index)->key(); if (coreKey < 0) { return; } - mPlatform platform = m_inputMenuIndices.key(index.parent(), PLATFORM_NONE); - bindKey(platform, KEYBOARD, key, coreKey); + bindKey(KEYBOARD, key, coreKey); } #ifdef BUILD_SDL -void InputController::bindButton(const QModelIndex& index, int key) { - int coreKey = m_inputModel->keyAt(index); +void InputController::doBindButton(const QModelIndex& index, int key) { + int coreKey = m_inputModel->itemAt(index)->key(); if (coreKey < 0) { return; } - mPlatform platform = m_inputMenuIndices.key(index.parent(), PLATFORM_NONE); - bindKey(platform, SDL_BINDING_BUTTON, key, coreKey); + bindKey(SDL_BINDING_BUTTON, key, coreKey); } -void InputController::bindAxis(const QModelIndex& index, int axis, GamepadAxisEvent::Direction direction) { - int coreKey = m_inputModel->keyAt(index); +void InputController::doBindAxis(const QModelIndex& index, int axis, GamepadAxisEvent::Direction direction) { + int coreKey = m_inputModel->itemAt(index)->key(); if (coreKey < 0) { return; } - mPlatform platform = m_inputMenuIndices.key(index.parent(), PLATFORM_NONE); - bindAxis(platform, SDL_BINDING_BUTTON, axis, direction, coreKey); + bindAxis(SDL_BINDING_BUTTON, axis, direction, coreKey); } -void InputController::bindHat(const QModelIndex& index, int hat, GamepadHatEvent::Direction direction) { - int coreKey = m_inputModel->keyAt(index); +void InputController::doBindHat(const QModelIndex& index, int hat, GamepadHatEvent::Direction direction) { + int coreKey = m_inputModel->itemAt(index)->key(); if (coreKey < 0) { return; } - mPlatform platform = m_inputMenuIndices.key(index.parent(), PLATFORM_NONE); - bindHat(platform, SDL_BINDING_BUTTON, hat, direction, coreKey); + bindHat(SDL_BINDING_BUTTON, hat, direction, coreKey); } #else void InputController::bindButton(const QModelIndex& index, int key) {} @@ -755,67 +699,60 @@ bool InputController::eventFilter(QObject*, QEvent* event) { return true; } - if (m_inputModel->triggerKey(key, event->type() == QEvent::KeyPress, m_platform)) { - event->accept(); - return true; - } + // TODO } if (event->type() == GamepadButtonEvent::Down() || event->type() == GamepadButtonEvent::Up()) { GamepadButtonEvent* gbe = static_cast(event); - if (m_inputModel->triggerButton(gbe->value(), event->type() == GamepadButtonEvent::Down())) { - event->accept(); - return true; - } + // TODO } if (event->type() == GamepadAxisEvent::Type()) { GamepadAxisEvent* gae = static_cast(event); - if (m_inputModel->triggerAxis(gae->axis(), gae->direction(), gae->isNew())) { - event->accept(); - return true; - } + // TODO } return false; } void InputController::restoreModel() { bool signalsBlocked = m_inputModel->blockSignals(true); - for (auto iter = m_inputMaps.begin(); iter != m_inputMaps.end(); ++iter) { - mPlatform platform = iter.key(); - QModelIndex parent = m_inputMenuIndices[platform]; - int nKeys = iter->info->nKeys; - for (int i = 0; i < nKeys; ++i) { - int key = mInputQueryBinding(&iter.value(), KEYBOARD, i); + int nKeys = m_inputMap.info->nKeys; + /*for (int i = 0; i < nKeys; ++i) { + InputItem* item = m_inputModel->itemForKey(i); + if (item) { + int key = mInputQueryBinding(&m_inputMap, KEYBOARD, i); if (key >= 0) { - m_inputModel->updateKey(m_inputModel->index(i, 0, parent), key); + item->setShortcut(key); } else { - m_inputModel->clearKey(m_inputModel->index(i, 0, parent)); + item->clearShortcut(); } #ifdef BUILD_SDL - key = mInputQueryBinding(&iter.value(), SDL_BINDING_BUTTON, i); + key = mInputQueryBinding(&m_inputMap, SDL_BINDING_BUTTON, i); if (key >= 0) { - m_inputModel->updateButton(m_inputModel->index(i, 0, parent), key); + item->setButton(key); } else { - m_inputModel->clearButton(m_inputModel->index(i, 0, parent)); + item->clearButton(); } #endif } -#ifdef BUILD_SDL - struct Context { - InputModel* model; - QModelIndex parent; - } context{ m_inputModel, parent }; - mInputEnumerateAxes(&iter.value(), SDL_BINDING_BUTTON, [](int axis, const struct mInputAxis* description, void* user) { - Context* context = static_cast(user); - if (description->highDirection >= 0) { - context->model->updateAxis(context->model->index(description->highDirection, 0, context->parent), axis, GamepadAxisEvent::POSITIVE); - } - if (description->lowDirection >= 0) { - context->model->updateAxis(context->model->index(description->lowDirection, 0, context->parent), axis, GamepadAxisEvent::NEGATIVE); - } - }, &context); -#endif } +#ifdef BUILD_SDL + mInputEnumerateAxes(&m_inputMap, SDL_BINDING_BUTTON, [](int axis, const struct mInputAxis* description, void* user) { + InputModel* model = static_cast(user); + InputItem* item; + if (description->highDirection >= 0) { + item = model->itemForKey(description->highDirection); + if (item) { + item->setAxis(axis, GamepadAxisEvent::POSITIVE); + } + } + if (description->lowDirection >= 0) { + item = model->itemForKey(description->lowDirection); + if (item) { + item->setAxis(axis, GamepadAxisEvent::NEGATIVE); + } + } + }, m_inputModel); +#endif*/ m_inputModel->blockSignals(signalsBlocked); } diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index 916f3b3fe..421e1e6d8 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -33,6 +33,7 @@ namespace QGBA { class ConfigController; class GameController; +class InputItem; class InputModel; class InputController : public QObject { @@ -44,9 +45,6 @@ public: InputController(InputModel* model, int playerId = 0, QWidget* topLevel = nullptr, QObject* parent = nullptr); ~InputController(); - void addPlatform(mPlatform, const QString& visibleName, const mInputPlatformInfo*); - void setPlatform(mPlatform); - void setConfiguration(ConfigController* config); void saveConfiguration(); void loadConfiguration(uint32_t type); @@ -68,9 +66,9 @@ public: QSet> activeGamepadHats(int type); void recalibrateAxes(); - void bindKey(mPlatform platform, uint32_t type, int key, int); - void bindAxis(mPlatform platform, uint32_t type, int axis, GamepadAxisEvent::Direction, int); - void bindHat(mPlatform platform, uint32_t type, int hat, GamepadHatEvent::Direction, int); + 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); QStringList connectedGamepads(uint32_t type) const; int gamepad(uint32_t type) const; @@ -106,10 +104,10 @@ public slots: void setScreensaverSuspendable(bool); private slots: - void bindKey(const QModelIndex&, int key); - void bindButton(const QModelIndex&, int key); - void bindAxis(const QModelIndex&, int axis, GamepadAxisEvent::Direction); - void bindHat(const QModelIndex&, int hat, GamepadHatEvent::Direction); + void doBindKey(const QModelIndex&, int key); + void doBindButton(const QModelIndex&, int key); + void doBindAxis(const QModelIndex&, int axis, GamepadAxisEvent::Direction); + void doBindHat(const QModelIndex&, int hat, GamepadHatEvent::Direction); protected: bool eventFilter(QObject*, QEvent*) override; @@ -121,9 +119,8 @@ private: void sendGamepadEvent(QEvent*); void restoreModel(); - InputModel* m_inputModel; - mPlatform m_platform; - QMap m_inputMaps; + InputModel* m_inputModel = nullptr; + mInputMap m_inputMap; ConfigController* m_config = nullptr; int m_playerId; bool m_allowOpposing = false; @@ -139,9 +136,8 @@ private: QVector m_deadzones; - std::unique_ptr m_inputMenu; - std::unique_ptr m_autofireMenu; - QMap m_inputMenuIndices; + InputItem* m_inputMenu; + InputItem* m_autofireMenu; QSet m_activeButtons; QSet> m_activeAxes; diff --git a/src/platform/qt/InputItem.cpp b/src/platform/qt/InputItem.cpp index f68a66763..efcac346e 100644 --- a/src/platform/qt/InputItem.cpp +++ b/src/platform/qt/InputItem.cpp @@ -10,15 +10,10 @@ using namespace QGBA; InputItem::InputItem(QAction* action, const QString& name, InputItem* parent) - : m_action(action) + : QObject(parent) + , m_action(action) , m_shortcut(action->shortcut().isEmpty() ? 0 : action->shortcut()[0]) - , m_keys(-1) - , m_menu(nullptr) , m_name(name) - , m_button(-1) - , m_axis(-1) - , m_direction(GamepadAxisEvent::NEUTRAL) - , m_platform(PLATFORM_NONE) , m_parent(parent) { m_visibleName = action->text() @@ -26,69 +21,41 @@ InputItem::InputItem(QAction* action, const QString& name, InputItem* parent) .remove("..."); } -InputItem::InputItem(InputItem::Functions functions, int shortcut, const QString& visibleName, const QString& name, InputItem* parent) - : m_action(nullptr) - , m_shortcut(shortcut) - , m_functions(functions) - , m_keys(-1) - , m_menu(nullptr) - , m_name(name) - , m_visibleName(visibleName) - , m_button(-1) - , m_axis(-1) - , m_direction(GamepadAxisEvent::NEUTRAL) - , m_platform(PLATFORM_NONE) - , m_parent(parent) -{ -} - -InputItem::InputItem(mPlatform platform, int key, int shortcut, const QString& visibleName, const QString& name, InputItem* parent) - : m_action(nullptr) - , m_shortcut(shortcut) - , m_keys(key) - , m_menu(nullptr) - , m_name(name) - , m_visibleName(visibleName) - , m_button(-1) - , m_axis(-1) - , m_direction(GamepadAxisEvent::NEUTRAL) - , m_platform(platform) - , m_parent(parent) -{ -} - -InputItem::InputItem(QMenu* menu, InputItem* parent) - : m_action(nullptr) - , m_shortcut(0) +InputItem::InputItem(QMenu* menu, const QString& name, InputItem* parent) + : QObject(parent) , m_menu(menu) - , m_button(-1) - , m_axis(-1) - , m_direction(GamepadAxisEvent::NEUTRAL) + , m_name(name) , m_parent(parent) { - if (menu) { - m_visibleName = menu->title() - .remove(QRegExp("&(?!&)")) - .remove("..."); - } + m_visibleName = menu->title() + .remove(QRegExp("&(?!&)")) + .remove("..."); } -void InputItem::addAction(QAction* action, const QString& name) { - m_items.append(InputItem(action, name, this)); +InputItem::InputItem(InputItem::Functions functions, const QString& visibleName, const QString& name, InputItem* parent) + : QObject(parent) + , m_functions(functions) + , m_name(name) + , m_visibleName(visibleName) + , m_parent(parent) +{ } -void InputItem::addFunctions(InputItem::Functions functions, - int shortcut, const QString& visibleName, - const QString& name) { - m_items.append(InputItem(functions, shortcut, visibleName, name, this)); +InputItem::InputItem(int key, const QString& visibleName, const QString& name, InputItem* parent) + : QObject(parent) + , m_keys(key) + , m_name(name) + , m_visibleName(visibleName) + , m_parent(parent) +{ } -void InputItem::addKey(mPlatform platform, int key, int shortcut, const QString& visibleName, const QString& name) { - m_items.append(InputItem(platform, key, shortcut, visibleName, name, this)); -} - -void InputItem::addSubmenu(QMenu* menu) { - m_items.append(InputItem(menu, this)); +InputItem::InputItem(const QString& visibleName, const QString& name, InputItem* parent) + : QObject(parent) + , m_name(name) + , m_visibleName(visibleName) + , m_parent(parent) +{ } void InputItem::setShortcut(int shortcut) { @@ -96,9 +63,24 @@ void InputItem::setShortcut(int shortcut) { if (m_action) { m_action->setShortcut(QKeySequence(shortcut)); } + emit shortcutBound(this, shortcut); +} + +void InputItem::clearShortcut() { + setShortcut(0); +} + +void InputItem::setButton(int button) { + m_button = button; + emit buttonBound(this, button); +} + +void InputItem::clearButton() { + setButton(-1); } void InputItem::setAxis(int axis, GamepadAxisEvent::Direction direction) { m_axis = axis; m_direction = direction; + emit axisBound(this, axis, direction); } diff --git a/src/platform/qt/InputItem.h b/src/platform/qt/InputItem.h index d52de02a6..2cf6da9c3 100644 --- a/src/platform/qt/InputItem.h +++ b/src/platform/qt/InputItem.h @@ -13,63 +13,76 @@ #include -#include - namespace QGBA { -class InputItem { +class InputItem : public QObject { +Q_OBJECT + public: typedef QPair, std::function> Functions; InputItem(QAction* action, const QString& name, InputItem* parent = nullptr); - InputItem(Functions functions, int shortcut, const QString& visibleName, - const QString& name, InputItem* parent = nullptr); - InputItem(mPlatform platform, int key, int shortcut, const QString& name, const QString& visibleName, InputItem* parent = nullptr); - InputItem(QMenu* action, InputItem* parent = nullptr); + InputItem(QMenu* action, const QString& name, InputItem* parent = nullptr); + InputItem(Functions functions, const QString& visibleName, const QString& name, + InputItem* parent = nullptr); + InputItem(int key, const QString& name, const QString& visibleName, InputItem* parent = nullptr); + InputItem(const QString& visibleName, const QString& name, InputItem* parent = nullptr); QAction* action() { return m_action; } const QAction* action() const { return m_action; } - int shortcut() const { return m_shortcut; } - mPlatform platform() const { return m_platform; } + const QMenu* menu() const { return m_menu; } Functions functions() const { return m_functions; } int key() const { return m_keys; } - QMenu* menu() { return m_menu; } - const QMenu* menu() const { return m_menu; } + const QString& visibleName() const { return m_visibleName; } const QString& name() const { return m_name; } - QList& items() { return m_items; } - const QList& items() const { return m_items; } + + QList& items() { return m_items; } + const QList& items() const { return m_items; } InputItem* parent() { return m_parent; } const InputItem* parent() const { return m_parent; } - void addAction(QAction* action, const QString& name); - void addFunctions(Functions functions, int shortcut, const QString& visibleName, - const QString& name); - void addKey(mPlatform platform, int key, int shortcut, const QString& visibleName, const QString& name); - void addSubmenu(QMenu* menu); - int button() const { return m_button; } + template InputItem* addItem(Args... params) { + InputItem* item = new InputItem(params..., this); + m_items.append(item); + emit childAdded(this, item); + return item; + } + + int shortcut() const { return m_shortcut; } void setShortcut(int sequence); - void setButton(int button) { m_button = button; } + void clearShortcut(); + + int button() const { return m_button; } + void setButton(int button); + void clearButton(); + int axis() const { return m_axis; } GamepadAxisEvent::Direction direction() const { return m_direction; } void setAxis(int axis, GamepadAxisEvent::Direction direction); bool operator==(const InputItem& other) const { - return m_menu == other.m_menu && m_action == other.m_action; + return m_name == other.m_name && m_visibleName == other.m_visibleName; } +signals: + void shortcutBound(InputItem*, int shortcut); + void buttonBound(InputItem*, int button); + void axisBound(InputItem*, int axis, GamepadAxisEvent::Direction); + void childAdded(InputItem* parent, InputItem* child); + private: - QAction* m_action; - int m_shortcut; - QMenu* m_menu; + QAction* m_action = nullptr; + QMenu* m_menu = nullptr; Functions m_functions; QString m_name; QString m_visibleName; - int m_button; - int m_axis; - int m_keys; - GamepadAxisEvent::Direction m_direction; - mPlatform m_platform; - QList m_items; + + int m_shortcut = 0; + int m_button = -1; + int m_axis = -1; + int m_keys =-1; + GamepadAxisEvent::Direction m_direction = GamepadAxisEvent::NEUTRAL; + QList m_items; InputItem* m_parent; }; diff --git a/src/platform/qt/InputModel.cpp b/src/platform/qt/InputModel.cpp index 18bbb9f8d..e47179e3f 100644 --- a/src/platform/qt/InputModel.cpp +++ b/src/platform/qt/InputModel.cpp @@ -17,8 +17,9 @@ using namespace QGBA; InputModel::InputModel(QObject* parent) : QAbstractItemModel(parent) - , m_rootMenu(nullptr) + , m_rootMenu(QString(), QString()) { + connect(&m_rootMenu, &InputItem::childAdded, this, &InputModel::itemAdded); } void InputModel::setConfigController(ConfigController* controller) { @@ -77,7 +78,7 @@ QModelIndex InputModel::index(int row, int column, const QModelIndex& parent) co if (parent.isValid()) { pmenu = static_cast(parent.internalPointer()); } - return createIndex(row, column, const_cast(&pmenu->items()[row])); + return createIndex(row, column, const_cast(pmenu->items()[row])); } QModelIndex InputModel::parent(const QModelIndex& index) const { @@ -88,11 +89,11 @@ QModelIndex InputModel::parent(const QModelIndex& index) const { return this->index(item->parent()); } -QModelIndex InputModel::index(InputItem* item) const { +QModelIndex InputModel::index(InputItem* item, int row) const { if (!item || !item->parent()) { return QModelIndex(); } - return createIndex(item->parent()->items().indexOf(*item), 0, item); + return createIndex(item->parent()->items().indexOf(item), row, item); } int InputModel::columnCount(const QModelIndex& index) const { @@ -107,88 +108,6 @@ int InputModel::rowCount(const QModelIndex& index) const { return item->items().count(); } -InputItem* InputModel::add(QMenu* menu, std::function callback) { - InputItem* smenu = m_menuMap[menu]; - if (!smenu) { - return nullptr; - } - QModelIndex parent = index(smenu); - beginInsertRows(parent, smenu->items().count(), smenu->items().count()); - callback(smenu); - endInsertRows(); - InputItem* item = &smenu->items().last(); - emit dataChanged(createIndex(smenu->items().count() - 1, 0, item), - createIndex(smenu->items().count() - 1, 2, item)); - return item; -} - -void InputModel::addAction(QMenu* menu, QAction* action, const QString& name) { - InputItem* item = add(menu, [&](InputItem* smenu) { - smenu->addAction(action, name); - }); - if (!item) { - return; - } - if (m_config) { - loadShortcuts(item); - } -} - -void InputModel::addFunctions(QMenu* menu, std::function press, std::function release, - int shortcut, const QString& visibleName, const QString& name) { - InputItem* item = add(menu, [&](InputItem* smenu) { - smenu->addFunctions(qMakePair(press, release), shortcut, visibleName, name); - }); - if (!item) { - return; - } - - bool loadedShortcut = false; - if (m_config) { - loadedShortcut = loadShortcuts(item); - } - if (!loadedShortcut && !m_heldKeys.contains(shortcut)) { - m_heldKeys[shortcut] = item; - } -} - -void InputModel::addFunctions(QMenu* menu, std::function press, std::function release, - const QKeySequence& shortcut, const QString& visibleName, const QString& name) { - addFunctions(menu, press, release, shortcut[0], visibleName, name); -} - -void InputModel::addKey(QMenu* menu, mPlatform platform, int key, int shortcut, const QString& visibleName, const QString& name) { - InputItem* item = add(menu, [&](InputItem* smenu) { - smenu->addKey(platform, key, shortcut, visibleName, name); - }); - if (!item) { - return; - } - bool loadedShortcut = false; - if (m_config) { - loadedShortcut = loadShortcuts(item); - } - if (!loadedShortcut && !m_keys.contains(qMakePair(platform, shortcut))) { - m_keys[qMakePair(platform, shortcut)] = item; - } -} - -QModelIndex InputModel::addMenu(QMenu* menu, QMenu* parentMenu) { - InputItem* smenu = m_menuMap[parentMenu]; - if (!smenu) { - smenu = &m_rootMenu; - } - QModelIndex parent = index(smenu); - beginInsertRows(parent, smenu->items().count(), smenu->items().count()); - smenu->addSubmenu(menu); - endInsertRows(); - InputItem* item = &smenu->items().last(); - emit dataChanged(createIndex(smenu->items().count() - 1, 0, item), - createIndex(smenu->items().count() - 1, 2, item)); - m_menuMap[menu] = item; - return index(item); -} - InputItem* InputModel::itemAt(const QModelIndex& index) { if (!index.isValid()) { return nullptr; @@ -200,7 +119,7 @@ InputItem* InputModel::itemAt(const QModelIndex& index) { return nullptr; } InputItem* pmenu = static_cast(index.parent().internalPointer()); - return &pmenu->items()[index.row()]; + return pmenu->items()[index.row()]; } const InputItem* InputModel::itemAt(const QModelIndex& index) const { @@ -214,220 +133,22 @@ const InputItem* InputModel::itemAt(const QModelIndex& index) const { return nullptr; } InputItem* pmenu = static_cast(index.parent().internalPointer()); - return &pmenu->items()[index.row()]; + return pmenu->items()[index.row()]; } -int InputModel::shortcutAt(const QModelIndex& index) const { - const InputItem* item = itemAt(index); +InputItem* InputModel::itemForMenu(const QMenu* menu) { + InputItem* item = m_menus[menu]; if (!item) { - return 0; + return &m_rootMenu; } - return item->shortcut(); + return item; } - -int InputModel::keyAt(const QModelIndex& index) const { - const InputItem* item = itemAt(index); +const InputItem* InputModel::itemForMenu(const QMenu* menu) const { + const InputItem* item = m_menus[menu]; if (!item) { - return -1; + return &m_rootMenu; } - return item->key(); -} - -bool InputModel::isMenuAt(const QModelIndex& index) const { - const InputItem* item = itemAt(index); - if (!item) { - return false; - } - return item->menu(); -} - -void InputModel::updateKey(const QModelIndex& index, int keySequence) { - if (!index.isValid()) { - return; - } - const QModelIndex& parent = index.parent(); - if (!parent.isValid()) { - return; - } - InputItem* item = itemAt(index); - updateKey(item, keySequence); - if (m_config) { - m_config->setQtOption(item->name(), QKeySequence(keySequence).toString(), KEY_SECTION); - } -} - -void InputModel::updateKey(InputItem* item, int keySequence) { - int oldShortcut = item->shortcut(); - if (item->functions().first) { - if (oldShortcut > 0) { - m_heldKeys.take(oldShortcut); - } - if (keySequence > 0) { - m_heldKeys[keySequence] = item; - } - } - - if (item->key() >= 0) { - if (oldShortcut > 0) { - m_keys.take(qMakePair(item->platform(), oldShortcut)); - } - if (keySequence > 0) { - m_keys[qMakePair(item->platform(), keySequence)] = item; - } - } - - item->setShortcut(keySequence); - - emit dataChanged(createIndex(index(item).row(), 0, item), - createIndex(index(item).row(), 2, item)); - - emit keyRebound(index(item), keySequence); -} - -void InputModel::updateButton(const QModelIndex& index, int button) { - if (!index.isValid()) { - return; - } - const QModelIndex& parent = index.parent(); - if (!parent.isValid()) { - return; - } - InputItem* item = itemAt(index); - int oldButton = item->button(); - if (oldButton >= 0) { - m_buttons.take(oldButton); - } - updateAxis(index, -1, GamepadAxisEvent::NEUTRAL); - item->setButton(button); - if (button >= 0) { - m_buttons[button] = item; - } - if (m_config) { - m_config->setQtOption(item->name(), button, BUTTON_SECTION); - if (!m_profileName.isNull()) { - m_config->setQtOption(item->name(), button, BUTTON_PROFILE_SECTION + m_profileName); - } - } - emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), - createIndex(index.row(), 2, index.internalPointer())); - - emit buttonRebound(index, button); -} - -void InputModel::updateAxis(const QModelIndex& index, int axis, GamepadAxisEvent::Direction direction) { - if (!index.isValid()) { - return; - } - const QModelIndex& parent = index.parent(); - if (!parent.isValid()) { - return; - } - InputItem* item = itemAt(index); - int oldAxis = item->axis(); - GamepadAxisEvent::Direction oldDirection = item->direction(); - if (oldAxis >= 0) { - m_axes.take(qMakePair(oldAxis, oldDirection)); - } - if (axis >= 0 && direction != GamepadAxisEvent::NEUTRAL) { - updateButton(index, -1); - m_axes[qMakePair(axis, direction)] = item; - } - item->setAxis(axis, direction); - if (m_config) { - char d = '\0'; - if (direction == GamepadAxisEvent::POSITIVE) { - d = '+'; - } - if (direction == GamepadAxisEvent::NEGATIVE) { - d = '-'; - } - m_config->setQtOption(item->name(), QString("%1%2").arg(d).arg(axis), AXIS_SECTION); - if (!m_profileName.isNull()) { - m_config->setQtOption(item->name(), QString("%1%2").arg(d).arg(axis), AXIS_PROFILE_SECTION + m_profileName); - } - } - emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), - createIndex(index.row(), 2, index.internalPointer())); - - emit axisRebound(index, axis, direction); -} - -void InputModel::clearKey(const QModelIndex& index) { - updateKey(index, 0); -} - -void InputModel::clearButton(const QModelIndex& index) { - updateButton(index, -1); -} - -bool InputModel::triggerKey(int keySequence, bool down, mPlatform platform) { - auto key = m_keys.find(qMakePair(platform, keySequence)); - if (key != m_keys.end()) { - m_keyCallback(key.value()->parent()->menu(), key.value()->key(), down); - return true; - } - auto heldKey = m_heldKeys.find(keySequence); - if (heldKey != m_heldKeys.end()) { - auto pair = heldKey.value()->functions(); - if (down) { - if (pair.first) { - pair.first(); - } - } else { - if (pair.second) { - pair.second(); - } - } - return true; - } - return false; -} - -bool InputModel::triggerButton(int button, bool down) { - auto item = m_buttons.find(button); - if (item == m_buttons.end()) { - return false; - } - if (down) { - QAction* action = item.value()->action(); - if (action && action->isEnabled()) { - action->trigger(); - } - auto pair = item.value()->functions(); - if (pair.first) { - pair.first(); - } - } else { - auto pair = item.value()->functions(); - if (pair.second) { - pair.second(); - } - } - return true; -} - -bool InputModel::triggerAxis(int axis, GamepadAxisEvent::Direction direction, bool isNew) { - auto item = m_axes.find(qMakePair(axis, direction)); - if (item == m_axes.end()) { - return false; - } - if (isNew) { - QAction* action = item.value()->action(); - if (action && action->isEnabled()) { - action->trigger(); - } - } - auto pair = item.value()->functions(); - if (isNew) { - if (pair.first) { - pair.first(); - } - } else { - if (pair.second) { - pair.second(); - } - } - return true; + return item; } bool InputModel::loadShortcuts(InputItem* item) { @@ -438,9 +159,9 @@ bool InputModel::loadShortcuts(InputItem* item) { QVariant shortcut = m_config->getQtOption(item->name(), KEY_SECTION); if (!shortcut.isNull()) { if (shortcut.toString().endsWith("+")) { - updateKey(item, toModifierShortcut(shortcut.toString())); + item->setShortcut(toModifierShortcut(shortcut.toString())); } else { - updateKey(item, QKeySequence(shortcut.toString())[0]); + item->setShortcut(QKeySequence(shortcut.toString())[0]); } return true; } @@ -452,11 +173,6 @@ void InputModel::loadGamepadShortcuts(InputItem* item) { return; } QVariant button = m_config->getQtOption(item->name(), !m_profileName.isNull() ? BUTTON_PROFILE_SECTION + m_profileName : BUTTON_SECTION); - int oldButton = item->button(); - if (oldButton >= 0) { - m_buttons.take(oldButton); - item->setButton(-1); - } if (button.isNull() && m_profile) { int buttonInt; if (m_profile->lookupShortcutButton(item->name(), &buttonInt)) { @@ -465,14 +181,11 @@ void InputModel::loadGamepadShortcuts(InputItem* item) { } if (!button.isNull()) { item->setButton(button.toInt()); - m_buttons[button.toInt()] = item; } QVariant axis = m_config->getQtOption(item->name(), !m_profileName.isNull() ? AXIS_PROFILE_SECTION + m_profileName : AXIS_SECTION); int oldAxis = item->axis(); - GamepadAxisEvent::Direction oldDirection = item->direction(); if (oldAxis >= 0) { - m_axes.take(qMakePair(oldAxis, oldDirection)); item->setAxis(-1, GamepadAxisEvent::NEUTRAL); } if (axis.isNull() && m_profile) { @@ -496,24 +209,23 @@ void InputModel::loadGamepadShortcuts(InputItem* item) { int axis = axisDesc.mid(1).toInt(&ok); if (ok) { item->setAxis(axis, direction); - m_axes[qMakePair(axis, direction)] = item; } } } } -void InputModel::loadProfile(mPlatform platform, const QString& profile) { +void InputModel::loadProfile(const QString& profile) { m_profileName = profile; - m_profile = InputProfile::findProfile(platform, profile); + m_profile = InputProfile::findProfile(profile); onSubitems(&m_rootMenu, [this](InputItem* item) { loadGamepadShortcuts(item); }); } void InputModel::onSubitems(InputItem* item, std::function func) { - for (InputItem& subitem : item->items()) { - func(&subitem); - onSubitems(&subitem, func); + for (InputItem* subitem : item->items()) { + func(subitem); + onSubitems(subitem, func); } } @@ -575,3 +287,12 @@ int InputModel::toModifierKey(int key) { } return modifiers; } + +void InputModel::itemAdded(InputItem* parent, InputItem* child) { + const QMenu* menu = child->menu(); + if (menu) { + m_menus[menu] = child; + } + m_names[child->name()] = child; + connect(child, &InputItem::childAdded, this, &InputModel::itemAdded); +} diff --git a/src/platform/qt/InputModel.h b/src/platform/qt/InputModel.h index 2d1044d2c..e1c354a73 100644 --- a/src/platform/qt/InputModel.h +++ b/src/platform/qt/InputModel.h @@ -35,12 +35,14 @@ private: constexpr static const char* const BUTTON_PROFILE_SECTION = "shortcutProfileButton."; constexpr static const char* const AXIS_PROFILE_SECTION = "shortcutProfileAxis."; +private slots: + void itemAdded(InputItem* parent, InputItem* child); + public: InputModel(QObject* parent = nullptr); void setConfigController(ConfigController* controller); void setProfile(const QString& profile); - void setKeyCallback(std::function callback) { m_keyCallback = callback; } virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; @@ -51,63 +53,38 @@ public: virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - void addAction(QMenu* menu, QAction* action, const QString& name); - void addFunctions(QMenu* menu, std::function press, std::function release, - int shortcut, const QString& visibleName, const QString& name); - void addFunctions(QMenu* menu, std::function press, std::function release, - const QKeySequence& shortcut, const QString& visibleName, const QString& name); - void addKey(QMenu* menu, mPlatform platform, int key, int shortcut, const QString& visibleName, const QString& name); - QModelIndex addMenu(QMenu* menu, QMenu* parent = nullptr); + template InputItem* addItem(Args... params) { return m_rootMenu.addItem(params...); } - QAction* getAction(const QString& name); - int shortcutAt(const QModelIndex& index) const; - int keyAt(const QModelIndex& index) const; - bool isMenuAt(const QModelIndex& index) const; + InputItem* itemAt(const QString& name); + const InputItem* itemAt(const QString& name) const; + InputItem* itemAt(const QModelIndex& index); + const InputItem* itemAt(const QModelIndex& index) const; - void updateKey(const QModelIndex& index, int keySequence); - void updateButton(const QModelIndex& index, int button); - void updateAxis(const QModelIndex& index, int axis, GamepadAxisEvent::Direction); - void updateHat(const QModelIndex& index, int hat, GamepadHatEvent::Direction); + InputItem* itemForKey(int key); + const InputItem* itemForKey(int key) const; - void clearKey(const QModelIndex& index); - void clearButton(const QModelIndex& index); + InputItem* itemForMenu(const QMenu* menu); + const InputItem* itemForMenu(const QMenu* menu) const; static int toModifierShortcut(const QString& shortcut); static bool isModifierKey(int key); static int toModifierKey(int key); - void loadProfile(mPlatform platform, const QString& profile); + void loadProfile(const QString& profile); - bool triggerKey(int keySequence, bool down, mPlatform platform = PLATFORM_NONE); - bool triggerButton(int button, bool down); - bool triggerAxis(int axis, GamepadAxisEvent::Direction, bool isNew); - bool triggerHat(int hat, GamepadHatEvent::Direction); - -signals: - void keyRebound(const QModelIndex&, int keySequence); - void buttonRebound(const QModelIndex&, int button); - void axisRebound(const QModelIndex& index, int axis, GamepadAxisEvent::Direction); - void hatRebound(const QModelIndex& index, int hat, GamepadHatEvent::Direction); + InputItem* root() { return &m_rootMenu; } private: - InputItem* add(QMenu* menu, std::function); - InputItem* itemAt(const QModelIndex& index); - const InputItem* itemAt(const QModelIndex& index) const; bool loadShortcuts(InputItem*); void loadGamepadShortcuts(InputItem*); void onSubitems(InputItem*, std::function func); - void updateKey(InputItem* item, int keySequence); - QModelIndex index(InputItem* item) const; + QModelIndex index(InputItem* item, int column = 0) const; InputItem m_rootMenu; - QMap m_menuMap; - QMap m_buttons; - QMap, InputItem*> m_axes; - QMap m_heldKeys; - QMap, InputItem*> m_keys; + QMap m_names; + QMap m_menus; ConfigController* m_config; - std::function m_keyCallback; QString m_profileName; const InputProfile* m_profile; }; diff --git a/src/platform/qt/InputProfile.cpp b/src/platform/qt/InputProfile.cpp index 92e1c0cc9..aedc47f6e 100644 --- a/src/platform/qt/InputProfile.cpp +++ b/src/platform/qt/InputProfile.cpp @@ -199,8 +199,7 @@ constexpr InputProfile::InputProfile(const char* name, { } -const InputProfile* InputProfile::findProfile(mPlatform platform, const QString& name) { - // TODO: Use platform +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)) { @@ -210,11 +209,11 @@ const InputProfile* InputProfile::findProfile(mPlatform platform, const QString& return nullptr; } -void InputProfile::apply(mPlatform platform, InputController* controller) const { +void InputProfile::apply(InputController* controller) const { for (size_t i = 0; i < GBA_KEY_MAX; ++i) { #ifdef BUILD_SDL - controller->bindKey(platform, SDL_BINDING_BUTTON, m_keys[i], static_cast(i)); - controller->bindAxis(platform, SDL_BINDING_BUTTON, m_axes[i].axis, m_axes[i].direction, static_cast(i)); + controller->bindKey(SDL_BINDING_BUTTON, m_keys[i], static_cast(i)); + controller->bindAxis(SDL_BINDING_BUTTON, m_axes[i].axis, m_axes[i].direction, static_cast(i)); #endif } controller->registerTiltAxisX(m_tiltAxis.x); diff --git a/src/platform/qt/InputProfile.h b/src/platform/qt/InputProfile.h index 37e608cd6..748987d20 100644 --- a/src/platform/qt/InputProfile.h +++ b/src/platform/qt/InputProfile.h @@ -17,9 +17,9 @@ class InputController; class InputProfile { public: - static const InputProfile* findProfile(mPlatform platform, const QString& name); + static const InputProfile* findProfile(const QString& name); - void apply(mPlatform platform, InputController*) const; + void apply(InputController*) const; bool lookupShortcutButton(const QString& shortcut, int* button) const; bool lookupShortcutAxis(const QString& shortcut, int* axis, GamepadAxisEvent::Direction* direction) const; diff --git a/src/platform/qt/ShortcutView.cpp b/src/platform/qt/ShortcutView.cpp index 71376a2c8..4436f3928 100644 --- a/src/platform/qt/ShortcutView.cpp +++ b/src/platform/qt/ShortcutView.cpp @@ -56,10 +56,8 @@ void ShortcutView::load(const QModelIndex& index) { if (!m_controller) { return; } - if (m_controller->isMenuAt(index)) { - return; - } - int shortcut = m_controller->shortcutAt(index); + InputItem* item = m_controller->itemAt(index); + int shortcut = item->shortcut(); if (index.column() == 1) { m_ui.keyboardButton->click(); } else if (index.column() == 2) { @@ -80,35 +78,34 @@ void ShortcutView::clear() { return; } QModelIndex index = m_ui.shortcutTable->selectionModel()->currentIndex(); - if (m_controller->isMenuAt(index)) { - return; - } + InputItem* item = m_controller->itemAt(index); if (m_ui.gamepadButton->isChecked()) { - m_controller->clearButton(index); + item->clearButton(); m_ui.keyEdit->setValueButton(-1); } else { - m_controller->clearKey(index); + item->clearShortcut(); m_ui.keyEdit->setValueKey(-1); } } void ShortcutView::updateButton(int button) { - if (!m_controller || m_controller->isMenuAt(m_ui.shortcutTable->selectionModel()->currentIndex())) { + if (!m_controller) { return; } + InputItem* item = m_controller->itemAt(m_ui.shortcutTable->selectionModel()->currentIndex()); if (m_ui.gamepadButton->isChecked()) { - m_controller->updateButton(m_ui.shortcutTable->selectionModel()->currentIndex(), button); + item->setButton(button); } else { - m_controller->updateKey(m_ui.shortcutTable->selectionModel()->currentIndex(), button); + item->setShortcut(button); } } void ShortcutView::updateAxis(int axis, int direction) { - if (!m_controller || m_controller->isMenuAt(m_ui.shortcutTable->selectionModel()->currentIndex())) { + if (!m_controller) { return; } - m_controller->updateAxis(m_ui.shortcutTable->selectionModel()->currentIndex(), axis, - static_cast(direction)); + InputItem* item = m_controller->itemAt(m_ui.shortcutTable->selectionModel()->currentIndex()); + item->setAxis(axis, static_cast(direction)); } void ShortcutView::closeEvent(QCloseEvent*) { diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 74904cc3b..172ba46d5 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -194,12 +194,6 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) m_inputModel->setConfigController(m_config); setupMenu(menuBar()); -#ifdef M_CORE_GBA - m_inputController.addPlatform(PLATFORM_GBA, tr("Game Boy Advance"), &GBAInputInfo); -#endif -#ifdef M_CORE_GB - m_inputController.addPlatform(PLATFORM_GB, tr("Game Boy"), &GBInputInfo); -#endif m_inputController.setupCallback(m_controller); } @@ -724,8 +718,6 @@ void Window::gameStarted(mCoreThread* context, const QString& fname) { } #endif - m_inputController.setPlatform(m_controller->platform()); - m_hitUnimplementedBiosCall = false; m_fpsTimer.start(); m_focusCheck.start(); @@ -930,7 +922,7 @@ void Window::openStateWindow(LoadSave ls) { void Window::setupMenu(QMenuBar* menubar) { menubar->clear(); QMenu* fileMenu = menubar->addMenu(tr("&File")); - m_inputModel->addMenu(fileMenu); + m_inputModel->addItem(fileMenu, "file"); installEventFilter(&m_inputController); addControlledAction(fileMenu, fileMenu->addAction(tr("Load &ROM..."), this, SLOT(selectROM()), QKeySequence::Open), "loadROM"); @@ -986,8 +978,8 @@ void Window::setupMenu(QMenuBar* menubar) { QMenu* quickLoadMenu = fileMenu->addMenu(tr("Quick load")); QMenu* quickSaveMenu = fileMenu->addMenu(tr("Quick save")); - m_inputModel->addMenu(quickLoadMenu); - m_inputModel->addMenu(quickSaveMenu); + m_inputModel->addItem(quickLoadMenu, "quickLoadMenu"); + m_inputModel->addItem(quickSaveMenu, "quickSaveMenu"); QAction* quickLoad = new QAction(tr("Load recent"), quickLoadMenu); connect(quickLoad, &QAction::triggered, m_controller, &GameController::loadState); @@ -1073,7 +1065,7 @@ void Window::setupMenu(QMenuBar* menubar) { #endif QMenu* emulationMenu = menubar->addMenu(tr("&Emulation")); - m_inputModel->addMenu(emulationMenu); + InputItem* emulationMenuItem = m_inputModel->addItem(emulationMenu, "emulation"); QAction* reset = new QAction(tr("&Reset"), emulationMenu); reset->setShortcut(tr("Ctrl+R")); connect(reset, &QAction::triggered, m_controller, &GameController::reset); @@ -1114,11 +1106,11 @@ void Window::setupMenu(QMenuBar* menubar) { emulationMenu->addSeparator(); - m_inputModel->addFunctions(emulationMenu, [this]() { + emulationMenuItem->addItem(qMakePair([this]() { m_controller->setTurbo(true, false); }, [this]() { m_controller->setTurbo(false, false); - }, QKeySequence(Qt::Key_Tab), tr("Fast forward (held)"), "holdFastForward"); + }), tr("Fast forward (held)"), "holdFastForward")->setShortcut(QKeySequence(Qt::Key_Tab)[0]); QAction* turbo = new QAction(tr("&Fast forward"), emulationMenu); turbo->setCheckable(true); @@ -1140,11 +1132,11 @@ void Window::setupMenu(QMenuBar* menubar) { } m_config->updateOption("fastForwardRatio"); - m_inputModel->addFunctions(emulationMenu, [this]() { + emulationMenuItem->addItem(qMakePair([this]() { m_controller->startRewinding(); }, [this]() { m_controller->stopRewinding(); - }, QKeySequence("`"), tr("Rewind (held)"), "holdRewind"); + }), tr("Rewind (held)"), "holdRewind")->setShortcut(QKeySequence("`")[0]); QAction* rewind = new QAction(tr("Re&wind"), emulationMenu); rewind->setShortcut(tr("~")); @@ -1179,7 +1171,7 @@ void Window::setupMenu(QMenuBar* menubar) { emulationMenu->addSeparator(); QMenu* solarMenu = emulationMenu->addMenu(tr("Solar sensor")); - m_inputModel->addMenu(solarMenu); + m_inputModel->addItem(solarMenu, "luminance"); QAction* solarIncrease = new QAction(tr("Increase solar level"), solarMenu); connect(solarIncrease, &QAction::triggered, m_controller, &GameController::increaseLuminanceLevel); addControlledAction(solarMenu, solarIncrease, "increaseLuminanceLevel"); @@ -1206,9 +1198,9 @@ void Window::setupMenu(QMenuBar* menubar) { } QMenu* avMenu = menubar->addMenu(tr("Audio/&Video")); - m_inputModel->addMenu(avMenu); + InputItem* avMenuItem = m_inputModel->addItem(avMenu, "av"); QMenu* frameMenu = avMenu->addMenu(tr("Frame size")); - m_inputModel->addMenu(frameMenu, avMenu); + avMenuItem->addItem(frameMenu, "frameSize"); for (int i = 1; i <= 6; ++i) { QAction* setSize = new QAction(tr("%1x").arg(QString::number(i)), avMenu); setSize->setCheckable(true); @@ -1343,13 +1335,13 @@ void Window::setupMenu(QMenuBar* menubar) { avMenu->addSeparator(); m_videoLayers = avMenu->addMenu(tr("Video layers")); - m_inputModel->addMenu(m_videoLayers, avMenu); + avMenuItem->addItem(m_videoLayers, "videoLayers"); m_audioChannels = avMenu->addMenu(tr("Audio channels")); - m_inputModel->addMenu(m_audioChannels, avMenu); + avMenuItem->addItem(m_audioChannels, "audioChannels"); QMenu* toolsMenu = menubar->addMenu(tr("&Tools")); - m_inputModel->addMenu(toolsMenu); + m_inputModel->addItem(toolsMenu, "tools"); QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu); connect(viewLogs, &QAction::triggered, m_logView, &QWidget::show); addControlledAction(toolsMenu, viewLogs, "viewLogs"); @@ -1489,67 +1481,67 @@ void Window::setupMenu(QMenuBar* menubar) { addHiddenAction(frameMenu, exitFullScreen, "exitFullScreen"); QMenu* autofireMenu = new QMenu(tr("Autofire"), this); - m_inputModel->addMenu(autofireMenu); + InputItem* autofireMenuItem = m_inputModel->addItem(autofireMenu, "autofire"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_A, true); }, [this]() { m_controller->setAutofire(GBA_KEY_A, false); - }, QKeySequence(), tr("Autofire A"), "autofireA"); + }), tr("Autofire A"), "autofireA"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_B, true); }, [this]() { m_controller->setAutofire(GBA_KEY_B, false); - }, QKeySequence(), tr("Autofire B"), "autofireB"); + }), tr("Autofire B"), "autofireB"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_L, true); }, [this]() { m_controller->setAutofire(GBA_KEY_L, false); - }, QKeySequence(), tr("Autofire L"), "autofireL"); + }), tr("Autofire L"), "autofireL"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_R, true); }, [this]() { m_controller->setAutofire(GBA_KEY_R, false); - }, QKeySequence(), tr("Autofire R"), "autofireR"); + }), tr("Autofire R"), "autofireR"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_START, true); }, [this]() { m_controller->setAutofire(GBA_KEY_START, false); - }, QKeySequence(), tr("Autofire Start"), "autofireStart"); + }), tr("Autofire Start"), "autofireStart"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_SELECT, true); }, [this]() { m_controller->setAutofire(GBA_KEY_SELECT, false); - }, QKeySequence(), tr("Autofire Select"), "autofireSelect"); + }), tr("Autofire Select"), "autofireSelect"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_UP, true); }, [this]() { m_controller->setAutofire(GBA_KEY_UP, false); - }, QKeySequence(), tr("Autofire Up"), "autofireUp"); + }), tr("Autofire Up"), "autofireUp"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_RIGHT, true); }, [this]() { m_controller->setAutofire(GBA_KEY_RIGHT, false); - }, QKeySequence(), tr("Autofire Right"), "autofireRight"); + }), tr("Autofire Right"), "autofireRight"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_DOWN, true); }, [this]() { m_controller->setAutofire(GBA_KEY_DOWN, false); - }, QKeySequence(), tr("Autofire Down"), "autofireDown"); + }), tr("Autofire Down"), "autofireDown"); - m_inputModel->addFunctions(autofireMenu, [this]() { + autofireMenuItem->addItem(qMakePair([this]() { m_controller->setAutofire(GBA_KEY_LEFT, true); }, [this]() { m_controller->setAutofire(GBA_KEY_LEFT, false); - }, QKeySequence(), tr("Autofire Left"), "autofireLeft"); + }), tr("Autofire Left"), "autofireLeft"); for (QAction* action : m_gameActions) { action->setDisabled(true); @@ -1606,7 +1598,8 @@ QAction* Window::addControlledAction(QMenu* menu, QAction* action, const QString } QAction* Window::addHiddenAction(QMenu* menu, QAction* action, const QString& name) { - m_inputModel->addAction(menu, action, name); + InputItem* item = m_inputModel->itemForMenu(menu); + item->addItem(action, name); action->setShortcutContext(Qt::WidgetShortcut); addAction(action); return action;