Qt: Remappable controls for tilt and gyroscope sensors

This commit is contained in:
Jeffrey Pfau 2015-04-21 20:36:53 -07:00
parent 3eb4c01515
commit 6248e44e47
10 changed files with 183 additions and 4 deletions

View File

@ -11,6 +11,7 @@ Features:
- Deadzone estimation for game controllers
- Analog inputs can be used for shortcuts
- Menu items for specific solar sensor brightness levels
- Remappable controls for tilt and gyroscope sensors
Bugfixes:
- GBA: Fix timers not updating timing when writing to only the reload register
- All: Fix sanitize-deb script not cleaning up after itself

View File

@ -500,3 +500,23 @@ void GBAInputSetPreferredDevice(struct Configuration* config, uint32_t type, int
snprintf(deviceId, sizeof(deviceId), "device%i", playerId);
return ConfigurationSetValue(config, sectionName, deviceId, deviceName);
}
const char* GBAInputGetCustomValue(const struct Configuration* config, uint32_t type, const char* key, const char* profile) {
char sectionName[SECTION_NAME_MAX];
if (profile) {
snprintf(sectionName, SECTION_NAME_MAX, "input-profile.%s", profile);
} else {
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
}
return ConfigurationGetValue(config, sectionName, key);
}
void GBAInputSetCustomValue(struct Configuration* config, uint32_t type, const char* key, const char* value, const char* profile) {
char sectionName[SECTION_NAME_MAX];
if (profile) {
snprintf(sectionName, SECTION_NAME_MAX, "input-profile.%s", profile);
} else {
_makeSectionName(sectionName, SECTION_NAME_MAX, type);
}
ConfigurationSetValue(config, sectionName, key, value);
}

View File

@ -51,4 +51,7 @@ void GBAInputProfileSave(const struct GBAInputMap*, uint32_t type, struct Config
const char* GBAInputGetPreferredDevice(const struct Configuration*, uint32_t type, int playerId);
void GBAInputSetPreferredDevice(struct Configuration*, uint32_t type, int playerId, const char* deviceName);
const char* GBAInputGetCustomValue(const struct Configuration* config, uint32_t type, const char* key, const char* profile);
void GBAInputSetCustomValue(struct Configuration* config, uint32_t type, const char* key, const char* value, const char* profile);
#endif

View File

@ -110,6 +110,11 @@ void InputController::loadProfile(uint32_t type, const QString& profile) {
void InputController::saveConfiguration(uint32_t type) {
GBAInputMapSave(&m_inputMap, type, m_config->input());
#ifdef BUILD_SDL
if (m_playerAttached) {
GBASDLPlayerSaveConfig(&m_sdlPlayer, m_config->input());
}
#endif
m_config->write();
}
@ -170,6 +175,27 @@ GBARumble* InputController::rumble() {
GBARotationSource* InputController::rotationSource() {
return &m_sdlPlayer.rotation.d;
}
void InputController::registerTiltAxisX(int axis) {
m_sdlPlayer.rotation.axisX = axis;
}
void InputController::registerTiltAxisY(int axis) {
m_sdlPlayer.rotation.axisY = axis;
}
void InputController::registerGyroAxisX(int axis) {
m_sdlPlayer.rotation.gyroX = axis;
}
void InputController::registerGyroAxisY(int axis) {
m_sdlPlayer.rotation.gyroY = axis;
}
float InputController::gyroSensitivity() const {
return m_sdlPlayer.rotation.gyroSensitivity;
}
void InputController::setGyroSensitivity(float sensitivity) {
m_sdlPlayer.rotation.gyroSensitivity = sensitivity;
}
#else
GBARumble* InputController::rumble() {
return nullptr;

View File

@ -65,6 +65,14 @@ public:
int gamepad(uint32_t type) const { return m_sdlPlayer.joystickIndex; }
void setGamepad(uint32_t type, int index) { GBASDLPlayerChangeJoystick(&s_sdlEvents, &m_sdlPlayer, index); }
void setPreferredGamepad(uint32_t type, const QString& device);
void registerTiltAxisX(int axis);
void registerTiltAxisY(int axis);
void registerGyroAxisX(int axis);
void registerGyroAxisY(int axis);
float gyroSensitivity() const;
void setGyroSensitivity(float sensitivity);
#endif
GBARumble* rumble();

View File

@ -6,6 +6,7 @@
#include "SensorView.h"
#include "GameController.h"
#include "GamepadAxisEvent.h"
#include "InputController.h"
using namespace QGBA;
@ -50,6 +51,42 @@ SensorView::SensorView(GameController* controller, InputController* input, QWidg
} else {
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);
m_ui.gyroSensitivity->setValue(m_input->gyroSensitivity() / 1e8f);
connect(m_ui.gyroSensitivity, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {
m_input->setGyroSensitivity(value * 1e8f);
});
}
void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
connect(button, &QAbstractButton::toggled, [this, button, setter](bool checked) {
if (!checked) {
m_jiggered = nullptr;
} else {
m_jiggered = [this, button, setter](int axis) {
(m_input->*setter)(axis);
button->setChecked(false);
};
}
});
button->installEventFilter(this);
}
bool SensorView::eventFilter(QObject*, QEvent* event) {
if (event->type() == GamepadAxisEvent::Type()) {
GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
gae->accept();
if (m_jiggered && gae->direction() != GamepadAxisEvent::NEUTRAL && gae->isNew()) {
m_jiggered(gae->axis());
}
return true;
}
return false;
}
void SensorView::updateSensors() {

View File

@ -9,6 +9,8 @@
#include <QTimer>
#include <QWidget>
#include <functional>
#include "ui_SensorView.h"
struct GBARotationSource;
@ -17,6 +19,7 @@ namespace QGBA {
class ConfigController;
class GameController;
class GamepadAxisEvent;
class InputController;
class SensorView : public QWidget {
@ -25,6 +28,9 @@ Q_OBJECT
public:
SensorView(GameController* controller, InputController* input, QWidget* parent = nullptr);
protected:
bool eventFilter(QObject*, QEvent* event) override;
private slots:
void updateSensors();
void setLuminanceValue(int);
@ -33,10 +39,13 @@ private slots:
private:
Ui::SensorView m_ui;
std::function<void(int)> m_jiggered;
GameController* m_controller;
InputController* m_input;
GBARotationSource* m_rotation;
QTimer m_timer;
void jiggerer(QAbstractButton*, void (InputController::*)(int));
};
}

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>508</width>
<height>258</height>
<width>434</width>
<height>288</height>
</rect>
</property>
<property name="sizePolicy">
@ -157,6 +157,9 @@
<property name="text">
<string>Set Y</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
@ -164,6 +167,9 @@
<property name="text">
<string>Set X</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" alignment="Qt::AlignHCenter">
@ -240,6 +246,9 @@
<property name="text">
<string>Set Y</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
@ -247,6 +256,9 @@
<property name="text">
<string>Set X</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">

View File

@ -12,6 +12,7 @@
#include "gba/video.h"
#include "gba/renderers/video-software.h"
#include "util/configuration.h"
#include "util/formatting.h"
#include "util/vfs.h"
#if SDL_VERSION_ATLEAST(2, 0, 0) && defined(__APPLE__)
@ -233,10 +234,71 @@ void GBASDLPlayerLoadConfig(struct GBASDLPlayer* context, const struct Configura
if (context->joystick) {
GBAInputMapLoad(context->bindings, SDL_BINDING_BUTTON, config);
#if SDL_VERSION_ATLEAST(2, 0, 0)
GBAInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, SDL_JoystickName(context->joystick));
const char* name = SDL_JoystickName(context->joystick);
#else
GBAInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, SDL_JoystickName(SDL_JoystickIndex(context->joystick)));
const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick));
#endif
GBAInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, name);
const char* value;
char* end;
int axis;
value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "tiltAxisX", name);
if (value) {
axis = strtol(value, &end, 0);
if (end && !*end) {
context->rotation.axisX = axis;
}
}
value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "tiltAxisY", name);
if (value) {
axis = strtol(value, &end, 0);
if (end && !*end) {
context->rotation.axisY = axis;
}
}
value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "gyroAxisX", name);
if (value) {
axis = strtol(value, &end, 0);
if (end && !*end) {
context->rotation.gyroX = axis;
}
}
value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "gyroAxisY", name);
if (value) {
axis = strtol(value, &end, 0);
if (end && !*end) {
context->rotation.gyroY = axis;
}
}
value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "gyroSensitivity", name);
if (value) {
float sensitivity = strtof_u(value, &end);
if (end && !*end) {
context->rotation.gyroSensitivity = sensitivity;
}
}
}
}
void GBASDLPlayerSaveConfig(const struct GBASDLPlayer* context, struct Configuration* config) {
if (context->joystick) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
const char* name = SDL_JoystickName(context->joystick);
#else
const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick));
#endif
char value[12];
snprintf(value, sizeof(value), "%i", context->rotation.axisX);
GBAInputSetCustomValue(config, SDL_BINDING_BUTTON, "tiltAxisX", value, name);
snprintf(value, sizeof(value), "%i", context->rotation.axisY);
GBAInputSetCustomValue(config, SDL_BINDING_BUTTON, "tiltAxisY", value, name);
snprintf(value, sizeof(value), "%i", context->rotation.gyroX);
GBAInputSetCustomValue(config, SDL_BINDING_BUTTON, "gyroAxisX", value, name);
snprintf(value, sizeof(value), "%i", context->rotation.gyroY);
GBAInputSetCustomValue(config, SDL_BINDING_BUTTON, "gyroAxisY", value, name);
snprintf(value, sizeof(value), "%g", context->rotation.gyroSensitivity);
GBAInputSetCustomValue(config, SDL_BINDING_BUTTON, "gyroSensitivity", value, name);
}
}

View File

@ -78,6 +78,7 @@ void GBASDLPlayerChangeJoystick(struct GBASDLEvents*, struct GBASDLPlayer*, size
void GBASDLInitBindings(struct GBAInputMap* inputMap);
void GBASDLPlayerLoadConfig(struct GBASDLPlayer*, const struct Configuration*);
void GBASDLPlayerSaveConfig(const struct GBASDLPlayer*, struct Configuration*);
void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLPlayer* sdlContext, const union SDL_Event* event);