Emulate motion controls with a mouse (#3122)

* Rework framework to allow for more types of mouse-to-something emulation and hook up gyro to it

* Remove the unnecessary null check now that deltatime is handled differently

* Fix toggle key

* Basic gyro emulation working for two out of the three dimensions

* clang

* Added bindable key to hold for switching from looking to the sides to rolling

* documentation
This commit is contained in:
kalaposfos13
2025-06-20 12:55:41 +02:00
committed by GitHub
parent be12305f65
commit 551751df3c
7 changed files with 88 additions and 30 deletions

View File

@@ -66,6 +66,7 @@ auto output_array = std::array{
ControllerOutput(LEFTJOYSTICK_HALFMODE),
ControllerOutput(RIGHTJOYSTICK_HALFMODE),
ControllerOutput(KEY_TOGGLE),
ControllerOutput(MOUSE_GYRO_ROLL_MODE),
// Button mappings
ControllerOutput(SDL_GAMEPAD_BUTTON_NORTH), // Triangle
@@ -534,6 +535,9 @@ void ControllerOutput::FinalizeUpdate() {
// to do it, and it would be inconvenient to force it here, when AddUpdate does the job just
// fine, and a toggle doesn't have to checked against every input that's bound to it, it's
// enough that one is pressed
case MOUSE_GYRO_ROLL_MODE:
SetMouseGyroRollMode(new_button_state);
break;
default: // is a normal key (hopefully)
controller->CheckButton(0, SDLGamepadToOrbisButton(button), new_button_state);
break;

View File

@@ -35,6 +35,7 @@
#define BACK_BUTTON 0x00040000
#define KEY_TOGGLE 0x00200000
#define MOUSE_GYRO_ROLL_MODE 0x00400000
#define SDL_UNMAPPED UINT32_MAX - 1
@@ -114,6 +115,7 @@ const std::map<std::string, u32> string_to_cbutton_map = {
{"lpaddle_low", SDL_GAMEPAD_BUTTON_LEFT_PADDLE2},
{"rpaddle_high", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1},
{"rpaddle_low", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2},
{"mouse_gyro_roll_mode", MOUSE_GYRO_ROLL_MODE},
};
const std::map<std::string, AxisMapping> string_to_axis_map = {

View File

@@ -3,6 +3,7 @@
#include <cmath>
#include "common/assert.h"
#include "common/types.h"
#include "input/controller.h"
#include "input_mouse.h"
@@ -13,12 +14,19 @@ namespace Input {
int mouse_joystick_binding = 0;
float mouse_deadzone_offset = 0.5, mouse_speed = 1, mouse_speed_offset = 0.1250;
bool mouse_gyro_roll_mode = false;
Uint32 mouse_polling_id = 0;
bool mouse_enabled = false;
MouseMode mouse_mode = MouseMode::Off;
// We had to go through 3 files of indirection just to update a flag
void ToggleMouseEnabled() {
mouse_enabled = !mouse_enabled;
// Switches mouse to a set mode or turns mouse emulation off if it was already in that mode.
// Returns whether the mode is turned on.
bool ToggleMouseModeTo(MouseMode m) {
if (mouse_mode == m) {
mouse_mode = MouseMode::Off;
} else {
mouse_mode = m;
}
return mouse_mode == m;
}
void SetMouseToJoystick(int joystick) {
@@ -31,10 +39,11 @@ void SetMouseParams(float mdo, float ms, float mso) {
mouse_speed_offset = mso;
}
Uint32 MousePolling(void* param, Uint32 id, Uint32 interval) {
auto* controller = (GameController*)param;
if (!mouse_enabled)
return interval;
void SetMouseGyroRollMode(bool mode) {
mouse_gyro_roll_mode = mode;
}
void EmulateJoystick(GameController* controller, u32 interval) {
Axis axis_x, axis_y;
switch (mouse_joystick_binding) {
@@ -47,7 +56,7 @@ Uint32 MousePolling(void* param, Uint32 id, Uint32 interval) {
axis_y = Axis::RightY;
break;
default:
return interval; // no update needed
return; // no update needed
}
float d_x = 0, d_y = 0;
@@ -67,7 +76,35 @@ Uint32 MousePolling(void* param, Uint32 id, Uint32 interval) {
controller->Axis(0, axis_x, GetAxis(-0x80, 0x7f, 0));
controller->Axis(0, axis_y, GetAxis(-0x80, 0x7f, 0));
}
}
constexpr float constant_down_accel[3] = {0.0f, 10.0f, 0.0f};
void EmulateGyro(GameController* controller, u32 interval) {
// LOG_INFO(Input, "todo gyro");
float d_x = 0, d_y = 0;
SDL_GetRelativeMouseState(&d_x, &d_y);
controller->Acceleration(1, constant_down_accel);
float gyro_from_mouse[3] = {-d_y / 100, -d_x / 100, 0.0f};
if (mouse_gyro_roll_mode) {
gyro_from_mouse[1] = 0.0f;
gyro_from_mouse[2] = -d_x / 100;
}
controller->Gyro(1, gyro_from_mouse);
}
Uint32 MousePolling(void* param, Uint32 id, Uint32 interval) {
auto* controller = (GameController*)param;
switch (mouse_mode) {
case MouseMode::Joystick:
EmulateJoystick(controller, interval);
break;
case MouseMode::Gyro:
EmulateGyro(controller, interval);
break;
default:
break;
}
return interval;
}

View File

@@ -8,11 +8,21 @@
namespace Input {
void ToggleMouseEnabled();
enum MouseMode {
Off = 0,
Joystick,
Gyro,
};
bool ToggleMouseModeTo(MouseMode m);
void SetMouseToJoystick(int joystick);
void SetMouseParams(float mouse_deadzone_offset, float mouse_speed, float mouse_speed_offset);
void SetMouseGyroRollMode(bool mode);
// Polls the mouse for changes, and simulates joystick movement from it.
void EmulateJoystick(GameController* controller, u32 interval);
void EmulateGyro(GameController* controller, u32 interval);
// Polls the mouse for changes
Uint32 MousePolling(void* param, Uint32 id, Uint32 interval);
} // namespace Input