mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-06-02 18:07:40 +00:00
Generalized the sensor coordinate transform for wraparound gamepads
This commit is contained in:
parent
9eb5eab0ad
commit
610c31c7b7
3 changed files with 65 additions and 34 deletions
|
@ -370,33 +370,19 @@ static void RecenterGamepad(SDL_Gamepad *gamepad)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SDL defines sensor orientation for phones relative to the natural
|
/* SDL defines sensor orientation relative to the device natural
|
||||||
orientation, and for gamepads relative to being held in front of you.
|
orientation, so when it's changed orientation to be used as a
|
||||||
When a phone is being used as a gamepad, its orientation changes,
|
gamepad, change the sensor orientation to match.
|
||||||
so adjust sensor axes to match.
|
|
||||||
*/
|
*/
|
||||||
static void AdjustSensorOrientation(float *src, float *dst)
|
static void AdjustSensorOrientation(SDL_Joystick *joystick, float *src, float *dst)
|
||||||
{
|
{
|
||||||
if (SDL_GetDisplayNaturalOrientation(SDL_GetPrimaryDisplay()) == SDL_ORIENTATION_LANDSCAPE) {
|
unsigned int i, j;
|
||||||
/* When a device in landscape orientation is laid flat, the axes change
|
|
||||||
orientation as follows:
|
for (i = 0; i < 3; ++i) {
|
||||||
-X to +X becomes -X to +X
|
dst[i] = 0.0f;
|
||||||
-Y to +Y becomes +Z to -Z
|
for (j = 0; j < 3; ++j) {
|
||||||
-Z to +Z becomes -Y to +Y
|
dst[i] += joystick->sensor_transform[i][j] * src[j];
|
||||||
*/
|
}
|
||||||
dst[0] = src[0];
|
|
||||||
dst[1] = src[2];
|
|
||||||
dst[2] = -src[1];
|
|
||||||
} else {
|
|
||||||
/* When a device in portrait orientation is rotated left and laid flat,
|
|
||||||
the axes change orientation as follows:
|
|
||||||
-X to +X becomes +Z to -Z
|
|
||||||
-Y to +Y becomes +X to -X
|
|
||||||
-Z to +Z becomes -Y to +Y
|
|
||||||
*/
|
|
||||||
dst[0] = -src[1];
|
|
||||||
dst[1] = src[2];
|
|
||||||
dst[2] = -src[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,12 +466,12 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
|
||||||
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
|
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
|
||||||
if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == event->sensor.which) {
|
if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == event->sensor.which) {
|
||||||
float data[3];
|
float data[3];
|
||||||
AdjustSensorOrientation(event->sensor.data, data);
|
AdjustSensorOrientation(gamepad->joystick, event->sensor.data, data);
|
||||||
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
|
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
|
||||||
}
|
}
|
||||||
if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == event->sensor.which) {
|
if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == event->sensor.which) {
|
||||||
float data[3];
|
float data[3];
|
||||||
AdjustSensorOrientation(event->sensor.data, data);
|
AdjustSensorOrientation(gamepad->joystick, event->sensor.data, data);
|
||||||
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_GYRO, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
|
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_GYRO, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -562,7 +562,7 @@ static SDL_bool IsROGAlly(SDL_Joystick *joystick)
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick)
|
static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *invert_sensors)
|
||||||
{
|
{
|
||||||
static Uint32 wraparound_gamepads[] = {
|
static Uint32 wraparound_gamepads[] = {
|
||||||
MAKE_VIDPID(0x1532, 0x0709), /* Razer Junglecat (L) */
|
MAKE_VIDPID(0x1532, 0x0709), /* Razer Junglecat (L) */
|
||||||
|
@ -578,6 +578,8 @@ static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick)
|
||||||
int i;
|
int i;
|
||||||
int hint;
|
int hint;
|
||||||
|
|
||||||
|
*invert_sensors = SDL_FALSE;
|
||||||
|
|
||||||
/* The SDL controller sensor API is only available for gamepads (at the moment) */
|
/* The SDL controller sensor API is only available for gamepads (at the moment) */
|
||||||
if (!joystick->is_gamepad) {
|
if (!joystick->is_gamepad) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -607,17 +609,23 @@ static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if this is another known wraparound gamepad */
|
/* See if this is another known wraparound gamepad */
|
||||||
if (IsBackboneOne(joystick) || IsROGAlly(joystick)) {
|
if (IsBackboneOne(joystick)) {
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
if (IsROGAlly(joystick)) {
|
||||||
|
/* I'm not sure if this is a Windows thing, or a quirk for ROG Ally,
|
||||||
|
* but we need to invert the sensor data on all axes.
|
||||||
|
*/
|
||||||
|
*invert_sensors = SDL_TRUE;
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AttemptSensorFusion(SDL_Joystick *joystick)
|
static void AttemptSensorFusion(SDL_Joystick *joystick, SDL_bool invert_sensors)
|
||||||
{
|
{
|
||||||
SDL_SensorID *sensors;
|
SDL_SensorID *sensors;
|
||||||
int i;
|
unsigned int i, j;
|
||||||
|
|
||||||
if (SDL_InitSubSystem(SDL_INIT_SENSOR) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_SENSOR) < 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -646,6 +654,41 @@ static void AttemptSensorFusion(SDL_Joystick *joystick)
|
||||||
SDL_free(sensors);
|
SDL_free(sensors);
|
||||||
}
|
}
|
||||||
SDL_QuitSubSystem(SDL_INIT_SENSOR);
|
SDL_QuitSubSystem(SDL_INIT_SENSOR);
|
||||||
|
|
||||||
|
/* SDL defines sensor orientation for phones relative to the natural
|
||||||
|
orientation, and for gamepads relative to being held in front of you.
|
||||||
|
When a phone is being used as a gamepad, its orientation changes,
|
||||||
|
so adjust sensor axes to match.
|
||||||
|
*/
|
||||||
|
if (SDL_GetDisplayNaturalOrientation(SDL_GetPrimaryDisplay()) == SDL_ORIENTATION_LANDSCAPE) {
|
||||||
|
/* When a device in landscape orientation is laid flat, the axes change
|
||||||
|
orientation as follows:
|
||||||
|
-X to +X becomes -X to +X
|
||||||
|
-Y to +Y becomes +Z to -Z
|
||||||
|
-Z to +Z becomes -Y to +Y
|
||||||
|
*/
|
||||||
|
joystick->sensor_transform[0][0] = 1.0f;
|
||||||
|
joystick->sensor_transform[1][2] = 1.0f;
|
||||||
|
joystick->sensor_transform[2][1] = -1.0f;
|
||||||
|
} else {
|
||||||
|
/* When a device in portrait orientation is rotated left and laid flat,
|
||||||
|
the axes change orientation as follows:
|
||||||
|
-X to +X becomes +Z to -Z
|
||||||
|
-Y to +Y becomes +X to -X
|
||||||
|
-Z to +Z becomes -Y to +Y
|
||||||
|
*/
|
||||||
|
joystick->sensor_transform[0][1] = -1.0f;
|
||||||
|
joystick->sensor_transform[1][2] = 1.0f;
|
||||||
|
joystick->sensor_transform[2][0] = -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invert_sensors) {
|
||||||
|
for (i = 0; i < SDL_arraysize(joystick->sensor_transform); ++i) {
|
||||||
|
for (j = 0; j < SDL_arraysize(joystick->sensor_transform[i]); ++j) {
|
||||||
|
joystick->sensor_transform[i][j] *= -1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CleanupSensorFusion(SDL_Joystick *joystick)
|
static void CleanupSensorFusion(SDL_Joystick *joystick)
|
||||||
|
@ -690,6 +733,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
|
||||||
const char *joystickname = NULL;
|
const char *joystickname = NULL;
|
||||||
const char *joystickpath = NULL;
|
const char *joystickpath = NULL;
|
||||||
SDL_JoystickPowerLevel initial_power_level;
|
SDL_JoystickPowerLevel initial_power_level;
|
||||||
|
SDL_bool invert_sensors = SDL_FALSE;
|
||||||
|
|
||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
|
|
||||||
|
@ -776,8 +820,8 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
|
||||||
joystick->is_gamepad = SDL_IsGamepad(instance_id);
|
joystick->is_gamepad = SDL_IsGamepad(instance_id);
|
||||||
|
|
||||||
/* Use system gyro and accelerometer if the gamepad doesn't have built-in sensors */
|
/* Use system gyro and accelerometer if the gamepad doesn't have built-in sensors */
|
||||||
if (ShouldAttemptSensorFusion(joystick)) {
|
if (ShouldAttemptSensorFusion(joystick, &invert_sensors)) {
|
||||||
AttemptSensorFusion(joystick);
|
AttemptSensorFusion(joystick, invert_sensors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add joystick to list */
|
/* Add joystick to list */
|
||||||
|
|
|
@ -117,6 +117,7 @@ struct SDL_Joystick
|
||||||
SDL_Sensor *accel _guarded;
|
SDL_Sensor *accel _guarded;
|
||||||
SDL_SensorID gyro_sensor _guarded;
|
SDL_SensorID gyro_sensor _guarded;
|
||||||
SDL_Sensor *gyro _guarded;
|
SDL_Sensor *gyro _guarded;
|
||||||
|
float sensor_transform[3][3] _guarded;
|
||||||
|
|
||||||
struct SDL_JoystickDriver *driver _guarded;
|
struct SDL_JoystickDriver *driver _guarded;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue