mirror of https://github.com/mgba-emu/mgba.git
Qt: Start splitting up InputController
This commit is contained in:
parent
1584023f34
commit
be3022156f
|
@ -107,6 +107,7 @@ set(SOURCE_FILES
|
||||||
GamepadButtonEvent.cpp
|
GamepadButtonEvent.cpp
|
||||||
GamepadHatEvent.cpp
|
GamepadHatEvent.cpp
|
||||||
IOViewer.cpp
|
IOViewer.cpp
|
||||||
|
input/InputMapper.cpp
|
||||||
InputController.cpp
|
InputController.cpp
|
||||||
InputProfile.cpp
|
InputProfile.cpp
|
||||||
KeyEditor.cpp
|
KeyEditor.cpp
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "input/InputMapper.h"
|
||||||
#include "InputController.h"
|
#include "InputController.h"
|
||||||
#include "KeyEditor.h"
|
#include "KeyEditor.h"
|
||||||
|
|
||||||
|
@ -214,8 +215,9 @@ void GBAKeyEditor::setNext() {
|
||||||
|
|
||||||
void GBAKeyEditor::save() {
|
void GBAKeyEditor::save() {
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
m_controller->unbindAllAxes(m_type);
|
InputMapper mapper = m_controller->mapper(m_type);
|
||||||
m_controller->unbindAllHats(m_type);
|
mapper.unbindAllAxes();
|
||||||
|
mapper.unbindAllHats();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bindKey(m_keyDU, GBA_KEY_UP);
|
bindKey(m_keyDU, GBA_KEY_UP);
|
||||||
|
@ -324,15 +326,16 @@ void GBAKeyEditor::lookupHats(const mInputMap* map) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void GBAKeyEditor::bindKey(const KeyEditor* keyEditor, GBAKey key) {
|
void GBAKeyEditor::bindKey(const KeyEditor* keyEditor, GBAKey key) {
|
||||||
|
InputMapper mapper = m_controller->mapper(m_type);
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (m_type == SDL_BINDING_BUTTON && keyEditor->axis() >= 0) {
|
if (m_type == SDL_BINDING_BUTTON && keyEditor->axis() >= 0) {
|
||||||
m_controller->bindAxis(m_type, keyEditor->axis(), keyEditor->direction(), key);
|
mapper.bindAxis(keyEditor->axis(), keyEditor->direction(), key);
|
||||||
}
|
}
|
||||||
if (m_type == SDL_BINDING_BUTTON && keyEditor->hat() >= 0) {
|
if (m_type == SDL_BINDING_BUTTON && keyEditor->hat() >= 0) {
|
||||||
m_controller->bindHat(m_type, keyEditor->hat(), keyEditor->hatDirection(), key);
|
mapper.bindHat(keyEditor->hat(), keyEditor->hatDirection(), key);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
m_controller->bindKey(m_type, keyEditor->value(), key);
|
mapper.bindKey(keyEditor->value(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GBAKeyEditor::findFocus(KeyEditor* needle) {
|
bool GBAKeyEditor::findFocus(KeyEditor* needle) {
|
||||||
|
|
|
@ -301,6 +301,10 @@ void InputController::setPreferredGamepad(uint32_t type, int index) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputMapper InputController::mapper(uint32_t type) {
|
||||||
|
return InputMapper(&m_inputMap, type);
|
||||||
|
}
|
||||||
|
|
||||||
mRumble* InputController::rumble() {
|
mRumble* InputController::rumble() {
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
@ -384,10 +388,6 @@ GBAKey InputController::mapKeyboard(int key) const {
|
||||||
return static_cast<GBAKey>(mInputMapKey(&m_inputMap, KEYBOARD, key));
|
return static_cast<GBAKey>(mInputMapKey(&m_inputMap, KEYBOARD, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::bindKey(uint32_t type, int key, GBAKey gbaKey) {
|
|
||||||
return mInputBindKey(&m_inputMap, type, key, gbaKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputController::updateJoysticks() {
|
void InputController::updateJoysticks() {
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
QString profile = profileForType(SDL_BINDING_BUTTON);
|
QString profile = profileForType(SDL_BINDING_BUTTON);
|
||||||
|
@ -501,36 +501,6 @@ QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes
|
||||||
return activeAxes;
|
return activeAxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction direction, GBAKey key) {
|
|
||||||
const mInputAxis* old = mInputQueryAxis(&m_inputMap, type, axis);
|
|
||||||
mInputAxis description = { GBA_KEY_NONE, GBA_KEY_NONE, -AXIS_THRESHOLD, AXIS_THRESHOLD };
|
|
||||||
if (old) {
|
|
||||||
description = *old;
|
|
||||||
}
|
|
||||||
int deadzone = 0;
|
|
||||||
if (axis > 0 && m_deadzones.size() > axis) {
|
|
||||||
deadzone = m_deadzones[axis];
|
|
||||||
}
|
|
||||||
switch (direction) {
|
|
||||||
case GamepadAxisEvent::NEGATIVE:
|
|
||||||
description.lowDirection = key;
|
|
||||||
|
|
||||||
description.deadLow = deadzone - AXIS_THRESHOLD;
|
|
||||||
break;
|
|
||||||
case GamepadAxisEvent::POSITIVE:
|
|
||||||
description.highDirection = key;
|
|
||||||
description.deadHigh = deadzone + AXIS_THRESHOLD;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mInputBindAxis(&m_inputMap, type, axis, &description);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputController::unbindAllAxes(uint32_t type) {
|
|
||||||
mInputUnbindAllAxes(&m_inputMap, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QPair<int, GamepadHatEvent::Direction>> InputController::activeGamepadHats(int type) {
|
QSet<QPair<int, GamepadHatEvent::Direction>> InputController::activeGamepadHats(int type) {
|
||||||
QSet<QPair<int, GamepadHatEvent::Direction>> activeHats;
|
QSet<QPair<int, GamepadHatEvent::Direction>> activeHats;
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
|
@ -563,32 +533,6 @@ QSet<QPair<int, GamepadHatEvent::Direction>> InputController::activeGamepadHats(
|
||||||
return activeHats;
|
return activeHats;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::bindHat(uint32_t type, int hat, GamepadHatEvent::Direction direction, GBAKey gbaKey) {
|
|
||||||
mInputHatBindings bindings{ -1, -1, -1, -1 };
|
|
||||||
mInputQueryHat(&m_inputMap, type, hat, &bindings);
|
|
||||||
switch (direction) {
|
|
||||||
case GamepadHatEvent::UP:
|
|
||||||
bindings.up = gbaKey;
|
|
||||||
break;
|
|
||||||
case GamepadHatEvent::RIGHT:
|
|
||||||
bindings.right = gbaKey;
|
|
||||||
break;
|
|
||||||
case GamepadHatEvent::DOWN:
|
|
||||||
bindings.down = gbaKey;
|
|
||||||
break;
|
|
||||||
case GamepadHatEvent::LEFT:
|
|
||||||
bindings.left = gbaKey;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mInputBindHat(&m_inputMap, type, hat, &bindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputController::unbindAllHats(uint32_t type) {
|
|
||||||
mInputUnbindAllHats(&m_inputMap, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputController::testGamepad(int type) {
|
void InputController::testGamepad(int type) {
|
||||||
QWriteLocker l(&m_eventsLock);
|
QWriteLocker l(&m_eventsLock);
|
||||||
auto activeAxes = activeGamepadAxes(type);
|
auto activeAxes = activeGamepadAxes(type);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "GamepadAxisEvent.h"
|
#include "GamepadAxisEvent.h"
|
||||||
#include "GamepadHatEvent.h"
|
#include "GamepadHatEvent.h"
|
||||||
|
#include "input/InputMapper.h"
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
@ -64,8 +65,6 @@ public:
|
||||||
|
|
||||||
GBAKey mapKeyboard(int key) const;
|
GBAKey mapKeyboard(int key) const;
|
||||||
|
|
||||||
void bindKey(uint32_t type, int key, GBAKey);
|
|
||||||
|
|
||||||
const mInputMap* map() const { return &m_inputMap; }
|
const mInputMap* map() const { return &m_inputMap; }
|
||||||
|
|
||||||
int pollEvents();
|
int pollEvents();
|
||||||
|
@ -76,17 +75,13 @@ public:
|
||||||
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
|
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
|
||||||
void recalibrateAxes();
|
void recalibrateAxes();
|
||||||
|
|
||||||
void bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction, GBAKey);
|
|
||||||
void unbindAllAxes(uint32_t type);
|
|
||||||
|
|
||||||
void bindHat(uint32_t type, int hat, GamepadHatEvent::Direction, GBAKey);
|
|
||||||
void unbindAllHats(uint32_t type);
|
|
||||||
|
|
||||||
QStringList connectedGamepads(uint32_t type) const;
|
QStringList connectedGamepads(uint32_t type) const;
|
||||||
int gamepad(uint32_t type) const;
|
int gamepad(uint32_t type) const;
|
||||||
void setGamepad(uint32_t type, int index);
|
void setGamepad(uint32_t type, int index);
|
||||||
void setPreferredGamepad(uint32_t type, int index);
|
void setPreferredGamepad(uint32_t type, int index);
|
||||||
|
|
||||||
|
InputMapper mapper(uint32_t type);
|
||||||
|
|
||||||
void registerTiltAxisX(int axis);
|
void registerTiltAxisX(int axis);
|
||||||
void registerTiltAxisY(int axis);
|
void registerTiltAxisY(int axis);
|
||||||
void registerGyroAxisX(int axis);
|
void registerGyroAxisX(int axis);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "InputProfile.h"
|
#include "InputProfile.h"
|
||||||
|
|
||||||
|
#include "input/InputMapper.h"
|
||||||
#include "InputController.h"
|
#include "InputController.h"
|
||||||
|
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
@ -210,12 +211,13 @@ const InputProfile* InputProfile::findProfile(const QString& name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputProfile::apply(InputController* controller) const {
|
void InputProfile::apply(InputController* controller) const {
|
||||||
for (size_t i = 0; i < GBA_KEY_MAX; ++i) {
|
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
controller->bindKey(SDL_BINDING_BUTTON, m_keys[i], static_cast<GBAKey>(i));
|
InputMapper mapper = controller->mapper(SDL_BINDING_BUTTON);
|
||||||
controller->bindAxis(SDL_BINDING_BUTTON, m_axes[i].axis, m_axes[i].direction, static_cast<GBAKey>(i));
|
for (size_t i = 0; i < GBA_KEY_MAX; ++i) {
|
||||||
#endif
|
mapper.bindKey(m_keys[i], static_cast<GBAKey>(i));
|
||||||
|
mapper.bindAxis(m_axes[i].axis, m_axes[i].direction, static_cast<GBAKey>(i));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
controller->registerTiltAxisX(m_tiltAxis.x);
|
controller->registerTiltAxisX(m_tiltAxis.x);
|
||||||
controller->registerTiltAxisY(m_tiltAxis.y);
|
controller->registerTiltAxisY(m_tiltAxis.y);
|
||||||
controller->registerGyroAxisX(m_gyroAxis.x);
|
controller->registerGyroAxisX(m_gyroAxis.x);
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
/* Copyright (c) 2013-2023 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#include "input/InputMapper.h"
|
||||||
|
|
||||||
|
#include <mgba/core/input.h>
|
||||||
|
|
||||||
|
using namespace QGBA;
|
||||||
|
|
||||||
|
InputMapper::InputMapper(mInputMap* map, uint32_t type)
|
||||||
|
: m_map(map)
|
||||||
|
, m_type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputMapper::mapKey(int key) {
|
||||||
|
return mInputMapKey(m_map, m_type, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputMapper::mapAxis(int axis, int16_t value) {
|
||||||
|
return mInputMapAxis(m_map, m_type, axis, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputMapper::mapHat(int hat, GamepadHatEvent::Direction direction) {
|
||||||
|
return mInputMapHat(m_map, m_type, hat, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMapper::bindKey(int key, int platformKey) {
|
||||||
|
mInputBindKey(m_map, m_type, key, platformKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMapper::bindAxis(int axis, GamepadAxisEvent::Direction direction, int platformKey) {
|
||||||
|
const mInputAxis* old = mInputQueryAxis(m_map, m_type, axis);
|
||||||
|
mInputAxis description = { -1, -1, -axisThreshold(axis), axisThreshold(axis) };
|
||||||
|
if (old) {
|
||||||
|
description = *old;
|
||||||
|
}
|
||||||
|
switch (direction) {
|
||||||
|
case GamepadAxisEvent::NEGATIVE:
|
||||||
|
description.lowDirection = platformKey;
|
||||||
|
description.deadLow = axisCenter(axis) - axisThreshold(axis);
|
||||||
|
break;
|
||||||
|
case GamepadAxisEvent::POSITIVE:
|
||||||
|
description.highDirection = platformKey;
|
||||||
|
description.deadHigh = axisCenter(axis) + axisThreshold(axis);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInputBindAxis(m_map, m_type, axis, &description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMapper::bindHat(int hat, GamepadHatEvent::Direction direction, int platformKey) {
|
||||||
|
mInputHatBindings bindings{ -1, -1, -1, -1 };
|
||||||
|
mInputQueryHat(m_map, m_type, hat, &bindings);
|
||||||
|
switch (direction) {
|
||||||
|
case GamepadHatEvent::UP:
|
||||||
|
bindings.up = platformKey;
|
||||||
|
break;
|
||||||
|
case GamepadHatEvent::RIGHT:
|
||||||
|
bindings.right = platformKey;
|
||||||
|
break;
|
||||||
|
case GamepadHatEvent::DOWN:
|
||||||
|
bindings.down = platformKey;
|
||||||
|
break;
|
||||||
|
case GamepadHatEvent::LEFT:
|
||||||
|
bindings.left = platformKey;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInputBindHat(m_map, m_type, hat, &bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<int> InputMapper::queryKeyBindings(int platformKey) const {
|
||||||
|
return {mInputQueryBinding(m_map, m_type, platformKey)};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QPair<int, GamepadAxisEvent::Direction>> InputMapper::queryAxisBindings(int platformKey) const {
|
||||||
|
QPair<int, QSet<QPair<int, GamepadAxisEvent::Direction>>> userdata;
|
||||||
|
userdata.first = platformKey;
|
||||||
|
|
||||||
|
mInputEnumerateAxes(m_map, m_type, [](int axis, const struct mInputAxis* description, void* user) {
|
||||||
|
auto userdata = static_cast<QPair<int, QSet<QPair<int, GamepadAxisEvent::Direction>>>*>(user);
|
||||||
|
int platformKey = userdata->first;
|
||||||
|
auto& bindings = userdata->second;
|
||||||
|
|
||||||
|
if (description->lowDirection == platformKey) {
|
||||||
|
bindings.insert({axis, GamepadAxisEvent::NEGATIVE});
|
||||||
|
}
|
||||||
|
if (description->highDirection == platformKey) {
|
||||||
|
bindings.insert({axis, GamepadAxisEvent::POSITIVE});
|
||||||
|
}
|
||||||
|
}, &userdata);
|
||||||
|
|
||||||
|
return userdata.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QPair<int, GamepadHatEvent::Direction>> InputMapper::queryHatBindings(int platformKey) const {
|
||||||
|
QPair<int, QSet<QPair<int, GamepadHatEvent::Direction>>> userdata;
|
||||||
|
userdata.first = platformKey;
|
||||||
|
|
||||||
|
mInputEnumerateHats(m_map, m_type, [](int hat, const struct mInputHatBindings* description, void* user) {
|
||||||
|
auto userdata = static_cast<QPair<int, QSet<QPair<int, GamepadHatEvent::Direction>>>*>(user);
|
||||||
|
int platformKey = userdata->first;
|
||||||
|
auto& bindings = userdata->second;
|
||||||
|
|
||||||
|
if (description->up == platformKey) {
|
||||||
|
bindings.insert({hat, GamepadHatEvent::UP});
|
||||||
|
}
|
||||||
|
if (description->right == platformKey) {
|
||||||
|
bindings.insert({hat, GamepadHatEvent::RIGHT});
|
||||||
|
}
|
||||||
|
if (description->down == platformKey) {
|
||||||
|
bindings.insert({hat, GamepadHatEvent::DOWN});
|
||||||
|
}
|
||||||
|
if (description->left == platformKey) {
|
||||||
|
bindings.insert({hat, GamepadHatEvent::LEFT});
|
||||||
|
}
|
||||||
|
}, &userdata);
|
||||||
|
|
||||||
|
return userdata.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMapper::unbindAllKeys() {
|
||||||
|
mInputUnbindAllKeys(m_map, m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMapper::unbindAllAxes() {
|
||||||
|
mInputUnbindAllAxes(m_map, m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMapper::unbindAllHats() {
|
||||||
|
mInputUnbindAllHats(m_map, m_type);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* Copyright (c) 2013-2023 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QPair>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
|
#include "GamepadAxisEvent.h"
|
||||||
|
#include "GamepadHatEvent.h"
|
||||||
|
|
||||||
|
struct mInputMap;
|
||||||
|
|
||||||
|
namespace QGBA {
|
||||||
|
|
||||||
|
class InputMapper final {
|
||||||
|
public:
|
||||||
|
static const int32_t DEFAULT_AXIS_THRESHOLD = 0x3000;
|
||||||
|
|
||||||
|
InputMapper(mInputMap* map, uint32_t type);
|
||||||
|
|
||||||
|
mInputMap* inputMap() const { return m_map; }
|
||||||
|
uint32_t type() const { return m_type; }
|
||||||
|
|
||||||
|
int mapKey(int key);
|
||||||
|
int mapAxis(int axis, int16_t value);
|
||||||
|
int mapHat(int hat, GamepadHatEvent::Direction);
|
||||||
|
|
||||||
|
void bindKey(int key, int platformKey);
|
||||||
|
void bindAxis(int axis, GamepadAxisEvent::Direction, int platformKey);
|
||||||
|
void bindHat(int hat, GamepadHatEvent::Direction, int platformKey);
|
||||||
|
|
||||||
|
QSet<int> queryKeyBindings(int platformKey) const;
|
||||||
|
QSet<QPair<int, GamepadAxisEvent::Direction>> queryAxisBindings(int platformKey) const;
|
||||||
|
QSet<QPair<int, GamepadHatEvent::Direction>> queryHatBindings(int platformKey) const;
|
||||||
|
|
||||||
|
int16_t axisThreshold(int) const { return DEFAULT_AXIS_THRESHOLD; }
|
||||||
|
int16_t axisCenter(int) const { return 0; }
|
||||||
|
|
||||||
|
void unbindAllKeys();
|
||||||
|
void unbindAllAxes();
|
||||||
|
void unbindAllHats();
|
||||||
|
|
||||||
|
private:
|
||||||
|
mInputMap* m_map;
|
||||||
|
uint32_t m_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue