mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
38c51308c3
|
@ -55,6 +55,7 @@ int mInputMapKeyBits(const struct mInputMap* map, uint32_t type, uint32_t bits,
|
|||
void mInputBindKey(struct mInputMap*, uint32_t type, int key, int input);
|
||||
int mInputQueryBinding(const struct mInputMap*, uint32_t type, int input);
|
||||
void mInputUnbindKey(struct mInputMap*, uint32_t type, int input);
|
||||
void mInputUnbindAllKeys(struct mInputMap*, uint32_t type);
|
||||
|
||||
int mInputMapAxis(const struct mInputMap*, uint32_t type, int axis, int value);
|
||||
int mInputClearAxis(const struct mInputMap*, uint32_t type, int axis, int keys);
|
||||
|
@ -69,6 +70,7 @@ void mInputBindHat(struct mInputMap*, uint32_t type, int id, const struct mInput
|
|||
bool mInputQueryHat(const struct mInputMap*, uint32_t type, int id, struct mInputHatBindings* bindings);
|
||||
void mInputUnbindHat(struct mInputMap*, uint32_t type, int id);
|
||||
void mInputUnbindAllHats(struct mInputMap*, uint32_t type);
|
||||
void mInputEnumerateHats(const struct mInputMap*, uint32_t type, void (handler(int hat, const struct mInputHatBindings* bindings, void* user)), void* user);
|
||||
|
||||
bool mInputMapLoad(struct mInputMap*, uint32_t type, const struct Configuration*);
|
||||
void mInputMapSave(const struct mInputMap*, uint32_t type, struct Configuration*);
|
||||
|
|
|
@ -38,6 +38,11 @@ struct mInputAxisEnumerate {
|
|||
void* user;
|
||||
};
|
||||
|
||||
struct mInputHatEnumerate {
|
||||
void (*handler)(int axis, const struct mInputHatBindings* bindings, void* user);
|
||||
void* user;
|
||||
};
|
||||
|
||||
static void _makeSectionName(const char* platform, char* sectionName, size_t len, uint32_t type) {
|
||||
snprintf(sectionName, len, "%s.input.%c%c%c%c", platform, type >> 24, type >> 16, type >> 8, type);
|
||||
sectionName[len - 1] = '\0';
|
||||
|
@ -304,6 +309,12 @@ void _unbindAxis(uint32_t axis, void* dp, void* user) {
|
|||
}
|
||||
}
|
||||
|
||||
void _enumerateHat(uint32_t axis, void* dp, void* ep) {
|
||||
struct mInputHatEnumerate* enumUser = ep;
|
||||
const struct mInputHatBindings* description = dp;
|
||||
enumUser->handler(axis, description, enumUser->user);
|
||||
}
|
||||
|
||||
static bool _loadAll(struct mInputMap* map, uint32_t type, const char* sectionName, const struct Configuration* config) {
|
||||
if (!ConfigurationHasSection(config, sectionName)) {
|
||||
return false;
|
||||
|
@ -415,6 +426,16 @@ void mInputUnbindKey(struct mInputMap* map, uint32_t type, int input) {
|
|||
}
|
||||
}
|
||||
|
||||
void mInputUnbindAllKeys(struct mInputMap* map, uint32_t type) {
|
||||
struct mInputMapImpl* impl = _lookupMap(map, type);
|
||||
if (impl) {
|
||||
size_t i;
|
||||
for (i = 0; i < map->info->nKeys; ++i) {
|
||||
impl->map[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mInputQueryBinding(const struct mInputMap* map, uint32_t type, int input) {
|
||||
if (input < 0 || (size_t) input >= map->info->nKeys) {
|
||||
return -1;
|
||||
|
@ -578,6 +599,18 @@ void mInputUnbindAllHats(struct mInputMap* map, uint32_t type) {
|
|||
}
|
||||
}
|
||||
|
||||
void mInputEnumerateHats(const struct mInputMap* map, uint32_t type, void (handler(int hat, const struct mInputHatBindings* bindings, void* user)), void* user) {
|
||||
const struct mInputMapImpl* impl = _lookupMapConst(map, type);
|
||||
if (!impl) {
|
||||
return;
|
||||
}
|
||||
struct mInputHatEnumerate enumUser = {
|
||||
handler,
|
||||
user
|
||||
};
|
||||
TableEnumerate(&impl->axes, _enumerateHat, &enumUser);
|
||||
}
|
||||
|
||||
bool mInputMapLoad(struct mInputMap* map, uint32_t type, const struct Configuration* config) {
|
||||
char sectionName[SECTION_NAME_MAX];
|
||||
_makeSectionName(map->info->platformName, sectionName, SECTION_NAME_MAX, type);
|
||||
|
|
|
@ -103,9 +103,6 @@ set(SOURCE_FILES
|
|||
FrameView.cpp
|
||||
GBAApp.cpp
|
||||
GIFView.cpp
|
||||
GamepadAxisEvent.cpp
|
||||
GamepadButtonEvent.cpp
|
||||
GamepadHatEvent.cpp
|
||||
IOViewer.cpp
|
||||
KeyEditor.cpp
|
||||
LoadSaveState.cpp
|
||||
|
@ -145,11 +142,19 @@ set(SOURCE_FILES
|
|||
VFileDevice.cpp
|
||||
VideoProxy.cpp
|
||||
VideoView.cpp
|
||||
input/Gamepad.cpp
|
||||
input/GamepadAxisEvent.cpp
|
||||
input/GamepadButtonEvent.cpp
|
||||
input/GamepadHatEvent.cpp
|
||||
input/InputController.cpp
|
||||
input/InputDriver.cpp
|
||||
input/InputIndex.cpp
|
||||
input/InputItem.cpp
|
||||
input/InputMapper.cpp
|
||||
input/InputModel.cpp
|
||||
input/InputProfile.cpp)
|
||||
input/InputProfile.cpp
|
||||
input/InputSource.cpp
|
||||
input/KeySource.cpp)
|
||||
|
||||
set(UI_FILES
|
||||
AboutScreen.ui
|
||||
|
@ -201,6 +206,7 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libqt5widgets5
|
|||
|
||||
set(AUDIO_SRC)
|
||||
if(BUILD_SDL)
|
||||
list(APPEND SOURCE_FILES input/SDLInputDriver.cpp)
|
||||
list(APPEND AUDIO_SRC AudioProcessorSDL.cpp)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -420,7 +420,6 @@ void CoreController::setOverride(std::unique_ptr<Override> override) {
|
|||
|
||||
void CoreController::setInputController(InputController* inputController) {
|
||||
m_inputController = inputController;
|
||||
m_inputController->setPlatform(platform());
|
||||
m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_ROTATION, m_inputController->rotationSource());
|
||||
m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_RUMBLE, m_inputController->rumble());
|
||||
m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_IMAGE_SOURCE, m_inputController->imageSource());
|
||||
|
@ -1159,7 +1158,7 @@ void CoreController::setFramebufferHandle(int fb) {
|
|||
}
|
||||
|
||||
void CoreController::updateKeys() {
|
||||
int polledKeys = m_inputController->pollEvents() | m_inputController->updateAutofire();
|
||||
int polledKeys = m_inputController->pollEvents();
|
||||
int activeKeys = m_activeKeys | polledKeys;
|
||||
activeKeys |= m_threadContext.core->getKeys(m_threadContext.core) & ~m_removedKeys;
|
||||
m_removedKeys = polledKeys;
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include "DiscordCoordinator.h"
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "input/SDLInputDriver.h"
|
||||
#endif
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
static GBAApp* g_app = nullptr;
|
||||
|
@ -309,6 +313,25 @@ bool GBAApp::waitOnJob(qint64 jobId, QObject* context, std::function<void ()> ca
|
|||
return true;
|
||||
}
|
||||
|
||||
void GBAApp::suspendScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
SDL::suspendScreensaver();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAApp::resumeScreensaver() {
|
||||
#ifdef BUILD_SDL
|
||||
SDL::resumeScreensaver();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAApp::setScreensaverSuspendable(bool suspendable) {
|
||||
UNUSED(suspendable);
|
||||
#ifdef BUILD_SDL
|
||||
SDL::setScreensaverSuspendable(suspendable);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAApp::cleanupAfterUpdate() {
|
||||
// Remove leftover updater if there's one present
|
||||
QDir configDir(ConfigController::configDir());
|
||||
|
|
|
@ -86,6 +86,10 @@ public slots:
|
|||
void restartForUpdate();
|
||||
Window* newWindow();
|
||||
|
||||
void suspendScreensaver();
|
||||
void resumeScreensaver();
|
||||
void setScreensaverSuspendable(bool);
|
||||
|
||||
signals:
|
||||
void jobFinished(qint64 jobId);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -260,7 +262,7 @@ void GBAKeyEditor::refresh() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void GBAKeyEditor::lookupBinding(const mInputMap* map, KeyEditor* keyEditor, GBAKey key) {
|
||||
void GBAKeyEditor::lookupBinding(const mInputMap* map, KeyEditor* keyEditor, int key) {
|
||||
#ifdef BUILD_SDL
|
||||
if (m_type == SDL_BINDING_BUTTON) {
|
||||
int value = mInputQueryBinding(map, m_type, key);
|
||||
|
@ -275,14 +277,14 @@ void GBAKeyEditor::lookupBinding(const mInputMap* map, KeyEditor* keyEditor, GBA
|
|||
void GBAKeyEditor::lookupAxes(const mInputMap* map) {
|
||||
mInputEnumerateAxes(map, m_type, [](int axis, const mInputAxis* description, void* user) {
|
||||
GBAKeyEditor* self = static_cast<GBAKeyEditor*>(user);
|
||||
if (description->highDirection != GBA_KEY_NONE) {
|
||||
KeyEditor* key = self->keyById(static_cast<enum GBAKey>(description->highDirection));
|
||||
if (description->highDirection != -1) {
|
||||
KeyEditor* key = self->keyById(description->highDirection);
|
||||
if (key) {
|
||||
key->setValueAxis(axis, GamepadAxisEvent::POSITIVE);
|
||||
}
|
||||
}
|
||||
if (description->lowDirection != GBA_KEY_NONE) {
|
||||
KeyEditor* key = self->keyById(static_cast<enum GBAKey>(description->lowDirection));
|
||||
if (description->lowDirection != -1) {
|
||||
KeyEditor* key = self->keyById(description->lowDirection);
|
||||
if (key) {
|
||||
key->setValueAxis(axis, GamepadAxisEvent::NEGATIVE);
|
||||
}
|
||||
|
@ -295,25 +297,25 @@ void GBAKeyEditor::lookupHats(const mInputMap* map) {
|
|||
int i = 0;
|
||||
while (mInputQueryHat(map, m_type, i, &bindings)) {
|
||||
if (bindings.up >= 0) {
|
||||
KeyEditor* key = keyById(static_cast<enum GBAKey>(bindings.up));
|
||||
KeyEditor* key = keyById(bindings.up);
|
||||
if (key) {
|
||||
key->setValueHat(i, GamepadHatEvent::UP);
|
||||
}
|
||||
}
|
||||
if (bindings.right >= 0) {
|
||||
KeyEditor* key = keyById(static_cast<enum GBAKey>(bindings.right));
|
||||
KeyEditor* key = keyById(bindings.right);
|
||||
if (key) {
|
||||
key->setValueHat(i, GamepadHatEvent::RIGHT);
|
||||
}
|
||||
}
|
||||
if (bindings.down >= 0) {
|
||||
KeyEditor* key = keyById(static_cast<enum GBAKey>(bindings.down));
|
||||
KeyEditor* key = keyById(bindings.down);
|
||||
if (key) {
|
||||
key->setValueHat(i, GamepadHatEvent::DOWN);
|
||||
}
|
||||
}
|
||||
if (bindings.left >= 0) {
|
||||
KeyEditor* key = keyById(static_cast<enum GBAKey>(bindings.left));
|
||||
KeyEditor* key = keyById(bindings.left);
|
||||
if (key) {
|
||||
key->setValueHat(i, GamepadHatEvent::LEFT);
|
||||
}
|
||||
|
@ -323,16 +325,17 @@ void GBAKeyEditor::lookupHats(const mInputMap* map) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void GBAKeyEditor::bindKey(const KeyEditor* keyEditor, GBAKey key) {
|
||||
void GBAKeyEditor::bindKey(const KeyEditor* keyEditor, int 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) {
|
||||
|
@ -358,7 +361,7 @@ void GBAKeyEditor::selectGamepad(int index) {
|
|||
}
|
||||
#endif
|
||||
|
||||
KeyEditor* GBAKeyEditor::keyById(GBAKey key) {
|
||||
KeyEditor* GBAKeyEditor::keyById(int key) {
|
||||
switch (key) {
|
||||
case GBA_KEY_UP:
|
||||
return m_keyDU;
|
||||
|
@ -395,14 +398,13 @@ void GBAKeyEditor::setLocation(QWidget* widget, qreal x, qreal y) {
|
|||
|
||||
#ifdef BUILD_SDL
|
||||
void GBAKeyEditor::updateJoysticks() {
|
||||
m_controller->updateJoysticks();
|
||||
m_controller->recalibrateAxes();
|
||||
m_controller->update();
|
||||
|
||||
// Block the currentIndexChanged signal while rearranging the combo box
|
||||
auto wasBlocked = m_profileSelect->blockSignals(true);
|
||||
m_profileSelect->clear();
|
||||
m_profileSelect->addItems(m_controller->connectedGamepads(m_type));
|
||||
int activeGamepad = m_controller->gamepad(m_type);
|
||||
int activeGamepad = m_controller->gamepadIndex(m_type);
|
||||
m_profileSelect->setCurrentIndex(activeGamepad);
|
||||
m_profileSelect->blockSignals(wasBlocked);
|
||||
|
||||
|
|
|
@ -54,8 +54,8 @@ private:
|
|||
|
||||
void setLocation(QWidget* widget, qreal x, qreal y);
|
||||
|
||||
void lookupBinding(const mInputMap*, KeyEditor*, GBAKey);
|
||||
void bindKey(const KeyEditor*, GBAKey);
|
||||
void lookupBinding(const mInputMap*, KeyEditor*, int key);
|
||||
void bindKey(const KeyEditor*, int key);
|
||||
|
||||
bool findFocus(KeyEditor* needle = nullptr);
|
||||
|
||||
|
@ -64,7 +64,7 @@ private:
|
|||
void lookupHats(const mInputMap*);
|
||||
#endif
|
||||
|
||||
KeyEditor* keyById(GBAKey);
|
||||
KeyEditor* keyById(int);
|
||||
|
||||
QComboBox* m_profileSelect = nullptr;
|
||||
QWidget* m_clear = nullptr;
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "KeyEditor.h"
|
||||
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "GamepadButtonEvent.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
#include "InputIndex.h"
|
||||
#include "ShortcutController.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFontMetrics>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "GamepadHatEvent.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
#include "input/GamepadHatEvent.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QTimer>
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#include "LoadSaveState.h"
|
||||
|
||||
#include "CoreController.h"
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "GamepadButtonEvent.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
#include "VFileDevice.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include <QPainter>
|
||||
|
||||
#include <mgba/core/serialize.h>
|
||||
#include <mgba/internal/gba/input.h>
|
||||
#include <mgba-util/memory.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
|
@ -131,13 +132,13 @@ bool LoadSaveState::eventFilter(QObject* object, QEvent* event) {
|
|||
if (event->type() == GamepadButtonEvent::Down() || event->type() == GamepadAxisEvent::Type()) {
|
||||
int column = m_currentFocus % 3;
|
||||
int row = m_currentFocus - column;
|
||||
GBAKey key = GBA_KEY_NONE;
|
||||
int key = -1;
|
||||
if (event->type() == GamepadButtonEvent::Down()) {
|
||||
key = static_cast<GamepadButtonEvent*>(event)->gbaKey();
|
||||
key = static_cast<GamepadButtonEvent*>(event)->platformKey();
|
||||
} else if (event->type() == GamepadAxisEvent::Type()) {
|
||||
GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
|
||||
if (gae->isNew()) {
|
||||
key = gae->gbaKey();
|
||||
key = gae->platformKey();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -314,10 +314,8 @@ void ReportView::generateReport() {
|
|||
} else {
|
||||
windowReport << QString("ROM open: No");
|
||||
}
|
||||
#ifdef BUILD_SDL
|
||||
InputController* input = window->inputController();
|
||||
windowReport << QString("Active gamepad: %1").arg(input->gamepad(SDL_BINDING_BUTTON));
|
||||
#endif
|
||||
windowReport << QString("Active gamepad: %1").arg(input->gamepadIndex());
|
||||
windowReport << QString("Configuration: %1").arg(configs.indexOf(config) + 1);
|
||||
addReport(QString("Window %1").arg(winId), windowReport.join('\n'));
|
||||
}
|
||||
|
@ -477,9 +475,8 @@ void ReportView::addGLInfo(QStringList& report) {
|
|||
}
|
||||
|
||||
void ReportView::addGamepadInfo(QStringList& report) {
|
||||
#ifdef BUILD_SDL
|
||||
InputController* input = GBAApp::app()->windows()[0]->inputController();
|
||||
QStringList gamepads = input->connectedGamepads(SDL_BINDING_BUTTON);
|
||||
QStringList gamepads = input->connectedGamepads();
|
||||
report << QString("Connected gamepads: %1").arg(gamepads.size());
|
||||
int i = 0;
|
||||
for (const auto& gamepad : gamepads) {
|
||||
|
@ -490,10 +487,9 @@ void ReportView::addGamepadInfo(QStringList& report) {
|
|||
i = 0;
|
||||
for (Window* window : GBAApp::app()->windows()) {
|
||||
++i;
|
||||
report << QString("Window %1 gamepad: %2").arg(i).arg(window->inputController()->gamepad(SDL_BINDING_BUTTON));
|
||||
report << QString("Window %1 gamepad: %2").arg(i).arg(window->inputController()->gamepadIndex());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ReportView::addROMInfo(QStringList& report, CoreController* controller) {
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include "SensorView.h"
|
||||
|
||||
#include "CoreController.h"
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
#include "input/InputDriver.h"
|
||||
#include "InputController.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -47,14 +48,20 @@ SensorView::SensorView(InputController* input, QWidget* parent)
|
|||
m_timer.start();
|
||||
}
|
||||
|
||||
jiggerer(m_ui.tiltSetX, &InputController::registerTiltAxisX);
|
||||
jiggerer(m_ui.tiltSetY, &InputController::registerTiltAxisY);
|
||||
jiggerer(m_ui.gyroSetX, &InputController::registerGyroAxisX);
|
||||
jiggerer(m_ui.gyroSetY, &InputController::registerGyroAxisY);
|
||||
jiggerer(m_ui.tiltSetX, &InputDriver::registerTiltAxisX);
|
||||
jiggerer(m_ui.tiltSetY, &InputDriver::registerTiltAxisY);
|
||||
jiggerer(m_ui.gyroSetX, &InputDriver::registerGyroAxisX);
|
||||
jiggerer(m_ui.gyroSetY, &InputDriver::registerGyroAxisY);
|
||||
|
||||
m_ui.gyroSensitivity->setValue(m_input->gyroSensitivity() / 1e8f);
|
||||
InputDriver* sensorDriver = m_input->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
m_ui.gyroSensitivity->setValue(sensorDriver->gyroSensitivity() / 1e8f);
|
||||
}
|
||||
connect(m_ui.gyroSensitivity, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {
|
||||
m_input->setGyroSensitivity(value * 1e8f);
|
||||
InputDriver* sensorDriver = m_input->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
sensorDriver->setGyroSensitivity(value * 1e8f);
|
||||
}
|
||||
});
|
||||
m_input->stealFocus(this);
|
||||
connect(m_input, &InputController::luminanceValueChanged, this, &SensorView::luminanceValueChanged);
|
||||
|
@ -84,7 +91,7 @@ void SensorView::setController(std::shared_ptr<CoreController> controller) {
|
|||
});
|
||||
}
|
||||
|
||||
void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
|
||||
void SensorView::jiggerer(QAbstractButton* button, void (InputDriver::*setter)(int)) {
|
||||
connect(button, &QAbstractButton::toggled, [this, button, setter](bool checked) {
|
||||
if (!checked) {
|
||||
m_button = nullptr;
|
||||
|
@ -115,7 +122,10 @@ bool SensorView::eventFilter(QObject*, QEvent* event) {
|
|||
m_button->removeEventFilter(this);
|
||||
m_button->clearFocus();
|
||||
m_button->setChecked(false);
|
||||
(m_input->*m_setter)(gae->axis());
|
||||
InputDriver* sensorDriver = m_input->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
(sensorDriver->*m_setter)(gae->axis());
|
||||
}
|
||||
m_button = nullptr;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -21,6 +21,7 @@ class ConfigController;
|
|||
class CoreController;
|
||||
class GamepadAxisEvent;
|
||||
class InputController;
|
||||
class InputDriver;
|
||||
|
||||
class SensorView : public QDialog {
|
||||
Q_OBJECT
|
||||
|
@ -43,14 +44,14 @@ private:
|
|||
Ui::SensorView m_ui;
|
||||
|
||||
QAbstractButton* m_button = nullptr;
|
||||
void (InputController::*m_setter)(int);
|
||||
void (InputDriver::*m_setter)(int);
|
||||
|
||||
std::shared_ptr<CoreController> m_controller;
|
||||
InputController* m_input;
|
||||
mRotationSource* m_rotation;
|
||||
QTimer m_timer;
|
||||
|
||||
void jiggerer(QAbstractButton*, void (InputController::*)(int));
|
||||
void jiggerer(QAbstractButton*, void (InputDriver::*)(int));
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include <mgba/core/version.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "ShortcutController.h"
|
||||
|
||||
#include "ConfigController.h"
|
||||
#include "GamepadButtonEvent.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
#include "InputProfile.h"
|
||||
|
||||
#include <QAction>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ActionMapper.h"
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "ShortcutView.h"
|
||||
|
||||
#include "GamepadButtonEvent.h"
|
||||
#include "InputController.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
#include "ShortcutController.h"
|
||||
#include "ShortcutModel.h"
|
||||
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "InputIndex.h"
|
||||
#include "InputModel.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
#include "GDBController.h"
|
||||
#include "GDBWindow.h"
|
||||
#include "GIFView.h"
|
||||
#ifdef BUILD_SDL
|
||||
#include "input/SDLInputDriver.h"
|
||||
#endif
|
||||
#include "IOViewer.h"
|
||||
#include "LoadSaveState.h"
|
||||
#include "LogView.h"
|
||||
|
@ -82,6 +85,7 @@
|
|||
#include <mgba/internal/ds/input.h>
|
||||
#endif
|
||||
#include <mgba/feature/commandline.h>
|
||||
#include <mgba/internal/gba/input.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#include <mgba-util/convolve.h>
|
||||
|
@ -193,19 +197,14 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi
|
|||
m_mustReset.setInterval(MUST_RESTART_TIMEOUT);
|
||||
m_mustReset.setSingleShot(true);
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
m_inputController.addInputDriver(std::make_shared<SDLInputDriver>(&m_inputController));
|
||||
#endif
|
||||
|
||||
m_shortcutController->setConfigController(m_config);
|
||||
m_shortcutController->setActionMapper(&m_actions);
|
||||
setupMenu(menuBar());
|
||||
|
||||
#ifdef M_CORE_GBA
|
||||
m_inputController.addPlatform(mPLATFORM_GBA, &GBAInputInfo);
|
||||
#endif
|
||||
#ifdef M_CORE_GB
|
||||
m_inputController.addPlatform(mPLATFORM_GB, &GBInputInfo);
|
||||
#endif
|
||||
#ifdef M_CORE_DS
|
||||
m_inputController.addPlatform(mPLATFORM_DS, &DSInputInfo);
|
||||
#endif
|
||||
setupOptions();
|
||||
}
|
||||
|
||||
|
@ -330,7 +329,7 @@ void Window::reloadConfig() {
|
|||
m_display->resizeContext();
|
||||
}
|
||||
|
||||
m_inputController.setScreensaverSuspendable(opts->suspendScreensaver);
|
||||
GBAApp::app()->setScreensaverSuspendable(opts->suspendScreensaver);
|
||||
}
|
||||
|
||||
void Window::saveConfig() {
|
||||
|
@ -2023,7 +2022,6 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
}
|
||||
|
||||
m_controller = std::shared_ptr<CoreController>(controller);
|
||||
m_inputController.recalibrateAxes();
|
||||
m_controller->setInputController(&m_inputController);
|
||||
m_controller->setLogger(&m_log);
|
||||
|
||||
|
@ -2036,14 +2034,14 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
});
|
||||
|
||||
connect(m_controller.get(), &CoreController::started, this, &Window::gameStarted);
|
||||
connect(m_controller.get(), &CoreController::started, &m_inputController, &InputController::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::started, GBAApp::app(), &GBAApp::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::stopping, this, &Window::gameStopped);
|
||||
{
|
||||
connect(m_controller.get(), &CoreController::stopping, [this]() {
|
||||
m_controller.reset();
|
||||
});
|
||||
}
|
||||
connect(m_controller.get(), &CoreController::stopping, &m_inputController, &InputController::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::stopping, GBAApp::app(), &GBAApp::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::paused, this, &Window::updateFrame);
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
|
@ -2055,14 +2053,14 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
});
|
||||
#endif
|
||||
|
||||
connect(m_controller.get(), &CoreController::paused, &m_inputController, &InputController::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::paused, GBAApp::app(), &GBAApp::resumeScreensaver);
|
||||
connect(m_controller.get(), &CoreController::paused, [this]() {
|
||||
emit paused(true);
|
||||
});
|
||||
connect(m_controller.get(), &CoreController::unpaused, [this]() {
|
||||
emit paused(false);
|
||||
});
|
||||
connect(m_controller.get(), &CoreController::unpaused, &m_inputController, &InputController::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::unpaused, GBAApp::app(), &GBAApp::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::frameAvailable, this, &Window::recordFrame);
|
||||
connect(m_controller.get(), &CoreController::crashed, this, &Window::gameCrashed);
|
||||
connect(m_controller.get(), &CoreController::failed, this, &Window::gameFailed);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* 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/Gamepad.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
Gamepad::Gamepad(InputDriver* driver, QObject* parent)
|
||||
: InputSource(driver, parent)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* 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 "GamepadHatEvent.h"
|
||||
#include "input/InputSource.h"
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class InputDriver;
|
||||
|
||||
class Gamepad : public InputSource {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Gamepad(InputDriver* driver, QObject* parent = nullptr);
|
||||
|
||||
virtual QList<bool> currentButtons() = 0;
|
||||
virtual QList<int16_t> currentAxes() = 0;
|
||||
virtual QList<GamepadHatEvent::Direction> currentHats() = 0;
|
||||
|
||||
virtual int buttonCount() const = 0;
|
||||
virtual int axisCount() const = 0;
|
||||
virtual int hatCount() const = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
/* 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 "GamepadAxisEvent.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
|
||||
#include "InputController.h"
|
||||
|
||||
|
@ -16,11 +16,11 @@ GamepadAxisEvent::GamepadAxisEvent(int axis, Direction direction, bool isNew, in
|
|||
, m_axis(axis)
|
||||
, m_direction(direction)
|
||||
, m_isNew(isNew)
|
||||
, m_key(GBA_KEY_NONE)
|
||||
, m_key(-1)
|
||||
{
|
||||
ignore();
|
||||
if (controller && controller->map()) {
|
||||
m_key = static_cast<GBAKey>(mInputMapAxis(controller->map(), type, axis, direction * INT_MAX));
|
||||
m_key = mInputMapAxis(controller->map(), type, axis, direction * INT_MAX);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include <QEvent>
|
||||
|
||||
#include <mgba/internal/gba/input.h>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class InputController;
|
||||
|
@ -26,7 +24,7 @@ public:
|
|||
int axis() const { return m_axis; }
|
||||
Direction direction() const { return m_direction; }
|
||||
bool isNew() const { return m_isNew; }
|
||||
GBAKey gbaKey() const { return m_key; }
|
||||
int platformKey() const { return m_key; }
|
||||
|
||||
static enum Type Type();
|
||||
|
||||
|
@ -36,7 +34,7 @@ private:
|
|||
int m_axis;
|
||||
Direction m_direction;
|
||||
bool m_isNew;
|
||||
GBAKey m_key;
|
||||
int m_key;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
/* 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 "GamepadButtonEvent.h"
|
||||
#include "input/GamepadButtonEvent.h"
|
||||
|
||||
#include "InputController.h"
|
||||
|
||||
|
@ -15,11 +15,11 @@ QEvent::Type GamepadButtonEvent::s_upType = QEvent::None;
|
|||
GamepadButtonEvent::GamepadButtonEvent(QEvent::Type pressType, int button, int type, InputController* controller)
|
||||
: QEvent(pressType)
|
||||
, m_button(button)
|
||||
, m_key(GBA_KEY_NONE)
|
||||
, m_key(-1)
|
||||
{
|
||||
ignore();
|
||||
if (controller && controller->map()) {
|
||||
m_key = static_cast<GBAKey>(mInputMapKey(controller->map(), type, button));
|
||||
m_key = mInputMapKey(controller->map(), type, button);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
/* 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
|
||||
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include <QEvent>
|
||||
|
||||
#include <mgba/internal/gba/input.h>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class InputController;
|
||||
|
@ -18,7 +16,7 @@ public:
|
|||
GamepadButtonEvent(Type pressType, int button, int type, InputController* controller = nullptr);
|
||||
|
||||
int value() const { return m_button; }
|
||||
GBAKey gbaKey() const { return m_key; }
|
||||
int platformKey() const { return m_key; }
|
||||
|
||||
static Type Down();
|
||||
static Type Up();
|
||||
|
@ -28,7 +26,7 @@ private:
|
|||
static Type s_upType;
|
||||
|
||||
int m_button;
|
||||
GBAKey m_key;
|
||||
int m_key;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||
/* 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 "GamepadHatEvent.h"
|
||||
#include "input/GamepadHatEvent.h"
|
||||
|
||||
#include "InputController.h"
|
||||
|
||||
|
@ -16,11 +16,11 @@ GamepadHatEvent::GamepadHatEvent(QEvent::Type pressType, int hatId, Direction di
|
|||
: QEvent(pressType)
|
||||
, m_hatId(hatId)
|
||||
, m_direction(direction)
|
||||
, m_key(GBA_KEY_NONE)
|
||||
, m_key(-1)
|
||||
{
|
||||
ignore();
|
||||
if (controller && controller->map()) {
|
||||
m_key = static_cast<GBAKey>(mInputMapHat(controller->map(), type, hatId, direction));
|
||||
m_key = mInputMapHat(controller->map(), type, hatId, direction);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include <QEvent>
|
||||
|
||||
#include <mgba/internal/gba/input.h>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class InputController;
|
||||
|
@ -27,7 +25,7 @@ public:
|
|||
|
||||
int hatId() const { return m_hatId; }
|
||||
Direction direction() const { return m_direction; }
|
||||
GBAKey gbaKey() const { return m_key; }
|
||||
int platformKey() const { return m_key; }
|
||||
|
||||
static Type Down();
|
||||
static Type Up();
|
||||
|
@ -38,7 +36,7 @@ private:
|
|||
|
||||
int m_hatId;
|
||||
Direction m_direction;
|
||||
GBAKey m_key;
|
||||
int m_key;
|
||||
};
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
/* 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
|
||||
|
@ -9,8 +9,14 @@
|
|||
#include "GamepadHatEvent.h"
|
||||
#include "InputIndex.h"
|
||||
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
#include "input/GamepadHatEvent.h"
|
||||
#include "input/InputDriver.h"
|
||||
#include "input/InputMapper.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QHash>
|
||||
#include <QImage>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
|
@ -23,12 +29,9 @@
|
|||
#include <mgba/core/core.h>
|
||||
#include <mgba/core/input.h>
|
||||
|
||||
#include <mgba/core/input.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_QT_MULTIMEDIA
|
||||
#include "VideoDumper.h"
|
||||
#include <QCamera>
|
||||
|
@ -37,14 +40,11 @@
|
|||
struct mRotationSource;
|
||||
struct mRumble;
|
||||
|
||||
class QCamera;
|
||||
class QMenu;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class ConfigController;
|
||||
class GameController;
|
||||
class InputItem;
|
||||
class Gamepad;
|
||||
class InputSource;
|
||||
|
||||
class InputController : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -62,14 +62,7 @@ public:
|
|||
InputController(int playerId = 0, QWidget* topLevel = nullptr, QObject* parent = nullptr);
|
||||
~InputController();
|
||||
|
||||
InputIndex* inputIndex() { return &m_inputIndex; }
|
||||
InputIndex* keyIndex() { return &m_keyIndex; }
|
||||
void rebuildIndex(const InputIndex* = nullptr);
|
||||
void rebuildKeyIndex(const InputIndex* = nullptr);
|
||||
|
||||
void addPlatform(mPlatform, const mInputPlatformInfo*);
|
||||
void setPlatform(mPlatform);
|
||||
void addKey(const QString& name);
|
||||
void addInputDriver(std::shared_ptr<InputDriver>);
|
||||
|
||||
void setConfiguration(ConfigController* config);
|
||||
void saveConfiguration();
|
||||
|
@ -77,42 +70,35 @@ public:
|
|||
bool loadProfile(uint32_t type, const QString& profile);
|
||||
void saveConfiguration(uint32_t type);
|
||||
void saveProfile(uint32_t type, const QString& profile);
|
||||
const char* profileForType(uint32_t type);
|
||||
QString profileForType(uint32_t type);
|
||||
|
||||
GBAKey mapKeyboard(int key) const;
|
||||
int mapKeyboard(int key) const;
|
||||
|
||||
void bindKey(uint32_t type, int key, GBAKey);
|
||||
|
||||
const mInputMap* map();
|
||||
mInputMap* map() { return &m_inputMap; }
|
||||
const mInputMap* map() const { return &m_inputMap; }
|
||||
|
||||
int pollEvents();
|
||||
|
||||
static const int32_t AXIS_THRESHOLD = 0x3000;
|
||||
QSet<int> activeGamepadButtons(int type);
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(int type);
|
||||
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
|
||||
void recalibrateAxes();
|
||||
|
||||
void bindKey(uint32_t type, int key, const QString&);
|
||||
void setGamepadDriver(uint32_t type);
|
||||
const InputDriver* gamepadDriver() const { return m_inputDrivers.value(m_sensorDriver).get(); }
|
||||
InputDriver* gamepadDriver() { return m_inputDrivers.value(m_sensorDriver).get(); }
|
||||
|
||||
void bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction, const QString&);
|
||||
void unbindAllAxes(uint32_t type);
|
||||
|
||||
void bindHat(uint32_t type, int hat, GamepadHatEvent::Direction, const QString&);
|
||||
void unbindAllHats(uint32_t type);
|
||||
|
||||
QStringList connectedGamepads(uint32_t type) const;
|
||||
int gamepad(uint32_t type) const;
|
||||
QStringList connectedGamepads(uint32_t type = 0) const;
|
||||
int gamepadIndex(uint32_t type = 0) const;
|
||||
void setGamepad(uint32_t type, int index);
|
||||
void setGamepad(int index);
|
||||
void setPreferredGamepad(uint32_t type, int index);
|
||||
void setPreferredGamepad(int index);
|
||||
|
||||
void registerTiltAxisX(int axis);
|
||||
void registerTiltAxisY(int axis);
|
||||
void registerGyroAxisX(int axis);
|
||||
void registerGyroAxisY(int axis);
|
||||
InputMapper mapper(uint32_t type);
|
||||
InputMapper mapper(InputDriver*);
|
||||
InputMapper mapper(InputSource*);
|
||||
|
||||
float gyroSensitivity() const;
|
||||
void setGyroSensitivity(float sensitivity);
|
||||
void setSensorDriver(uint32_t type);
|
||||
const InputDriver* sensorDriver() const { return m_inputDrivers.value(m_sensorDriver).get(); }
|
||||
InputDriver* sensorDriver() { return m_inputDrivers.value(m_sensorDriver).get(); }
|
||||
|
||||
void stealFocus(QWidget* focus);
|
||||
void releaseFocus(QWidget* focus);
|
||||
|
@ -130,15 +116,7 @@ signals:
|
|||
|
||||
public slots:
|
||||
void testGamepad(int type);
|
||||
void updateJoysticks();
|
||||
int updateAutofire();
|
||||
|
||||
void setAutofire(int key, bool enable);
|
||||
|
||||
// TODO: Move these to somewhere that makes sense
|
||||
void suspendScreensaver();
|
||||
void resumeScreensaver();
|
||||
void setScreensaverSuspendable(bool);
|
||||
void update();
|
||||
|
||||
void increaseLuminanceLevel();
|
||||
void decreaseLuminanceLevel();
|
||||
|
@ -150,9 +128,6 @@ public slots:
|
|||
|
||||
void setCamera(const QByteArray& id);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject*, QEvent*) override;
|
||||
|
||||
private slots:
|
||||
#ifdef BUILD_QT_MULTIMEDIA
|
||||
void prepareCamSettings(QCamera::Status);
|
||||
|
@ -161,18 +136,17 @@ private slots:
|
|||
void teardownCam();
|
||||
|
||||
private:
|
||||
void postPendingEvent(int key);
|
||||
void clearPendingEvent(int key);
|
||||
bool hasPendingEvent(int key) const;
|
||||
void postPendingEvent(int);
|
||||
void clearPendingEvent(int);
|
||||
bool hasPendingEvent(int) const;
|
||||
void sendGamepadEvent(QEvent*);
|
||||
void restoreModel();
|
||||
void rebindKey(const QString& key);
|
||||
|
||||
InputItem* itemForKey(const QString& key);
|
||||
int keyId(const QString& key);
|
||||
Gamepad* gamepad(uint32_t type);
|
||||
QList<Gamepad*> gamepads();
|
||||
|
||||
InputIndex m_inputIndex;
|
||||
InputIndex m_keyIndex;
|
||||
QSet<int> activeGamepadButtons(int type);
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(int type);
|
||||
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
|
||||
|
||||
struct InputControllerLux : GBALuminanceSource {
|
||||
InputController* p;
|
||||
|
@ -198,9 +172,6 @@ private:
|
|||
#endif
|
||||
|
||||
mInputMap m_inputMap;
|
||||
int m_activeKeys;
|
||||
bool m_autofireEnabled[32] = {};
|
||||
int m_autofireStatus[32] = {};
|
||||
|
||||
ConfigController* m_config = nullptr;
|
||||
int m_playerId;
|
||||
|
@ -209,17 +180,9 @@ private:
|
|||
QMap<mPlatform, const mInputPlatformInfo*> m_keyInfo;
|
||||
const mInputPlatformInfo* m_activeKeyInfo = nullptr;
|
||||
|
||||
std::unique_ptr<QMenu> m_bindings;
|
||||
std::unique_ptr<QMenu> m_autofire;
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
static int s_sdlInited;
|
||||
static mSDLEvents s_sdlEvents;
|
||||
mSDLPlayer m_sdlPlayer{};
|
||||
bool m_playerAttached = false;
|
||||
#endif
|
||||
|
||||
QVector<int> m_deadzones;
|
||||
QHash<uint32_t, std::shared_ptr<InputDriver>> m_inputDrivers;
|
||||
uint32_t m_gamepadDriver;
|
||||
uint32_t m_sensorDriver;
|
||||
|
||||
QSet<int> m_activeButtons;
|
||||
QSet<QPair<int, GamepadAxisEvent::Direction>> m_activeAxes;
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/* 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/InputDriver.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
InputDriver::InputDriver(QObject* parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
void InputDriver::loadConfiguration(ConfigController*) {
|
||||
}
|
||||
|
||||
void InputDriver::saveConfiguration(ConfigController*) {
|
||||
}
|
||||
|
||||
bool InputDriver::supportsPolling() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputDriver::supportsGamepads() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputDriver::supportsSensors() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputDriver::bindDefaults(InputController*) {
|
||||
}
|
||||
|
||||
QList<KeySource*> InputDriver::connectedKeySources() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
QList<Gamepad*> InputDriver::connectedGamepads() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
int InputDriver::activeKeySource() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int InputDriver::activeGamepad() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void InputDriver::setActiveKeySource(int) {
|
||||
}
|
||||
|
||||
void InputDriver::setActiveGamepad(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerTiltAxisX(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerTiltAxisY(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerGyroAxisX(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerGyroAxisY(int) {
|
||||
}
|
||||
|
||||
void InputDriver::registerGyroAxisZ(int) {
|
||||
}
|
||||
|
||||
float InputDriver::gyroSensitivity() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputDriver::setGyroSensitivity(float) {
|
||||
}
|
||||
|
||||
mRumble* InputDriver::rumble() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mRotationSource* InputDriver::rotationSource() {
|
||||
return nullptr;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* 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 <QList>
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
struct mRotationSource;
|
||||
struct mRumble;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class ConfigController;
|
||||
class Gamepad;
|
||||
class InputController;
|
||||
class KeySource;
|
||||
|
||||
class InputDriver : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InputDriver(QObject* parent = nullptr);
|
||||
virtual ~InputDriver() = default;
|
||||
|
||||
virtual uint32_t type() const = 0;
|
||||
virtual QString visibleName() const = 0;
|
||||
virtual QString currentProfile() const = 0;
|
||||
|
||||
virtual bool supportsPolling() const;
|
||||
virtual bool supportsGamepads() const;
|
||||
virtual bool supportsSensors() const;
|
||||
|
||||
virtual void loadConfiguration(ConfigController*);
|
||||
virtual void saveConfiguration(ConfigController*);
|
||||
|
||||
virtual void bindDefaults(InputController*);
|
||||
|
||||
virtual bool update() = 0;
|
||||
|
||||
virtual QList<KeySource*> connectedKeySources() const;
|
||||
virtual QList<Gamepad*> connectedGamepads() const;
|
||||
|
||||
virtual int activeKeySource() const;
|
||||
virtual int activeGamepad() const;
|
||||
|
||||
virtual void setActiveKeySource(int);
|
||||
virtual void setActiveGamepad(int);
|
||||
|
||||
virtual void registerTiltAxisX(int axis);
|
||||
virtual void registerTiltAxisY(int axis);
|
||||
virtual void registerGyroAxisX(int axis);
|
||||
virtual void registerGyroAxisY(int axis);
|
||||
virtual void registerGyroAxisZ(int axis);
|
||||
|
||||
virtual float gyroSensitivity() const;
|
||||
virtual void setGyroSensitivity(float sensitivity);
|
||||
|
||||
virtual mRumble* rumble();
|
||||
virtual mRotationSource* rotationSource();
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/* 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) const {
|
||||
return mInputMapKey(m_map, m_type, key);
|
||||
}
|
||||
|
||||
int InputMapper::mapAxis(int axis, int16_t value) const {
|
||||
return mInputMapAxis(m_map, m_type, axis, value);
|
||||
}
|
||||
|
||||
int InputMapper::mapHat(int hat, GamepadHatEvent::Direction direction) const {
|
||||
return mInputMapHat(m_map, m_type, hat, direction);
|
||||
}
|
||||
|
||||
int InputMapper::mapKeys(QList<bool> keys) const {
|
||||
int platformKeys = 0;
|
||||
for (int i = 0; i < keys.count(); ++i) {
|
||||
if (!keys[i]) {
|
||||
continue;
|
||||
}
|
||||
int platformKey = mInputMapKey(m_map, m_type, i);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
int InputMapper::mapKeys(QSet<int> keys) const {
|
||||
int platformKeys = 0;
|
||||
for (int key : keys) {
|
||||
int platformKey = mInputMapKey(m_map, m_type, key);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
int InputMapper::mapAxes(QList<int16_t> axes) const {
|
||||
int platformKeys = 0;
|
||||
for (int i = 0; i < axes.count(); ++i) {
|
||||
int platformKey = mInputMapAxis(m_map, m_type, i, axes[i]);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
int InputMapper::mapHats(QList<GamepadHatEvent::Direction> hats) const {
|
||||
int platformKeys = 0;
|
||||
for (int i = 0; i < hats.count(); ++i) {
|
||||
int platformKey = mInputMapHat(m_map, m_type, i, hats[i]);
|
||||
if (platformKey >= 0) {
|
||||
platformKeys |= 1 << platformKey;
|
||||
}
|
||||
}
|
||||
return platformKeys;
|
||||
}
|
||||
|
||||
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,56 @@
|
|||
/* 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) const;
|
||||
int mapAxis(int axis, int16_t value) const;
|
||||
int mapHat(int hat, GamepadHatEvent::Direction) const;
|
||||
|
||||
int mapKeys(QList<bool> keys) const;
|
||||
int mapKeys(QSet<int> keys) const;
|
||||
int mapAxes(QList<int16_t> axes) const;
|
||||
int mapHats(QList<GamepadHatEvent::Direction> hats) const;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,95 +5,271 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "InputProfile.h"
|
||||
|
||||
#include "input/InputMapper.h"
|
||||
#include "InputController.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QRegExp>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
QList<InputProfile> InputProfile::s_profiles;
|
||||
const InputProfile InputProfile::s_defaultMaps[] = {
|
||||
{
|
||||
"XInput Controller #\\d+", // XInput (Windows)
|
||||
{
|
||||
/*keyA */ 11,
|
||||
/*keyB */ 10,
|
||||
/*keySelect */ 5,
|
||||
/*keyStart */ 4,
|
||||
/*keyRight */ 3,
|
||||
/*keyLeft */ 2,
|
||||
/*keyUp */ 0,
|
||||
/*keyDown */ 1,
|
||||
/*keyR */ 9,
|
||||
/*keyL */ 8
|
||||
},
|
||||
{
|
||||
/*loadState */ 12,
|
||||
/*saveState */ 13,
|
||||
/*holdFastForward */ -1,
|
||||
/*holdRewind */ -1,
|
||||
},
|
||||
{
|
||||
/*loadState */ {GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
/*saveState */ {GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
/*holdFastForward */ {GamepadAxisEvent::Direction::POSITIVE, 5},
|
||||
/*holdRewind */ {GamepadAxisEvent::Direction::POSITIVE, 4},
|
||||
}
|
||||
},
|
||||
{
|
||||
"(Microsoft X-Box 360 pad|Xbox Gamepad \\(userspace driver\\))", // Linux
|
||||
{
|
||||
/*keyA */ 1,
|
||||
/*keyB */ 0,
|
||||
/*keySelect */ 6,
|
||||
/*keyStart */ 7,
|
||||
/*keyRight */ -1,
|
||||
/*keyLeft */ -1,
|
||||
/*keyUp */ -1,
|
||||
/*keyDown */ -1,
|
||||
/*keyR */ 5,
|
||||
/*keyL */ 4
|
||||
},
|
||||
{
|
||||
/*loadState */ 2,
|
||||
/*saveState */ 3,
|
||||
/*holdFastForward */ -1,
|
||||
/*holdRewind */ -1,
|
||||
},
|
||||
{
|
||||
/*loadState */ {GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
/*saveState */ {GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
/*holdFastForward */ {GamepadAxisEvent::Direction::POSITIVE, 5},
|
||||
/*holdRewind */ {GamepadAxisEvent::Direction::POSITIVE, 2},
|
||||
}
|
||||
},
|
||||
{
|
||||
"Xbox 360 Wired Controller", // OS X
|
||||
{
|
||||
/*keyA */ 1,
|
||||
/*keyB */ 0,
|
||||
/*keySelect */ 9,
|
||||
/*keyStart */ 8,
|
||||
/*keyRight */ 14,
|
||||
/*keyLeft */ 13,
|
||||
/*keyUp */ 11,
|
||||
/*keyDown */ 12,
|
||||
/*keyR */ 5,
|
||||
/*keyL */ 4
|
||||
},
|
||||
{
|
||||
/*loadState */ 2,
|
||||
/*saveState */ 3,
|
||||
/*holdFastForward */ -1,
|
||||
/*holdRewind */ -1,
|
||||
},
|
||||
{
|
||||
/*loadState */ {GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
/*saveState */ {GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
/*holdFastForward */ {GamepadAxisEvent::Direction::POSITIVE, 5},
|
||||
/*holdRewind */ {GamepadAxisEvent::Direction::POSITIVE, 2},
|
||||
}
|
||||
},
|
||||
{
|
||||
"(Sony Computer Entertainment )?Wireless Controller", // The DualShock 4 device ID is cut off on Windows
|
||||
{
|
||||
/*keyA */ 1,
|
||||
/*keyB */ 2,
|
||||
/*keySelect */ 8,
|
||||
/*keyStart */ 9,
|
||||
/*keyRight */ -1,
|
||||
/*keyLeft */ -1,
|
||||
/*keyUp */ -1,
|
||||
/*keyDown */ -1,
|
||||
/*keyR */ 5,
|
||||
/*keyL */ 4
|
||||
},
|
||||
{
|
||||
/*loadState */ 0,
|
||||
/*saveState */ 3,
|
||||
/*holdFastForward */ 7,
|
||||
/*holdRewind */ 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
"PLAYSTATION\\(R\\)3 Controller", // DualShock 3 (OS X)
|
||||
{
|
||||
/*keyA */ 13,
|
||||
/*keyB */ 14,
|
||||
/*keySelect */ 0,
|
||||
/*keyStart */ 3,
|
||||
/*keyRight */ 5,
|
||||
/*keyLeft */ 7,
|
||||
/*keyUp */ 4,
|
||||
/*keyDown */ 6,
|
||||
/*keyR */ 11,
|
||||
/*keyL */ 10
|
||||
},
|
||||
{
|
||||
/*loadState */ 15,
|
||||
/*saveState */ 12,
|
||||
/*holdFastForward */ 9,
|
||||
/*holdRewind */ 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
"Wiimote \\(..-..-..-..-..-..\\)", // WJoy (OS X)
|
||||
{
|
||||
/*keyA */ 15,
|
||||
/*keyB */ 16,
|
||||
/*keySelect */ 7,
|
||||
/*keyStart */ 6,
|
||||
/*keyRight */ 14,
|
||||
/*keyLeft */ 13,
|
||||
/*keyUp */ 11,
|
||||
/*keyDown */ 12,
|
||||
/*keyR */ 20,
|
||||
/*keyL */ 19
|
||||
},
|
||||
{
|
||||
/*loadState */ 18,
|
||||
/*saveState */ 17,
|
||||
/*holdFastForward */ 22,
|
||||
/*holdRewind */ 21,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
InputProfile::InputProfile(const QString& name)
|
||||
constexpr InputProfile::InputProfile(const char* name,
|
||||
const KeyList<int> keys,
|
||||
const Shortcuts<int> shortcutButtons,
|
||||
const Shortcuts<Axis> shortcutAxes,
|
||||
const KeyList<AxisValue> axes,
|
||||
const struct Coord& tiltAxis,
|
||||
const struct Coord& gyroAxis,
|
||||
float gyroSensitivity)
|
||||
: m_profileName(name)
|
||||
, m_keys {
|
||||
keys.keyA,
|
||||
keys.keyB,
|
||||
keys.keySelect,
|
||||
keys.keyStart,
|
||||
keys.keyRight,
|
||||
keys.keyLeft,
|
||||
keys.keyUp,
|
||||
keys.keyDown,
|
||||
keys.keyR,
|
||||
keys.keyL,
|
||||
}
|
||||
, m_axes {
|
||||
axes.keyA,
|
||||
axes.keyB,
|
||||
axes.keySelect,
|
||||
axes.keyStart,
|
||||
axes.keyRight,
|
||||
axes.keyLeft,
|
||||
axes.keyUp,
|
||||
axes.keyDown,
|
||||
axes.keyR,
|
||||
axes.keyL,
|
||||
}
|
||||
, m_shortcutButtons(shortcutButtons)
|
||||
, m_shortcutAxes(shortcutAxes)
|
||||
, m_tiltAxis(tiltAxis)
|
||||
, m_gyroAxis(gyroAxis)
|
||||
, m_gyroSensitivity(gyroSensitivity)
|
||||
{
|
||||
}
|
||||
|
||||
void InputProfile::loadDefaultProfiles() {
|
||||
loadProfiles(":/input/default-profiles.ini");
|
||||
}
|
||||
|
||||
void InputProfile::loadProfiles(const QString& path) {
|
||||
QSettings profileIni(path, QSettings::IniFormat);
|
||||
|
||||
for (const auto& group : profileIni.childGroups()) {
|
||||
}
|
||||
profileIni.beginGroup(PROFILE_SECTION);
|
||||
for (const auto& group : profileIni.childGroups()) {
|
||||
loadProfile(profileIni, group);
|
||||
}
|
||||
profileIni.endGroup();
|
||||
}
|
||||
|
||||
void InputProfile::loadProfile(QSettings& profileIni, const QString& name) {
|
||||
profileIni.beginGroup(name);
|
||||
s_profiles.append(name);
|
||||
InputProfile& profile = s_profiles.last();
|
||||
for (const auto& group : profileIni.childGroups()) {
|
||||
profileIni.beginGroup(group);
|
||||
if (group == MATCH_SECTION) {
|
||||
for (const auto& key : profileIni.childKeys()) {
|
||||
profile.m_match.append(QRegExp(profileIni.value(key).toString()));
|
||||
}
|
||||
}
|
||||
for (const auto& key : profileIni.childKeys()) {
|
||||
InputItem* item = profile.m_inputIndex.itemAt(key);
|
||||
if (!item) {
|
||||
item = profile.m_inputIndex.addItem(QString(), key);
|
||||
}
|
||||
if (group == BUTTON_SECTION) {
|
||||
item->setButton(profileIni.value(key).toInt());
|
||||
}
|
||||
if (group == AXIS_SECTION) {
|
||||
QString axisDescription = profileIni.value(key).toString();
|
||||
GamepadAxisEvent::Direction direction = GamepadAxisEvent::POSITIVE;
|
||||
int axis = profileIni.value(key).toInt();
|
||||
if (axisDescription[0] == '-') {
|
||||
direction = GamepadAxisEvent::NEGATIVE;
|
||||
axis = -axis;
|
||||
}
|
||||
|
||||
item->setAxis(axis, direction);
|
||||
}
|
||||
if (group == KEY_SECTION) {
|
||||
item->setShortcut(profileIni.value(key).toInt());
|
||||
}
|
||||
}
|
||||
profileIni.endGroup();
|
||||
}
|
||||
profile.m_inputIndex.rebuild();
|
||||
profileIni.endGroup();
|
||||
}
|
||||
|
||||
const InputProfile* InputProfile::findProfile(const QString& name) {
|
||||
if (s_profiles.isEmpty()) {
|
||||
loadDefaultProfiles();
|
||||
}
|
||||
for (const InputProfile& profile : s_profiles) {
|
||||
for (const auto& match : profile.m_match) {
|
||||
if (match.exactMatch(name)) {
|
||||
return &profile;
|
||||
}
|
||||
for (size_t i = 0; i < sizeof(s_defaultMaps) / sizeof(*s_defaultMaps); ++i) {
|
||||
QRegExp re(s_defaultMaps[i].m_profileName);
|
||||
if (re.exactMatch(name)) {
|
||||
return &s_defaultMaps[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void InputProfile::apply(InputController* controller) const {
|
||||
controller->rebuildIndex(&m_inputIndex);
|
||||
controller->rebuildKeyIndex(&m_inputIndex);
|
||||
controller->registerTiltAxisX(m_tiltAxis.x);
|
||||
controller->registerTiltAxisY(m_tiltAxis.y);
|
||||
controller->registerGyroAxisX(m_gyroAxis.x);
|
||||
controller->registerGyroAxisY(m_gyroAxis.y);
|
||||
controller->setGyroSensitivity(m_gyroSensitivity);
|
||||
auto gamepadDriver = controller->gamepadDriver();
|
||||
if (gamepadDriver) {
|
||||
InputMapper mapper = controller->mapper(gamepadDriver);
|
||||
for (size_t i = 0; i < GBA_KEY_MAX; ++i) {
|
||||
mapper.bindKey(m_keys[i], i);
|
||||
mapper.bindAxis(m_axes[i].axis, m_axes[i].direction, i);
|
||||
}
|
||||
}
|
||||
|
||||
InputDriver* sensorDriver = controller->sensorDriver();
|
||||
if (sensorDriver) {
|
||||
sensorDriver->registerTiltAxisX(m_tiltAxis.x);
|
||||
sensorDriver->registerTiltAxisY(m_tiltAxis.y);
|
||||
sensorDriver->registerGyroAxisX(m_gyroAxis.x);
|
||||
sensorDriver->registerGyroAxisY(m_gyroAxis.y);
|
||||
sensorDriver->setGyroSensitivity(m_gyroSensitivity);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputProfile::lookupShortcutButton(const QString& shortcutName, int* button) const {
|
||||
if (shortcutName == QLatin1String("loadState")) {
|
||||
*button = m_shortcutButtons.loadState;
|
||||
return true;
|
||||
}
|
||||
if (shortcutName == QLatin1String("saveState")) {
|
||||
*button = m_shortcutButtons.saveState;
|
||||
return true;
|
||||
}
|
||||
if (shortcutName == QLatin1String("holdFastForward")) {
|
||||
*button = m_shortcutButtons.holdFastForward;
|
||||
return true;
|
||||
}
|
||||
if (shortcutName == QLatin1String("holdRewind")) {
|
||||
*button = m_shortcutButtons.holdRewind;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputProfile::lookupShortcutAxis(const QString& shortcutName, int* axis, GamepadAxisEvent::Direction* direction) const {
|
||||
if (shortcutName == QLatin1String("loadState")) {
|
||||
*axis = m_shortcutAxes.loadState.axis;
|
||||
*direction = m_shortcutAxes.loadState.direction;
|
||||
return true;
|
||||
}
|
||||
if (shortcutName == QLatin1String("saveState")) {
|
||||
*axis = m_shortcutAxes.saveState.axis;
|
||||
*direction = m_shortcutAxes.saveState.direction;
|
||||
return true;
|
||||
}
|
||||
if (shortcutName == QLatin1String("holdFastForward")) {
|
||||
*axis = m_shortcutAxes.holdFastForward.axis;
|
||||
*direction = m_shortcutAxes.holdFastForward.direction;
|
||||
return true;
|
||||
}
|
||||
if (shortcutName == QLatin1String("holdRewind")) {
|
||||
*axis = m_shortcutAxes.holdRewind.axis;
|
||||
*direction = m_shortcutAxes.holdRewind.direction;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,18 +3,12 @@
|
|||
* 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/. */
|
||||
#ifndef QGBA_INPUT_PROFILE
|
||||
#define QGBA_INPUT_PROFILE
|
||||
#pragma once
|
||||
|
||||
#include "GamepadAxisEvent.h"
|
||||
#include "InputIndex.h"
|
||||
#include "input/GamepadAxisEvent.h"
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
|
||||
#include <QRegExp>
|
||||
|
||||
class QSettings;
|
||||
#include <mgba/internal/gba/input.h>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
|
@ -22,39 +16,81 @@ class InputController;
|
|||
|
||||
class InputProfile {
|
||||
public:
|
||||
constexpr static const char* const PROFILE_SECTION = "profiles";
|
||||
constexpr static const char* const MATCH_SECTION = "match";
|
||||
constexpr static const char* const KEY_SECTION = "keys";
|
||||
constexpr static const char* const BUTTON_SECTION = "buttons";
|
||||
constexpr static const char* const AXIS_SECTION = "axes";
|
||||
constexpr static const char* const HAT_SECTION = "hats";
|
||||
|
||||
static const InputProfile* findProfile(const QString& name);
|
||||
static void loadProfiles(const QString& path);
|
||||
|
||||
void apply(InputController*) const;
|
||||
private:
|
||||
InputProfile(const QString&);
|
||||
bool lookupShortcutButton(const QString& shortcut, int* button) const;
|
||||
bool lookupShortcutAxis(const QString& shortcut, int* axis, GamepadAxisEvent::Direction* direction) const;
|
||||
|
||||
private:
|
||||
struct Coord {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
static void loadDefaultProfiles();
|
||||
static void loadProfile(QSettings&, const QString& name);
|
||||
struct AxisValue {
|
||||
GamepadAxisEvent::Direction direction;
|
||||
int axis;
|
||||
};
|
||||
|
||||
static QList<InputProfile> s_profiles;
|
||||
template <typename T> struct Shortcuts {
|
||||
T loadState;
|
||||
T saveState;
|
||||
T holdFastForward;
|
||||
T holdRewind;
|
||||
};
|
||||
|
||||
QString m_profileName;
|
||||
QList<QRegExp> m_match;
|
||||
struct Axis {
|
||||
GamepadAxisEvent::Direction direction;
|
||||
int axis;
|
||||
};
|
||||
|
||||
Coord m_tiltAxis = { 2, 3 };
|
||||
Coord m_gyroAxis = { 0, 1 };
|
||||
float m_gyroSensitivity = 2e+09f;
|
||||
InputIndex m_inputIndex;
|
||||
template <typename T> struct KeyList {
|
||||
T keyA;
|
||||
T keyB;
|
||||
T keySelect;
|
||||
T keyStart;
|
||||
T keyRight;
|
||||
T keyLeft;
|
||||
T keyUp;
|
||||
T keyDown;
|
||||
T keyR;
|
||||
T keyL;
|
||||
};
|
||||
|
||||
constexpr InputProfile(const char* name,
|
||||
const KeyList<int> keys,
|
||||
const Shortcuts<int> shortcutButtons = { -1, -1, -1, -1},
|
||||
const Shortcuts<Axis> shortcutAxes = {
|
||||
{GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
{GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
{GamepadAxisEvent::Direction::NEUTRAL, -1},
|
||||
{GamepadAxisEvent::Direction::NEUTRAL, -1}},
|
||||
const KeyList<AxisValue> axes = {
|
||||
{ GamepadAxisEvent::Direction::NEUTRAL, -1 },
|
||||
{ GamepadAxisEvent::Direction::NEUTRAL, -1 },
|
||||
{ GamepadAxisEvent::Direction::NEUTRAL, -1 },
|
||||
{ GamepadAxisEvent::Direction::NEUTRAL, -1 },
|
||||
{ GamepadAxisEvent::Direction::POSITIVE, 0 },
|
||||
{ GamepadAxisEvent::Direction::NEGATIVE, 0 },
|
||||
{ GamepadAxisEvent::Direction::NEGATIVE, 1 },
|
||||
{ GamepadAxisEvent::Direction::POSITIVE, 1 },
|
||||
{ GamepadAxisEvent::Direction::NEUTRAL, -1 },
|
||||
{ GamepadAxisEvent::Direction::NEUTRAL, -1 }},
|
||||
const struct Coord& tiltAxis = { 2, 3 },
|
||||
const struct Coord& gyroAxis = { 0, 1 },
|
||||
float gyroSensitivity = 2e+09f);
|
||||
|
||||
static const InputProfile s_defaultMaps[];
|
||||
|
||||
const char* m_profileName;
|
||||
const int m_keys[GBA_KEY_MAX];
|
||||
const AxisValue m_axes[GBA_KEY_MAX];
|
||||
const Shortcuts<int> m_shortcutButtons;
|
||||
const Shortcuts<Axis> m_shortcutAxes;
|
||||
Coord m_tiltAxis;
|
||||
Coord m_gyroAxis;
|
||||
float m_gyroSensitivity;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/* 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/InputSource.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
InputSource::InputSource(InputDriver* driver, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_driver(driver)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* 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 <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "input/InputDriver.h"
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class InputSource : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InputSource(InputDriver* driver, QObject* parent = nullptr);
|
||||
virtual ~InputSource() = default;
|
||||
|
||||
InputDriver* driver() { return m_driver; }
|
||||
uint32_t type() { return m_driver->type(); }
|
||||
|
||||
virtual QString name() const = 0;
|
||||
virtual QString visibleName() const = 0;
|
||||
|
||||
protected:
|
||||
InputDriver* const m_driver;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/* 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/KeySource.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
KeySource::KeySource(InputDriver* driver, QObject* parent)
|
||||
: InputSource(driver, parent)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* 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 "input/InputSource.h"
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class InputDriver;
|
||||
|
||||
class KeySource : public InputSource {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KeySource(InputDriver* driver, QObject* parent = nullptr);
|
||||
|
||||
virtual QSet<int> currentKeys() = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,357 @@
|
|||
/* 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/SDLInputDriver.h"
|
||||
|
||||
#include "ConfigController.h"
|
||||
#include "InputController.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
int s_sdlInited = 0;
|
||||
mSDLEvents s_sdlEvents;
|
||||
|
||||
void SDL::suspendScreensaver() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (s_sdlInited) {
|
||||
mSDLSuspendScreensaver(&s_sdlEvents);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL::resumeScreensaver() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (s_sdlInited) {
|
||||
mSDLResumeScreensaver(&s_sdlEvents);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL::setScreensaverSuspendable(bool suspendable) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (s_sdlInited) {
|
||||
mSDLSetScreensaverSuspendable(&s_sdlEvents, suspendable);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SDLInputDriver::SDLInputDriver(InputController* controller, QObject* parent)
|
||||
: InputDriver(parent)
|
||||
, m_controller(controller)
|
||||
{
|
||||
if (s_sdlInited == 0) {
|
||||
mSDLInitEvents(&s_sdlEvents);
|
||||
}
|
||||
++s_sdlInited;
|
||||
m_sdlPlayer.bindings = m_controller->map();
|
||||
|
||||
for (size_t i = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) {
|
||||
m_gamepads.append(std::make_shared<SDLGamepad>(this, i));
|
||||
}
|
||||
}
|
||||
|
||||
SDLInputDriver::~SDLInputDriver() {
|
||||
if (m_playerAttached) {
|
||||
mSDLDetachPlayer(&s_sdlEvents, &m_sdlPlayer);
|
||||
}
|
||||
|
||||
--s_sdlInited;
|
||||
if (s_sdlInited == 0) {
|
||||
mSDLDeinitEvents(&s_sdlEvents);
|
||||
}
|
||||
}
|
||||
|
||||
bool SDLInputDriver::supportsPolling() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDLInputDriver::supportsGamepads() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDLInputDriver::supportsSensors() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString SDLInputDriver::currentProfile() const {
|
||||
if (m_sdlPlayer.joystick) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
return SDL_JoystickName(m_sdlPlayer.joystick->joystick);
|
||||
#else
|
||||
return SDL_JoystickName(SDL_JoystickIndex(m_sdlPlayer.joystick->joystick));
|
||||
#endif
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void SDLInputDriver::loadConfiguration(ConfigController* config) {
|
||||
mSDLEventsLoadConfig(&s_sdlEvents, config->input());
|
||||
if (!m_playerAttached) {
|
||||
m_playerAttached = mSDLAttachPlayer(&s_sdlEvents, &m_sdlPlayer);
|
||||
}
|
||||
if (m_playerAttached) {
|
||||
mSDLPlayerLoadConfig(&m_sdlPlayer, config->input());
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::saveConfiguration(ConfigController* config) {
|
||||
if (m_playerAttached) {
|
||||
mSDLPlayerSaveConfig(&m_sdlPlayer, config->input());
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::bindDefaults(InputController* controller) {
|
||||
mSDLInitBindingsGBA(controller->map());
|
||||
}
|
||||
|
||||
mRumble* SDLInputDriver::rumble() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (m_playerAttached) {
|
||||
return &m_sdlPlayer.rumble.d;
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mRotationSource* SDLInputDriver::rotationSource() {
|
||||
if (m_playerAttached) {
|
||||
return &m_sdlPlayer.rotation.d;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool SDLInputDriver::update() {
|
||||
if (!m_playerAttached || !m_sdlPlayer.joystick) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_JoystickUpdate();
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
updateGamepads();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<Gamepad*> SDLInputDriver::connectedGamepads() const {
|
||||
QList<Gamepad*> pads;
|
||||
for (auto& pad : m_gamepads) {
|
||||
pads.append(pad.get());
|
||||
}
|
||||
return pads;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
void SDLInputDriver::updateGamepads() {
|
||||
for (int i = 0; i < m_gamepads.size(); ++i) {
|
||||
if (m_gamepads.at(i)->updateIndex()) {
|
||||
continue;
|
||||
}
|
||||
m_gamepads.removeAt(i);
|
||||
--i;
|
||||
}
|
||||
std::sort(m_gamepads.begin(), m_gamepads.end(), [](const auto& a, const auto b) {
|
||||
return a->m_index < b->m_index;
|
||||
});
|
||||
|
||||
for (size_t i = 0, j = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) {
|
||||
std::shared_ptr<SDLGamepad> gamepad = m_gamepads.at(j);
|
||||
if (gamepad->m_index == i) {
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
m_gamepads.append(std::make_shared<SDLGamepad>(this, i));
|
||||
}
|
||||
std::sort(m_gamepads.begin(), m_gamepads.end(), [](const auto& a, const auto b) {
|
||||
return a->m_index < b->m_index;
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
int SDLInputDriver::activeGamepad() const {
|
||||
return m_sdlPlayer.joystick ? m_sdlPlayer.joystick->index : 0;
|
||||
}
|
||||
|
||||
void SDLInputDriver::setActiveGamepad(int index) {
|
||||
mSDLPlayerChangeJoystick(&s_sdlEvents, &m_sdlPlayer, index);
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerTiltAxisX(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.axisX = axis;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerTiltAxisY(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.axisY = axis;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerGyroAxisX(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroX = axis;
|
||||
if (m_sdlPlayer.rotation.gyroY == axis) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
} else {
|
||||
m_sdlPlayer.rotation.gyroZ = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerGyroAxisY(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroY = axis;
|
||||
if (m_sdlPlayer.rotation.gyroX == axis) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
} else {
|
||||
m_sdlPlayer.rotation.gyroZ = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLInputDriver::registerGyroAxisZ(int axis) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroZ = axis;
|
||||
m_sdlPlayer.rotation.gyroX = -1;
|
||||
m_sdlPlayer.rotation.gyroY = -1;
|
||||
}
|
||||
}
|
||||
|
||||
float SDLInputDriver::gyroSensitivity() const {
|
||||
if (m_playerAttached) {
|
||||
return m_sdlPlayer.rotation.gyroSensitivity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDLInputDriver::setGyroSensitivity(float sensitivity) {
|
||||
if (m_playerAttached) {
|
||||
m_sdlPlayer.rotation.gyroSensitivity = sensitivity;
|
||||
}
|
||||
}
|
||||
|
||||
SDLGamepad::SDLGamepad(SDLInputDriver* driver, int index, QObject* parent)
|
||||
: Gamepad(driver, parent)
|
||||
, m_index(index)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick;
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), m_guid, sizeof(m_guid));
|
||||
#endif
|
||||
}
|
||||
|
||||
QList<bool> SDLGamepad::currentButtons() {
|
||||
if (!verify()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick;
|
||||
QList<bool> buttons;
|
||||
|
||||
int numButtons = SDL_JoystickNumButtons(joystick);
|
||||
for (int i = 0; i < numButtons; ++i) {
|
||||
buttons.append(SDL_JoystickGetButton(joystick, i));
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
QList<int16_t> SDLGamepad::currentAxes() {
|
||||
if (!verify()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick;
|
||||
QList<int16_t> axes;
|
||||
|
||||
int numAxes = SDL_JoystickNumAxes(joystick);
|
||||
for (int i = 0; i < numAxes; ++i) {
|
||||
axes.append(SDL_JoystickGetAxis(joystick, i));
|
||||
}
|
||||
|
||||
return axes;
|
||||
}
|
||||
|
||||
QList<GamepadHatEvent::Direction> SDLGamepad::currentHats() {
|
||||
if (!verify()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick;
|
||||
QList<GamepadHatEvent::Direction> hats;
|
||||
|
||||
int numHats = SDL_JoystickNumHats(joystick);
|
||||
for (int i = 0; i < numHats; ++i) {
|
||||
hats.append(static_cast<GamepadHatEvent::Direction>(SDL_JoystickGetHat(joystick, i)));
|
||||
}
|
||||
|
||||
return hats;
|
||||
}
|
||||
|
||||
int SDLGamepad::buttonCount() const {
|
||||
if (!verify()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick;
|
||||
return SDL_JoystickNumButtons(joystick);
|
||||
}
|
||||
|
||||
int SDLGamepad::axisCount() const {
|
||||
if (!verify()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick;
|
||||
return SDL_JoystickNumAxes(joystick);
|
||||
}
|
||||
|
||||
int SDLGamepad::hatCount() const {
|
||||
if (!verify()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick;
|
||||
return SDL_JoystickNumHats(joystick);
|
||||
}
|
||||
|
||||
QString SDLGamepad::name() const {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
return m_guid;
|
||||
#else
|
||||
return visibleName();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString SDLGamepad::visibleName() const {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
return SDL_JoystickName(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick);
|
||||
#else
|
||||
return SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
bool SDLGamepad::updateIndex() {
|
||||
char guid[34];
|
||||
for (size_t i = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) {
|
||||
SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick;
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), guid, sizeof(guid));
|
||||
if (memcmp(guid, m_guid, 33) == 0) {
|
||||
m_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SDLGamepad::verify() const {
|
||||
return m_index < SDL_JoystickListSize(&s_sdlEvents.joysticks);
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/* 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 "input/Gamepad.h"
|
||||
#include "input/InputDriver.h"
|
||||
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class SDLGamepad;
|
||||
|
||||
namespace SDL {
|
||||
void suspendScreensaver();
|
||||
void resumeScreensaver();
|
||||
void setScreensaverSuspendable(bool);
|
||||
}
|
||||
|
||||
class SDLInputDriver : public InputDriver {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SDLInputDriver(InputController*, QObject* parent = nullptr);
|
||||
~SDLInputDriver();
|
||||
|
||||
uint32_t type() const override { return SDL_BINDING_BUTTON; }
|
||||
QString visibleName() const override { return QLatin1String("SDL"); }
|
||||
QString currentProfile() const override;
|
||||
|
||||
bool supportsPolling() const override;
|
||||
bool supportsGamepads() const override;
|
||||
bool supportsSensors() const override;
|
||||
|
||||
void loadConfiguration(ConfigController* config) override;
|
||||
void saveConfiguration(ConfigController* config) override;
|
||||
|
||||
void bindDefaults(InputController*) override;
|
||||
|
||||
bool update() override;
|
||||
|
||||
QList<Gamepad*> connectedGamepads() const override;
|
||||
|
||||
int activeGamepad() const override;
|
||||
void setActiveGamepad(int) override;
|
||||
|
||||
void registerTiltAxisX(int axis) override;
|
||||
void registerTiltAxisY(int axis) override;
|
||||
void registerGyroAxisX(int axis) override;
|
||||
void registerGyroAxisY(int axis) override;
|
||||
void registerGyroAxisZ(int axis) override;
|
||||
|
||||
float gyroSensitivity() const override;
|
||||
void setGyroSensitivity(float sensitivity) override;
|
||||
|
||||
mRumble* rumble() override;
|
||||
mRotationSource* rotationSource() override;
|
||||
|
||||
private:
|
||||
InputController* m_controller;
|
||||
mSDLPlayer m_sdlPlayer{};
|
||||
bool m_playerAttached = false;
|
||||
QList<std::shared_ptr<SDLGamepad>> m_gamepads;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
void updateGamepads();
|
||||
#endif
|
||||
};
|
||||
|
||||
class SDLGamepad : public Gamepad {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SDLGamepad(SDLInputDriver*, int index, QObject* parent = nullptr);
|
||||
|
||||
QList<bool> currentButtons() override;
|
||||
QList<int16_t> currentAxes() override;
|
||||
QList<GamepadHatEvent::Direction> currentHats() override;
|
||||
|
||||
int buttonCount() const override;
|
||||
int axisCount() const override;
|
||||
int hatCount() const override;
|
||||
|
||||
QString name() const override;
|
||||
QString visibleName() const override;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
bool updateIndex();
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class SDLInputDriver;
|
||||
|
||||
size_t m_index;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
char m_guid[34]{};
|
||||
#endif
|
||||
|
||||
bool verify() const;
|
||||
};
|
||||
|
||||
}
|
|
@ -14,6 +14,10 @@
|
|||
#include <mgba/core/version.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
|
||||
#ifdef BUILD_SDL
|
||||
#include "platform/sdl/sdl-events.h"
|
||||
#endif
|
||||
|
||||
#include <QLibraryInfo>
|
||||
#include <QTranslator>
|
||||
|
||||
|
|
Loading…
Reference in New Issue