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
|
||||
GamepadHatEvent.cpp
|
||||
IOViewer.cpp
|
||||
input/InputMapper.cpp
|
||||
InputController.cpp
|
||||
InputProfile.cpp
|
||||
KeyEditor.cpp
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "input/InputMapper.h"
|
||||
#include "InputController.h"
|
||||
#include "KeyEditor.h"
|
||||
|
||||
|
@ -214,8 +215,9 @@ void GBAKeyEditor::setNext() {
|
|||
|
||||
void GBAKeyEditor::save() {
|
||||
#ifdef BUILD_SDL
|
||||
m_controller->unbindAllAxes(m_type);
|
||||
m_controller->unbindAllHats(m_type);
|
||||
InputMapper mapper = m_controller->mapper(m_type);
|
||||
mapper.unbindAllAxes();
|
||||
mapper.unbindAllHats();
|
||||
#endif
|
||||
|
||||
bindKey(m_keyDU, GBA_KEY_UP);
|
||||
|
@ -324,15 +326,16 @@ void GBAKeyEditor::lookupHats(const mInputMap* map) {
|
|||
#endif
|
||||
|
||||
void GBAKeyEditor::bindKey(const KeyEditor* keyEditor, GBAKey key) {
|
||||
InputMapper mapper = m_controller->mapper(m_type);
|
||||
#ifdef BUILD_SDL
|
||||
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) {
|
||||
m_controller->bindHat(m_type, keyEditor->hat(), keyEditor->hatDirection(), key);
|
||||
mapper.bindHat(keyEditor->hat(), keyEditor->hatDirection(), key);
|
||||
}
|
||||
#endif
|
||||
m_controller->bindKey(m_type, keyEditor->value(), key);
|
||||
mapper.bindKey(keyEditor->value(), key);
|
||||
}
|
||||
|
||||
bool GBAKeyEditor::findFocus(KeyEditor* needle) {
|
||||
|
|
|
@ -301,6 +301,10 @@ void InputController::setPreferredGamepad(uint32_t type, int index) {
|
|||
#endif
|
||||
}
|
||||
|
||||
InputMapper InputController::mapper(uint32_t type) {
|
||||
return InputMapper(&m_inputMap, type);
|
||||
}
|
||||
|
||||
mRumble* InputController::rumble() {
|
||||
#ifdef BUILD_SDL
|
||||
#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));
|
||||
}
|
||||
|
||||
void InputController::bindKey(uint32_t type, int key, GBAKey gbaKey) {
|
||||
return mInputBindKey(&m_inputMap, type, key, gbaKey);
|
||||
}
|
||||
|
||||
void InputController::updateJoysticks() {
|
||||
#ifdef BUILD_SDL
|
||||
QString profile = profileForType(SDL_BINDING_BUTTON);
|
||||
|
@ -501,36 +501,6 @@ QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes
|
|||
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>> activeHats;
|
||||
#ifdef BUILD_SDL
|
||||
|
@ -563,32 +533,6 @@ QSet<QPair<int, GamepadHatEvent::Direction>> InputController::activeGamepadHats(
|
|||
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) {
|
||||
QWriteLocker l(&m_eventsLock);
|
||||
auto activeAxes = activeGamepadAxes(type);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "GamepadHatEvent.h"
|
||||
#include "input/InputMapper.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QMutex>
|
||||
|
@ -64,8 +65,6 @@ public:
|
|||
|
||||
GBAKey mapKeyboard(int key) const;
|
||||
|
||||
void bindKey(uint32_t type, int key, GBAKey);
|
||||
|
||||
const mInputMap* map() const { return &m_inputMap; }
|
||||
|
||||
int pollEvents();
|
||||
|
@ -76,17 +75,13 @@ public:
|
|||
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
|
||||
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;
|
||||
int gamepad(uint32_t type) const;
|
||||
void setGamepad(uint32_t type, int index);
|
||||
void setPreferredGamepad(uint32_t type, int index);
|
||||
|
||||
InputMapper mapper(uint32_t type);
|
||||
|
||||
void registerTiltAxisX(int axis);
|
||||
void registerTiltAxisY(int axis);
|
||||
void registerGyroAxisX(int axis);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "InputProfile.h"
|
||||
|
||||
#include "input/InputMapper.h"
|
||||
#include "InputController.h"
|
||||
|
||||
#include <QRegExp>
|
||||
|
@ -210,12 +211,13 @@ const InputProfile* InputProfile::findProfile(const QString& name) {
|
|||
}
|
||||
|
||||
void InputProfile::apply(InputController* controller) const {
|
||||
for (size_t i = 0; i < GBA_KEY_MAX; ++i) {
|
||||
#ifdef BUILD_SDL
|
||||
controller->bindKey(SDL_BINDING_BUTTON, m_keys[i], static_cast<GBAKey>(i));
|
||||
controller->bindAxis(SDL_BINDING_BUTTON, m_axes[i].axis, m_axes[i].direction, static_cast<GBAKey>(i));
|
||||
#endif
|
||||
InputMapper mapper = controller->mapper(SDL_BINDING_BUTTON);
|
||||
for (size_t i = 0; i < GBA_KEY_MAX; ++i) {
|
||||
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->registerTiltAxisY(m_tiltAxis.y);
|
||||
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