diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index d086057e1..fd03b2617 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -54,9 +54,6 @@ InputController::InputController(InputModel* model, int playerId, QWidget* topLe m_gamepadTimer.setInterval(50); m_gamepadTimer.start(); - m_autofireMenu = m_inputModel->root()->addItem(tr("Autofire"), "autofire"); - m_inputMenu = m_inputModel->root()->addItem(tr("Bindings"), "bindings"); - mInputMapInit(&m_inputMap, &GBAInputInfo); #ifdef BUILD_SDL @@ -632,20 +629,6 @@ void InputController::releaseFocus(QWidget* focus) { } } -void InputController::setupCallback(GameController* controller) { - [this, controller](InputItem* item, int key, bool down) { - if (item->parent() == m_autofireMenu) { - controller->setAutofire(key, down); - } else { - if (down) { - controller->keyPressed(key); - } else { - controller->keyReleased(key); - } - } - }; -} - void InputController::doBindKey(const QModelIndex& index, int key) { int coreKey = m_inputModel->itemAt(index)->key(); if (coreKey < 0) { @@ -699,26 +682,48 @@ bool InputController::eventFilter(QObject*, QEvent* event) { return true; } - // TODO + InputItem* item = m_inputModel->itemForShortcut(key); + if (item) { + item->trigger(event->type() == QEvent::KeyPress); + event->accept(); + return true; + } } if (event->type() == GamepadButtonEvent::Down() || event->type() == GamepadButtonEvent::Up()) { GamepadButtonEvent* gbe = static_cast(event); - // TODO + InputItem* item = m_inputModel->itemForButton(gbe->value()); + if (item) { + item->trigger(event->type() == GamepadButtonEvent::Down()); + event->accept(); + return true; + } } if (event->type() == GamepadAxisEvent::Type()) { GamepadAxisEvent* gae = static_cast(event); - // TODO + InputItem* item = m_inputModel->itemForAxis(gae->axis(), gae->direction()); + if (item) { + item->trigger(event->type() == gae->isNew()); + event->accept(); + return true; + } } return false; } +InputItem* InputController::itemForKey(int key) { + if (key < 0 || key >= m_inputMap.info->nKeys) { + return nullptr; + } + return m_inputModel->itemAt(QString("key%0").arg(m_inputMap.info->keyId[key])); +} + void InputController::restoreModel() { bool signalsBlocked = m_inputModel->blockSignals(true); int nKeys = m_inputMap.info->nKeys; - /*for (int i = 0; i < nKeys; ++i) { - InputItem* item = m_inputModel->itemForKey(i); + for (int i = 0; i < nKeys; ++i) { + InputItem* item = itemForKey(i); if (item) { int key = mInputQueryBinding(&m_inputMap, KEYBOARD, i); if (key >= 0) { @@ -737,22 +742,31 @@ void InputController::restoreModel() { } } #ifdef BUILD_SDL + struct Context { + InputModel* model; + InputController* controller; + } context { + m_inputModel, + this + }; mInputEnumerateAxes(&m_inputMap, SDL_BINDING_BUTTON, [](int axis, const struct mInputAxis* description, void* user) { - InputModel* model = static_cast(user); + Context* context = static_cast(user); + InputModel* model = context->model; + InputController* controller = context->controller; InputItem* item; - if (description->highDirection >= 0) { - item = model->itemForKey(description->highDirection); + if (description->highDirection >= 0 && description->highDirection < controller->m_inputMap.info->nKeys) { + item = controller->itemForKey(description->highDirection); if (item) { item->setAxis(axis, GamepadAxisEvent::POSITIVE); } } - if (description->lowDirection >= 0) { - item = model->itemForKey(description->lowDirection); + if (description->lowDirection >= 0 && description->lowDirection < controller->m_inputMap.info->nKeys) { + item = controller->itemForKey(description->lowDirection); if (item) { item->setAxis(axis, GamepadAxisEvent::NEGATIVE); } } - }, m_inputModel); -#endif*/ + }, &context); +#endif m_inputModel->blockSignals(signalsBlocked); } diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index 421e1e6d8..aac60386d 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -89,8 +89,6 @@ public: mRumble* rumble(); mRotationSource* rotationSource(); - void setupCallback(GameController* controller); - signals: void profileLoaded(const QString& profile); @@ -119,6 +117,8 @@ private: void sendGamepadEvent(QEvent*); void restoreModel(); + InputItem* itemForKey(int key); + InputModel* m_inputModel = nullptr; mInputMap m_inputMap; ConfigController* m_config = nullptr; @@ -136,9 +136,6 @@ private: QVector m_deadzones; - InputItem* m_inputMenu; - InputItem* m_autofireMenu; - QSet m_activeButtons; QSet> m_activeAxes; QSet> m_activeHats; diff --git a/src/platform/qt/InputItem.cpp b/src/platform/qt/InputItem.cpp index efcac346e..8dffa01ef 100644 --- a/src/platform/qt/InputItem.cpp +++ b/src/platform/qt/InputItem.cpp @@ -43,7 +43,7 @@ InputItem::InputItem(InputItem::Functions functions, const QString& visibleName, InputItem::InputItem(int key, const QString& visibleName, const QString& name, InputItem* parent) : QObject(parent) - , m_keys(key) + , m_key(key) , m_name(name) , m_visibleName(visibleName) , m_parent(parent) @@ -84,3 +84,15 @@ void InputItem::setAxis(int axis, GamepadAxisEvent::Direction direction) { m_direction = direction; emit axisBound(this, axis, direction); } + +void InputItem::trigger(bool active) { + if (active) { + if (m_functions.first) { + m_functions.first(); + } + } else { + if (m_functions.second) { + m_functions.second(); + } + } +} diff --git a/src/platform/qt/InputItem.h b/src/platform/qt/InputItem.h index 2cf6da9c3..510bb65e4 100644 --- a/src/platform/qt/InputItem.h +++ b/src/platform/qt/InputItem.h @@ -32,7 +32,7 @@ public: const QAction* action() const { return m_action; } const QMenu* menu() const { return m_menu; } Functions functions() const { return m_functions; } - int key() const { return m_keys; } + int key() const { return m_key; } const QString& visibleName() const { return m_visibleName; } const QString& name() const { return m_name; } @@ -64,6 +64,9 @@ public: return m_name == other.m_name && m_visibleName == other.m_visibleName; } +public slots: + void trigger(bool = true); + signals: void shortcutBound(InputItem*, int shortcut); void buttonBound(InputItem*, int button); @@ -80,7 +83,7 @@ private: int m_shortcut = 0; int m_button = -1; int m_axis = -1; - int m_keys =-1; + int m_key = -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 e47179e3f..fa54e61ec 100644 --- a/src/platform/qt/InputModel.cpp +++ b/src/platform/qt/InputModel.cpp @@ -136,6 +136,14 @@ const InputItem* InputModel::itemAt(const QModelIndex& index) const { return pmenu->items()[index.row()]; } +InputItem* InputModel::itemAt(const QString& name) { + return m_names[name]; +} + +const InputItem* InputModel::itemAt(const QString& name) const { + return m_names[name]; +} + InputItem* InputModel::itemForMenu(const QMenu* menu) { InputItem* item = m_menus[menu]; if (!item) { @@ -143,6 +151,7 @@ InputItem* InputModel::itemForMenu(const QMenu* menu) { } return item; } + const InputItem* InputModel::itemForMenu(const QMenu* menu) const { const InputItem* item = m_menus[menu]; if (!item) { @@ -151,6 +160,18 @@ const InputItem* InputModel::itemForMenu(const QMenu* menu) const { return item; } +InputItem* InputModel::itemForShortcut(int shortcut) { + return m_shortcuts[shortcut]; +} + +InputItem* InputModel::itemForButton(int button) { + return m_buttons[button]; +} + +InputItem* InputModel::itemForAxis(int axis, GamepadAxisEvent::Direction direction) { + return m_axes[qMakePair(axis, direction)]; +} + bool InputModel::loadShortcuts(InputItem* item) { if (item->name().isNull()) { return false; @@ -293,6 +314,36 @@ void InputModel::itemAdded(InputItem* parent, InputItem* child) { if (menu) { m_menus[menu] = child; } + if (child->shortcut()) { + m_shortcuts[child->shortcut()] = child; + } + if (child->button() >= 0) { + m_buttons[child->button()] = child; + } + if (child->direction() != GamepadAxisEvent::NEUTRAL) { + m_axes[qMakePair(child->axis(), child->direction())] = child; + } m_names[child->name()] = child; connect(child, &InputItem::childAdded, this, &InputModel::itemAdded); + connect(child, &InputItem::shortcutBound, this, &InputModel::rebindShortcut); + connect(child, &InputItem::buttonBound, this, &InputModel::rebindButton); + connect(child, &InputItem::axisBound, this, &InputModel::rebindAxis); +} + +void InputModel::rebindShortcut(InputItem* item, int shortcut) { + if (shortcut) { + m_shortcuts[shortcut] = item; + } +} + +void InputModel::rebindButton(InputItem* item, int button) { + if (button >= 0) { + m_buttons[button] = item; + } +} + +void InputModel::rebindAxis(InputItem* item, int axis, GamepadAxisEvent::Direction direction) { + if (axis != GamepadAxisEvent::NEUTRAL) { + m_axes[qMakePair(axis, direction)] = item; + } } diff --git a/src/platform/qt/InputModel.h b/src/platform/qt/InputModel.h index e1c354a73..50a99d4aa 100644 --- a/src/platform/qt/InputModel.h +++ b/src/platform/qt/InputModel.h @@ -37,6 +37,9 @@ private: private slots: void itemAdded(InputItem* parent, InputItem* child); + void rebindShortcut(InputItem*, int shortcut); + void rebindButton(InputItem*, int button); + void rebindAxis(InputItem*, int axis, GamepadAxisEvent::Direction); public: InputModel(QObject* parent = nullptr); @@ -60,12 +63,13 @@ public: InputItem* itemAt(const QModelIndex& index); const InputItem* itemAt(const QModelIndex& index) const; - InputItem* itemForKey(int key); - const InputItem* itemForKey(int key) const; - InputItem* itemForMenu(const QMenu* menu); const InputItem* itemForMenu(const QMenu* menu) const; + InputItem* itemForShortcut(int shortcut); + InputItem* itemForButton(int button); + InputItem* itemForAxis(int axis, GamepadAxisEvent::Direction); + static int toModifierShortcut(const QString& shortcut); static bool isModifierKey(int key); static int toModifierKey(int key); @@ -84,6 +88,9 @@ private: InputItem m_rootMenu; QMap m_names; QMap m_menus; + QMap m_shortcuts; + QMap m_buttons; + QMap, InputItem*> m_axes; ConfigController* m_config; QString m_profileName; const InputProfile* m_profile; diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 172ba46d5..5f7419b4d 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -193,8 +193,6 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent) m_inputModel->setConfigController(m_config); setupMenu(menuBar()); - - m_inputController.setupCallback(m_controller); } Window::~Window() { @@ -1543,6 +1541,69 @@ void Window::setupMenu(QMenuBar* menubar) { m_controller->setAutofire(GBA_KEY_LEFT, false); }), tr("Autofire Left"), "autofireLeft"); + QMenu* bindingsMenu = new QMenu(tr("Bindings"), this); + InputItem* bindingsMenuItem = m_inputModel->addItem(bindingsMenu, "bindings"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_A); + }, [this]() { + m_controller->keyReleased(GBA_KEY_A); + }), tr("A"), "keyA"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_B); + }, [this]() { + m_controller->keyReleased(GBA_KEY_B); + }), tr("B"), "keyB"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_START); + }, [this]() { + m_controller->keyReleased(GBA_KEY_START); + }), tr("Start"), "keyStart"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_SELECT); + }, [this]() { + m_controller->keyReleased(GBA_KEY_SELECT); + }), tr("Select"), "keySelect"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_L); + }, [this]() { + m_controller->keyReleased(GBA_KEY_L); + }), tr("L"), "keyL"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_R); + }, [this]() { + m_controller->keyReleased(GBA_KEY_R); + }), tr("R"), "keyR"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_UP); + }, [this]() { + m_controller->keyReleased(GBA_KEY_UP); + }), tr("Up"), "keyUp"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_DOWN); + }, [this]() { + m_controller->keyReleased(GBA_KEY_DOWN); + }), tr("Down"), "keyDown"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_LEFT); + }, [this]() { + m_controller->keyReleased(GBA_KEY_LEFT); + }), tr("Left"), "keyLeft"); + + bindingsMenuItem->addItem(qMakePair([this]() { + m_controller->keyPressed(GBA_KEY_RIGHT); + }, [this]() { + m_controller->keyReleased(GBA_KEY_RIGHT); + }), tr("Right"), "keyRight"); + for (QAction* action : m_gameActions) { action->setDisabled(true); }