Qt: Start splitting up InputController

This commit is contained in:
Vicki Pfau 2023-01-16 23:55:52 -08:00
parent 1584023f34
commit be3022156f
7 changed files with 210 additions and 77 deletions

View File

@ -107,6 +107,7 @@ set(SOURCE_FILES
GamepadButtonEvent.cpp
GamepadHatEvent.cpp
IOViewer.cpp
input/InputMapper.cpp
InputController.cpp
InputProfile.cpp
KeyEditor.cpp

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
};
}