Qt: Analog inputs can be used for shortcuts
@@ -9,6 +9,7 @@ - Rewind now shows the frame after rewinding
- Import/Export of GameShark/Action Replay snapshots - Add "Step backwards" item for single increment rewind - Deadzone estimation for game controllers + - Analog inputs can be used for shortcuts Bugfixes: - GBA: Fix timers not updating timing when writing to only the reload register - All: Fix sanitize-deb script not cleaning up after itself
@@ -298,17 +298,19 @@ oldAxes.subtract(m_activeAxes);
for (auto& axis : m_activeAxes) { bool newlyAboveThreshold = activeAxes.contains(axis); - GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, newlyAboveThreshold, this); if (newlyAboveThreshold) { + GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, newlyAboveThreshold, this); postPendingEvent(event->gbaKey()); QApplication::sendEvent(QApplication::focusWidget(), event); if (!event->isAccepted()) { clearPendingEvent(event->gbaKey()); } - } else if (oldAxes.contains(axis)) { - clearPendingEvent(event->gbaKey()); - QApplication::sendEvent(QApplication::focusWidget(), event); } + } + for (auto axis : oldAxes) { + GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, false, this); + clearPendingEvent(event->gbaKey()); + QApplication::sendEvent(QApplication::focusWidget(), event); } if (!QApplication::focusWidget()) {
@@ -40,6 +40,16 @@ case 2:
if (item->button() >= 0) { return item->button(); } + if (item->axis() >= 0) { + char d = '\0'; + if (item->direction() == GamepadAxisEvent::POSITIVE) { + d = '+'; + } + if (item->direction() == GamepadAxisEvent::NEGATIVE) { + d = '-'; + } + return QString("%1%2").arg(d).arg(item->axis()); + } break; } return QVariant();@@ -219,10 +229,43 @@ if (oldButton >= 0) {
m_buttons.take(oldButton); } if (button >= 0) { + updateAxis(index, -1, GamepadAxisEvent::NEUTRAL); m_buttons[button] = item; } if (m_config) { m_config->setQtOption(item->name(), button, BUTTON_SECTION); + } + emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), createIndex(index.row(), 2, index.internalPointer())); +} + +void ShortcutController::updateAxis(const QModelIndex& index, int axis, GamepadAxisEvent::Direction direction) { + if (!index.isValid()) { + return; + } + const QModelIndex& parent = index.parent(); + if (!parent.isValid()) { + return; + } + ShortcutItem* item = itemAt(index); + int oldAxis = item->axis(); + GamepadAxisEvent::Direction oldDirection = item->direction(); + item->setAxis(axis, 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; + } + 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); } emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), createIndex(index.row(), 2, index.internalPointer())); }@@ -286,6 +329,31 @@ }
event->accept(); return true; } + if (event->type() == GamepadAxisEvent::Type()) { + GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event); + auto item = m_axes.find(qMakePair(gae->axis(), gae->direction())); + if (item == m_axes.end()) { + return false; + } + if (gae->isNew()) { + QAction* action = item.value()->action(); + if (action && action->isEnabled()) { + action->trigger(); + } + } + ShortcutItem::Functions pair = item.value()->functions(); + if (gae->isNew()) { + if (pair.first) { + pair.first(); + } + } else { + if (pair.second) { + pair.second(); + } + } + event->accept(); + return true; + } return false; }@@ -311,6 +379,30 @@ m_buttons.take(oldButton);
} m_buttons[button.toInt()] = item; } + QVariant axis = m_config->getQtOption(item->name(), AXIS_SECTION); + if (!axis.isNull()) { + int oldAxis = item->axis(); + GamepadAxisEvent::Direction oldDirection = item->direction(); + QString axisDesc = axis.toString(); + if (axisDesc.size() >= 2) { + GamepadAxisEvent::Direction direction = GamepadAxisEvent::NEUTRAL; + if (axisDesc[0] == '-') { + direction = GamepadAxisEvent::NEGATIVE; + } + if (axisDesc[0] == '+') { + direction = GamepadAxisEvent::POSITIVE; + } + bool ok; + int axis = axisDesc.mid(1).toInt(&ok); + if (ok) { + item->setAxis(axis, direction); + if (oldAxis >= 0) { + m_axes.take(qMakePair(oldAxis, oldDirection)); + } + m_axes[qMakePair(axis, direction)] = item; + } + } + } } QKeySequence ShortcutController::keyEventToSequence(const QKeyEvent* event) {@@ -339,6 +431,8 @@ , m_shortcut(action->shortcut())
, m_menu(nullptr) , m_name(name) , m_button(-1) + , m_axis(-1) + , m_direction(GamepadAxisEvent::NEUTRAL) , m_parent(parent) { m_visibleName = action->text()@@ -354,6 +448,8 @@ , m_menu(nullptr)
, m_name(name) , m_visibleName(visibleName) , m_button(-1) + , m_axis(-1) + , m_direction(GamepadAxisEvent::NEUTRAL) , m_parent(parent) { }@@ -362,6 +458,8 @@ ShortcutController::ShortcutItem::ShortcutItem(QMenu* menu, ShortcutItem* parent)
: m_action(nullptr) , m_menu(menu) , m_button(-1) + , m_axis(-1) + , m_direction(GamepadAxisEvent::NEUTRAL) , m_parent(parent) { if (menu) {@@ -389,3 +487,8 @@ if (m_action) {
m_action->setShortcut(shortcut); } } + +void ShortcutController::ShortcutItem::setAxis(int axis, GamepadAxisEvent::Direction direction) { + m_axis = axis; + m_direction = direction; +}
@@ -6,6 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef QGBA_SHORTCUT_MODEL #define QGBA_SHORTCUT_MODEL +#include "GamepadAxisEvent.h" + #include <QAbstractItemModel> #include <QKeySequence>@@ -26,6 +28,7 @@
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"; class ShortcutItem { public:@@ -53,6 +56,9 @@ void addSubmenu(QMenu* menu);
int button() const { return m_button; } void setShortcut(const QKeySequence& sequence); void setButton(int button) { m_button = button; } + int axis() const { return m_axis; } + GamepadAxisEvent::Direction direction() const { return m_direction; } + void setAxis(int axis, GamepadAxisEvent::Direction direction); bool operator==(const ShortcutItem& other) const { return m_menu == other.m_menu && m_action == other.m_action; }@@ -64,6 +70,8 @@ Functions m_functions;
QString m_name; QString m_visibleName; int m_button; + int m_axis; + GamepadAxisEvent::Direction m_direction; QList<ShortcutItem> m_items; ShortcutItem* m_parent; };@@ -91,6 +99,7 @@ bool isMenuAt(const QModelIndex& index) const;
void updateKey(const QModelIndex& index, const QKeySequence& keySequence); void updateButton(const QModelIndex& index, int button); + void updateAxis(const QModelIndex& index, int axis, GamepadAxisEvent::Direction direction); void clearKey(const QModelIndex& index); void clearButton(const QModelIndex& index);@@ -108,6 +117,7 @@
ShortcutItem m_rootMenu; QMap<QMenu*, ShortcutItem*> m_menuMap; QMap<int, ShortcutItem*> m_buttons; + QMap<QPair<int, GamepadAxisEvent::Direction>, ShortcutItem*> m_axes; QMap<QKeySequence, ShortcutItem*> m_heldKeys; ConfigController* m_config; };
@@ -22,6 +22,7 @@ m_ui.keySequenceEdit->installEventFilter(this);
connect(m_ui.keySequenceEdit, SIGNAL(keySequenceChanged(const QKeySequence&)), this, SLOT(updateKey(const QKeySequence&))); connect(m_ui.keyEdit, SIGNAL(valueChanged(int)), this, SLOT(updateButton(int))); + connect(m_ui.keyEdit, SIGNAL(axisChanged(int, int)), this, SLOT(updateAxis(int, int))); connect(m_ui.shortcutTable, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(load(const QModelIndex&))); connect(m_ui.clearButton, SIGNAL(clicked()), this, SLOT(clear())); }@@ -29,15 +30,6 @@
void ShortcutView::setController(ShortcutController* controller) { m_controller = controller; m_ui.shortcutTable->setModel(controller); -} - -bool ShortcutView::event(QEvent* event) { - if (event->type() == GamepadButtonEvent::Down()) { - updateButton(static_cast<GamepadButtonEvent*>(event)->value()); - event->accept(); - return true; - } - return QWidget::event(event); } bool ShortcutView::eventFilter(QObject*, QEvent* event) {@@ -106,5 +98,12 @@ if (!m_controller || m_controller->isMenuAt(m_ui.shortcutTable->selectionModel()->currentIndex())) {
return; } m_controller->updateButton(m_ui.shortcutTable->selectionModel()->currentIndex(), button); +} + +void ShortcutView::updateAxis(int axis, int direction) { + if (!m_controller || m_controller->isMenuAt(m_ui.shortcutTable->selectionModel()->currentIndex())) { + return; + } + m_controller->updateAxis(m_ui.shortcutTable->selectionModel()->currentIndex(), axis, static_cast<GamepadAxisEvent::Direction>(direction)); }
@@ -6,6 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef QGBA_SHORTCUT_VIEW #define QGBA_SHORTCUT_VIEW +#include "GamepadAxisEvent.h" + #include <QWidget> #include "ui_ShortcutView.h"@@ -23,7 +25,6 @@
void setController(ShortcutController* controller); protected: - virtual bool event(QEvent* event) override; virtual bool eventFilter(QObject* obj, QEvent* event) override; private slots:@@ -31,6 +32,7 @@ void load(const QModelIndex&);
void clear(); void updateKey(const QKeySequence&); void updateButton(int button); + void updateAxis(int axis, int direction); private: Ui::ShortcutView m_ui;