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
|
||||
- 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,18 +298,20 @@ void InputController::testGamepad() {
|
|||
|
||||
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()) {
|
||||
return;
|
||||
|
|
|
@ -40,6 +40,16 @@ QVariant ShortcutController::data(const QModelIndex& index, int role) const {
|
|||
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,6 +229,7 @@ void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
|||
m_buttons.take(oldButton);
|
||||
}
|
||||
if (button >= 0) {
|
||||
updateAxis(index, -1, GamepadAxisEvent::NEUTRAL);
|
||||
m_buttons[button] = item;
|
||||
}
|
||||
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()));
|
||||
}
|
||||
|
||||
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) {
|
||||
updateKey(index, QKeySequence());
|
||||
}
|
||||
|
@ -286,6 +329,31 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
|||
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 @@ void ShortcutController::loadShortcuts(ShortcutItem* 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) {
|
||||
|
@ -339,6 +431,8 @@ ShortcutController::ShortcutItem::ShortcutItem(QAction* action, const QString& n
|
|||
, 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 @@ ShortcutController::ShortcutItem::ShortcutItem(ShortcutController::ShortcutItem:
|
|||
, 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 @@ void ShortcutController::ShortcutItem::setShortcut(const QKeySequence& 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
|
||||
#define QGBA_SHORTCUT_MODEL
|
||||
|
||||
#include "GamepadAxisEvent.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QKeySequence>
|
||||
|
||||
|
@ -26,6 +28,7 @@ Q_OBJECT
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
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 @@ public:
|
|||
|
||||
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 @@ private:
|
|||
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 @@ ShortcutView::ShortcutView(QWidget* parent)
|
|||
|
||||
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()));
|
||||
}
|
||||
|
@ -31,15 +32,6 @@ void ShortcutView::setController(ShortcutController* 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) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
|
@ -106,5 +98,12 @@ void ShortcutView::updateButton(int button) {
|
|||
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 @@
|
|||
#ifndef QGBA_SHORTCUT_VIEW
|
||||
#define QGBA_SHORTCUT_VIEW
|
||||
|
||||
#include "GamepadAxisEvent.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ui_ShortcutView.h"
|
||||
|
@ -23,7 +25,6 @@ public:
|
|||
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 @@ private slots:
|
|||
void clear();
|
||||
void updateKey(const QKeySequence&);
|
||||
void updateButton(int button);
|
||||
void updateAxis(int axis, int direction);
|
||||
|
||||
private:
|
||||
Ui::ShortcutView m_ui;
|
||||
|
|
Loading…
Reference in New Issue