mirror of https://github.com/mgba-emu/mgba.git
Qt: Analog inputs can be used for shortcuts
This commit is contained in:
parent
a0a3ac191a
commit
0c8a0cd0e4
1
CHANGES
1
CHANGES
|
@ -9,6 +9,7 @@ Features:
|
||||||
- Import/Export of GameShark/Action Replay snapshots
|
- Import/Export of GameShark/Action Replay snapshots
|
||||||
- Add "Step backwards" item for single increment rewind
|
- Add "Step backwards" item for single increment rewind
|
||||||
- Deadzone estimation for game controllers
|
- Deadzone estimation for game controllers
|
||||||
|
- Analog inputs can be used for shortcuts
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- GBA: Fix timers not updating timing when writing to only the reload register
|
- GBA: Fix timers not updating timing when writing to only the reload register
|
||||||
- All: Fix sanitize-deb script not cleaning up after itself
|
- All: Fix sanitize-deb script not cleaning up after itself
|
||||||
|
|
|
@ -298,18 +298,20 @@ void InputController::testGamepad() {
|
||||||
|
|
||||||
for (auto& axis : m_activeAxes) {
|
for (auto& axis : m_activeAxes) {
|
||||||
bool newlyAboveThreshold = activeAxes.contains(axis);
|
bool newlyAboveThreshold = activeAxes.contains(axis);
|
||||||
GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, newlyAboveThreshold, this);
|
|
||||||
if (newlyAboveThreshold) {
|
if (newlyAboveThreshold) {
|
||||||
|
GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, newlyAboveThreshold, this);
|
||||||
postPendingEvent(event->gbaKey());
|
postPendingEvent(event->gbaKey());
|
||||||
QApplication::sendEvent(QApplication::focusWidget(), event);
|
QApplication::sendEvent(QApplication::focusWidget(), event);
|
||||||
if (!event->isAccepted()) {
|
if (!event->isAccepted()) {
|
||||||
clearPendingEvent(event->gbaKey());
|
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()) {
|
if (!QApplication::focusWidget()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -40,6 +40,16 @@ QVariant ShortcutController::data(const QModelIndex& index, int role) const {
|
||||||
if (item->button() >= 0) {
|
if (item->button() >= 0) {
|
||||||
return item->button();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
@ -219,6 +229,7 @@ void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
||||||
m_buttons.take(oldButton);
|
m_buttons.take(oldButton);
|
||||||
}
|
}
|
||||||
if (button >= 0) {
|
if (button >= 0) {
|
||||||
|
updateAxis(index, -1, GamepadAxisEvent::NEUTRAL);
|
||||||
m_buttons[button] = item;
|
m_buttons[button] = item;
|
||||||
}
|
}
|
||||||
if (m_config) {
|
if (m_config) {
|
||||||
|
@ -227,6 +238,38 @@ void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
||||||
emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), createIndex(index.row(), 2, index.internalPointer()));
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
void ShortcutController::clearKey(const QModelIndex& index) {
|
void ShortcutController::clearKey(const QModelIndex& index) {
|
||||||
updateKey(index, QKeySequence());
|
updateKey(index, QKeySequence());
|
||||||
}
|
}
|
||||||
|
@ -286,6 +329,31 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
||||||
event->accept();
|
event->accept();
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,6 +379,30 @@ void ShortcutController::loadShortcuts(ShortcutItem* item) {
|
||||||
}
|
}
|
||||||
m_buttons[button.toInt()] = item;
|
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) {
|
QKeySequence ShortcutController::keyEventToSequence(const QKeyEvent* event) {
|
||||||
|
@ -339,6 +431,8 @@ ShortcutController::ShortcutItem::ShortcutItem(QAction* action, const QString& n
|
||||||
, m_menu(nullptr)
|
, m_menu(nullptr)
|
||||||
, m_name(name)
|
, m_name(name)
|
||||||
, m_button(-1)
|
, m_button(-1)
|
||||||
|
, m_axis(-1)
|
||||||
|
, m_direction(GamepadAxisEvent::NEUTRAL)
|
||||||
, m_parent(parent)
|
, m_parent(parent)
|
||||||
{
|
{
|
||||||
m_visibleName = action->text()
|
m_visibleName = action->text()
|
||||||
|
@ -354,6 +448,8 @@ ShortcutController::ShortcutItem::ShortcutItem(ShortcutController::ShortcutItem:
|
||||||
, m_name(name)
|
, m_name(name)
|
||||||
, m_visibleName(visibleName)
|
, m_visibleName(visibleName)
|
||||||
, m_button(-1)
|
, m_button(-1)
|
||||||
|
, m_axis(-1)
|
||||||
|
, m_direction(GamepadAxisEvent::NEUTRAL)
|
||||||
, m_parent(parent)
|
, m_parent(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -362,6 +458,8 @@ ShortcutController::ShortcutItem::ShortcutItem(QMenu* menu, ShortcutItem* parent
|
||||||
: m_action(nullptr)
|
: m_action(nullptr)
|
||||||
, m_menu(menu)
|
, m_menu(menu)
|
||||||
, m_button(-1)
|
, m_button(-1)
|
||||||
|
, m_axis(-1)
|
||||||
|
, m_direction(GamepadAxisEvent::NEUTRAL)
|
||||||
, m_parent(parent)
|
, m_parent(parent)
|
||||||
{
|
{
|
||||||
if (menu) {
|
if (menu) {
|
||||||
|
@ -389,3 +487,8 @@ void ShortcutController::ShortcutItem::setShortcut(const QKeySequence& shortcut)
|
||||||
m_action->setShortcut(shortcut);
|
m_action->setShortcut(shortcut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShortcutController::ShortcutItem::setAxis(int axis, GamepadAxisEvent::Direction direction) {
|
||||||
|
m_axis = axis;
|
||||||
|
m_direction = direction;
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#ifndef QGBA_SHORTCUT_MODEL
|
#ifndef QGBA_SHORTCUT_MODEL
|
||||||
#define QGBA_SHORTCUT_MODEL
|
#define QGBA_SHORTCUT_MODEL
|
||||||
|
|
||||||
|
#include "GamepadAxisEvent.h"
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
#include <QKeySequence>
|
#include <QKeySequence>
|
||||||
|
|
||||||
|
@ -26,6 +28,7 @@ Q_OBJECT
|
||||||
private:
|
private:
|
||||||
constexpr static const char* const KEY_SECTION = "shortcutKey";
|
constexpr static const char* const KEY_SECTION = "shortcutKey";
|
||||||
constexpr static const char* const BUTTON_SECTION = "shortcutButton";
|
constexpr static const char* const BUTTON_SECTION = "shortcutButton";
|
||||||
|
constexpr static const char* const AXIS_SECTION = "shortcutAxis";
|
||||||
|
|
||||||
class ShortcutItem {
|
class ShortcutItem {
|
||||||
public:
|
public:
|
||||||
|
@ -53,6 +56,9 @@ private:
|
||||||
int button() const { return m_button; }
|
int button() const { return m_button; }
|
||||||
void setShortcut(const QKeySequence& sequence);
|
void setShortcut(const QKeySequence& sequence);
|
||||||
void setButton(int button) { m_button = button; }
|
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; }
|
bool operator==(const ShortcutItem& other) const { return m_menu == other.m_menu && m_action == other.m_action; }
|
||||||
|
|
||||||
|
@ -64,6 +70,8 @@ private:
|
||||||
QString m_name;
|
QString m_name;
|
||||||
QString m_visibleName;
|
QString m_visibleName;
|
||||||
int m_button;
|
int m_button;
|
||||||
|
int m_axis;
|
||||||
|
GamepadAxisEvent::Direction m_direction;
|
||||||
QList<ShortcutItem> m_items;
|
QList<ShortcutItem> m_items;
|
||||||
ShortcutItem* m_parent;
|
ShortcutItem* m_parent;
|
||||||
};
|
};
|
||||||
|
@ -91,6 +99,7 @@ public:
|
||||||
|
|
||||||
void updateKey(const QModelIndex& index, const QKeySequence& keySequence);
|
void updateKey(const QModelIndex& index, const QKeySequence& keySequence);
|
||||||
void updateButton(const QModelIndex& index, int button);
|
void updateButton(const QModelIndex& index, int button);
|
||||||
|
void updateAxis(const QModelIndex& index, int axis, GamepadAxisEvent::Direction direction);
|
||||||
|
|
||||||
void clearKey(const QModelIndex& index);
|
void clearKey(const QModelIndex& index);
|
||||||
void clearButton(const QModelIndex& index);
|
void clearButton(const QModelIndex& index);
|
||||||
|
@ -108,6 +117,7 @@ private:
|
||||||
ShortcutItem m_rootMenu;
|
ShortcutItem m_rootMenu;
|
||||||
QMap<QMenu*, ShortcutItem*> m_menuMap;
|
QMap<QMenu*, ShortcutItem*> m_menuMap;
|
||||||
QMap<int, ShortcutItem*> m_buttons;
|
QMap<int, ShortcutItem*> m_buttons;
|
||||||
|
QMap<QPair<int, GamepadAxisEvent::Direction>, ShortcutItem*> m_axes;
|
||||||
QMap<QKeySequence, ShortcutItem*> m_heldKeys;
|
QMap<QKeySequence, ShortcutItem*> m_heldKeys;
|
||||||
ConfigController* m_config;
|
ConfigController* m_config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,7 @@ ShortcutView::ShortcutView(QWidget* parent)
|
||||||
|
|
||||||
connect(m_ui.keySequenceEdit, SIGNAL(keySequenceChanged(const QKeySequence&)), this, SLOT(updateKey(const QKeySequence&)));
|
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(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.shortcutTable, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(load(const QModelIndex&)));
|
||||||
connect(m_ui.clearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
connect(m_ui.clearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
||||||
}
|
}
|
||||||
|
@ -31,15 +32,6 @@ void ShortcutView::setController(ShortcutController* controller) {
|
||||||
m_ui.shortcutTable->setModel(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) {
|
bool ShortcutView::eventFilter(QObject*, QEvent* event) {
|
||||||
if (event->type() == QEvent::KeyPress) {
|
if (event->type() == QEvent::KeyPress) {
|
||||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||||
|
@ -106,5 +98,12 @@ void ShortcutView::updateButton(int button) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_controller->updateButton(m_ui.shortcutTable->selectionModel()->currentIndex(), button);
|
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 @@
|
||||||
#ifndef QGBA_SHORTCUT_VIEW
|
#ifndef QGBA_SHORTCUT_VIEW
|
||||||
#define QGBA_SHORTCUT_VIEW
|
#define QGBA_SHORTCUT_VIEW
|
||||||
|
|
||||||
|
#include "GamepadAxisEvent.h"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "ui_ShortcutView.h"
|
#include "ui_ShortcutView.h"
|
||||||
|
@ -23,7 +25,6 @@ public:
|
||||||
void setController(ShortcutController* controller);
|
void setController(ShortcutController* controller);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool event(QEvent* event) override;
|
|
||||||
virtual bool eventFilter(QObject* obj, QEvent* event) override;
|
virtual bool eventFilter(QObject* obj, QEvent* event) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -31,6 +32,7 @@ private slots:
|
||||||
void clear();
|
void clear();
|
||||||
void updateKey(const QKeySequence&);
|
void updateKey(const QKeySequence&);
|
||||||
void updateButton(int button);
|
void updateButton(int button);
|
||||||
|
void updateAxis(int axis, int direction);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ShortcutView m_ui;
|
Ui::ShortcutView m_ui;
|
||||||
|
|
Loading…
Reference in New Issue