From 9e50048ab6247283def1b5fe332f7a3f8ad97984 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 13 Sep 2023 22:42:47 -0700
Subject: [PATCH] Revert "Removed SDL_GamepadBinding from the API"
This reverts commit eb0955ef89a1917b93da86d9b4b6fdf67cd61a8c.
---
docs/README-migration.md | 4 -
include/SDL3/SDL_gamepad.h | 57 ++++++++++++
src/dynapi/SDL_dynapi.sym | 2 +
src/dynapi/SDL_dynapi_overrides.h | 2 +
src/dynapi/SDL_dynapi_procs.h | 2 +
src/joystick/SDL_gamepad.c | 143 ++++++++++++++++++++----------
6 files changed, 160 insertions(+), 50 deletions(-)
diff --git a/docs/README-migration.md b/docs/README-migration.md
index 5095f98d88c6..52e4b0b93b2b 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -374,8 +374,6 @@ The SDL_EVENT_GAMEPAD_ADDED event now provides the joystick instance ID in the w
The functions SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads.
-The gamepad binding structure has been removed in favor of exchanging bindings in text format.
-
SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_GAMEPAD_SENSOR_UPDATE events.
SDL_CONTROLLER_TYPE_VIRTUAL has been removed, so virtual controllers can emulate other gamepad types. If you need to know whether a controller is virtual, you can use SDL_IsJoystickVirtual().
@@ -471,8 +469,6 @@ The following functions have been renamed:
The following functions have been removed:
* SDL_GameControllerEventState() - replaced with SDL_SetGamepadEventsEnabled() and SDL_GamepadEventsEnabled()
-* SDL_GameControllerGetBindForAxis()
-* SDL_GameControllerGetBindForButton()
* SDL_GameControllerMappingForDeviceIndex() - replaced with SDL_GetGamepadInstanceMapping()
* SDL_GameControllerNameForIndex() - replaced with SDL_GetGamepadInstanceName()
* SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadInstancePath()
diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h
index 484aee49fcd0..a804ed650497 100644
--- a/include/SDL3/SDL_gamepad.h
+++ b/include/SDL3/SDL_gamepad.h
@@ -125,6 +125,33 @@ typedef enum
SDL_GAMEPAD_AXIS_MAX
} SDL_GamepadAxis;
+typedef enum
+{
+ SDL_GAMEPAD_BINDTYPE_NONE = 0,
+ SDL_GAMEPAD_BINDTYPE_BUTTON,
+ SDL_GAMEPAD_BINDTYPE_AXIS,
+ SDL_GAMEPAD_BINDTYPE_HAT
+} SDL_GamepadBindingType;
+
+/**
+ * Get the SDL joystick layer binding for this gamepad button/axis mapping
+ */
+typedef struct SDL_GamepadBinding
+{
+ SDL_GamepadBindingType bindType;
+ union
+ {
+ int button;
+ int axis;
+ struct {
+ int hat;
+ int hat_mask;
+ } hat;
+ } value;
+
+} SDL_GamepadBinding;
+
+
/**
* Add support for gamepads that SDL is unaware of or change the binding of an
* existing gamepad.
@@ -819,6 +846,21 @@ extern DECLSPEC SDL_GamepadAxis SDLCALL SDL_GetGamepadAxisFromString(const char
*/
extern DECLSPEC const char* SDLCALL SDL_GetGamepadStringForAxis(SDL_GamepadAxis axis);
+/**
+ * Get the SDL joystick layer binding for a gamepad axis mapping.
+ *
+ * \param gamepad a gamepad
+ * \param axis an axis enum value (one of the SDL_GamepadAxis values)
+ * \returns a SDL_GamepadBinding describing the bind. On failure (like the
+ * given Controller axis doesn't exist on the device), its
+ * `.bindType` will be `SDL_GAMEPAD_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetGamepadBindForButton
+ */
+extern DECLSPEC SDL_GamepadBinding SDLCALL SDL_GetGamepadBindForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis);
+
/**
* Query whether a gamepad has a given axis.
*
@@ -884,6 +926,21 @@ extern DECLSPEC SDL_GamepadButton SDLCALL SDL_GetGamepadButtonFromString(const c
*/
extern DECLSPEC const char* SDLCALL SDL_GetGamepadStringForButton(SDL_GamepadButton button);
+/**
+ * Get the SDL joystick layer binding for a gamepad button mapping.
+ *
+ * \param gamepad a gamepad
+ * \param button an button enum value (an SDL_GamepadButton value)
+ * \returns a SDL_GamepadBinding describing the bind. On failure (like the
+ * given Controller button doesn't exist on the device), its
+ * `.bindType` will be `SDL_GAMEPAD_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetGamepadBindForAxis
+ */
+extern DECLSPEC SDL_GamepadBinding SDLCALL SDL_GetGamepadBindForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button);
+
/**
* Query whether a gamepad has a given button.
*
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index 60366b050030..ac044bf10d46 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -172,6 +172,8 @@ SDL3_0.0.0 {
SDL_GetGamepadAppleSFSymbolsNameForButton;
SDL_GetGamepadAxis;
SDL_GetGamepadAxisFromString;
+ SDL_GetGamepadBindForAxis;
+ SDL_GetGamepadBindForButton;
SDL_GetGamepadButton;
SDL_GetGamepadButtonFromString;
SDL_GetGamepadFirmwareVersion;
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index bd97d523d23f..d5237abe2241 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -196,6 +196,8 @@
#define SDL_GetGamepadAppleSFSymbolsNameForButton SDL_GetGamepadAppleSFSymbolsNameForButton_REAL
#define SDL_GetGamepadAxis SDL_GetGamepadAxis_REAL
#define SDL_GetGamepadAxisFromString SDL_GetGamepadAxisFromString_REAL
+#define SDL_GetGamepadBindForAxis SDL_GetGamepadBindForAxis_REAL
+#define SDL_GetGamepadBindForButton SDL_GetGamepadBindForButton_REAL
#define SDL_GetGamepadButton SDL_GetGamepadButton_REAL
#define SDL_GetGamepadButtonFromString SDL_GetGamepadButtonFromString_REAL
#define SDL_GetGamepadFirmwareVersion SDL_GetGamepadFirmwareVersion_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 71eba0275e06..4f2212bcf3ff 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -271,6 +271,8 @@ SDL_DYNAPI_PROC(const char*,SDL_GetGamepadAppleSFSymbolsNameForAxis,(SDL_Gamepad
SDL_DYNAPI_PROC(const char*,SDL_GetGamepadAppleSFSymbolsNameForButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return)
SDL_DYNAPI_PROC(Sint16,SDL_GetGamepadAxis,(SDL_Gamepad *a, SDL_GamepadAxis b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GamepadAxis,SDL_GetGamepadAxisFromString,(const char *a),(a),return)
+SDL_DYNAPI_PROC(SDL_GamepadBinding,SDL_GetGamepadBindForAxis,(SDL_Gamepad *a, SDL_GamepadAxis b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GamepadBinding,SDL_GetGamepadBindForButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return)
SDL_DYNAPI_PROC(Uint8,SDL_GetGamepadButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GamepadButton,SDL_GetGamepadButtonFromString,(const char *a),(a),return)
SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadFirmwareVersion,(SDL_Gamepad *a),(a),return)
diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c
index 00b6e9287362..2dfbcdea2021 100644
--- a/src/joystick/SDL_gamepad.c
+++ b/src/joystick/SDL_gamepad.c
@@ -57,14 +57,6 @@
static SDL_bool SDL_gamepads_initialized;
static SDL_Gamepad *SDL_gamepads SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
-typedef enum
-{
- SDL_GAMEPAD_BINDTYPE_NONE = 0,
- SDL_GAMEPAD_BINDTYPE_BUTTON,
- SDL_GAMEPAD_BINDTYPE_AXIS,
- SDL_GAMEPAD_BINDTYPE_HAT
-} SDL_GamepadBindingType;
-
typedef struct
{
SDL_GamepadBindingType inputType;
@@ -101,7 +93,7 @@ typedef struct
} output;
-} SDL_GamepadBinding;
+} SDL_ExtendedGamepadBind;
/* our hard coded list of mapping support */
typedef enum
@@ -155,8 +147,8 @@ struct SDL_Gamepad
const char *name _guarded;
GamepadMapping_t *mapping _guarded;
int num_bindings _guarded;
- SDL_GamepadBinding *bindings _guarded;
- SDL_GamepadBinding **last_match_axis _guarded;
+ SDL_ExtendedGamepadBind *bindings _guarded;
+ SDL_ExtendedGamepadBind **last_match_axis _guarded;
Uint8 *last_hat_mask _guarded;
Uint64 guide_button_down _guarded;
@@ -192,7 +184,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id
static int SDL_SendGamepadAxis(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadAxis axis, Sint16 value);
static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadButton button, Uint8 state);
-static SDL_bool HasSameOutput(SDL_GamepadBinding *a, SDL_GamepadBinding *b)
+static SDL_bool HasSameOutput(SDL_ExtendedGamepadBind *a, SDL_ExtendedGamepadBind *b)
{
if (a->outputType != b->outputType) {
return SDL_FALSE;
@@ -205,7 +197,7 @@ static SDL_bool HasSameOutput(SDL_GamepadBinding *a, SDL_GamepadBinding *b)
}
}
-static void ResetOutput(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadBinding *bind)
+static void ResetOutput(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_ExtendedGamepadBind *bind)
{
if (bind->outputType == SDL_GAMEPAD_BINDTYPE_AXIS) {
SDL_SendGamepadAxis(timestamp, gamepad, bind->output.axis.axis, 0);
@@ -217,14 +209,14 @@ static void ResetOutput(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadBindi
static void HandleJoystickAxis(Uint64 timestamp, SDL_Gamepad *gamepad, int axis, int value)
{
int i;
- SDL_GamepadBinding *last_match;
- SDL_GamepadBinding *match = NULL;
+ SDL_ExtendedGamepadBind *last_match;
+ SDL_ExtendedGamepadBind *match = NULL;
SDL_AssertJoysticksLocked();
last_match = gamepad->last_match_axis[axis];
for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS &&
axis == binding->input.axis.axis) {
if (binding->input.axis.axis_min < binding->input.axis.axis_max) {
@@ -276,7 +268,7 @@ static void HandleJoystickButton(Uint64 timestamp, SDL_Gamepad *gamepad, int but
SDL_AssertJoysticksLocked();
for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
if (binding->inputType == SDL_GAMEPAD_BINDTYPE_BUTTON &&
button == binding->input.button) {
if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS) {
@@ -300,7 +292,7 @@ static void HandleJoystickHat(Uint64 timestamp, SDL_Gamepad *gamepad, int hat, U
last_mask = gamepad->last_hat_mask[hat];
changed_mask = (last_mask ^ value);
for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
if (binding->inputType == SDL_GAMEPAD_BINDTYPE_HAT && hat == binding->input.hat.hat) {
if ((changed_mask & binding->input.hat.hat_mask) != 0) {
if (value & binding->input.hat.hat_mask) {
@@ -1164,7 +1156,7 @@ const char *SDL_GetGamepadStringForButton(SDL_GamepadButton button)
*/
static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGameButton, const char *szJoystickButton)
{
- SDL_GamepadBinding bind;
+ SDL_ExtendedGamepadBind bind;
SDL_GamepadButton button;
SDL_GamepadAxis axis;
SDL_bool invert_input = SDL_FALSE;
@@ -1244,7 +1236,7 @@ static int SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szGa
}
++gamepad->num_bindings;
- gamepad->bindings = (SDL_GamepadBinding *)SDL_realloc(gamepad->bindings, gamepad->num_bindings * sizeof(*gamepad->bindings));
+ gamepad->bindings = (SDL_ExtendedGamepadBind *)SDL_realloc(gamepad->bindings, gamepad->num_bindings * sizeof(*gamepad->bindings));
if (!gamepad->bindings) {
gamepad->num_bindings = 0;
return SDL_OutOfMemory();
@@ -1323,7 +1315,7 @@ static void SDL_PrivateLoadButtonMapping(SDL_Gamepad *gamepad, GamepadMapping_t
/* Set the zero point for triggers */
for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS &&
binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS &&
(binding->output.axis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER ||
@@ -2486,7 +2478,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id)
}
if (gamepad->joystick->naxes) {
- gamepad->last_match_axis = (SDL_GamepadBinding **)SDL_calloc(gamepad->joystick->naxes, sizeof(*gamepad->last_match_axis));
+ gamepad->last_match_axis = (SDL_ExtendedGamepadBind **)SDL_calloc(gamepad->joystick->naxes, sizeof(*gamepad->last_match_axis));
if (!gamepad->last_match_axis) {
SDL_OutOfMemory();
SDL_CloseJoystick(gamepad->joystick);
@@ -2534,25 +2526,17 @@ void SDL_UpdateGamepads(void)
*/
SDL_bool SDL_GamepadHasAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis)
{
- SDL_bool retval = SDL_FALSE;
+ SDL_GamepadBinding bind;
SDL_LockJoysticks();
{
- int i;
-
CHECK_GAMEPAD_MAGIC(gamepad, SDL_FALSE);
- for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
- if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS && binding->output.axis.axis == axis) {
- retval = SDL_TRUE;
- break;
- }
- }
+ bind = SDL_GetGamepadBindForAxis(gamepad, axis);
}
SDL_UnlockJoysticks();
- return retval;
+ return (bind.bindType != SDL_GAMEPAD_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE;
}
/*
@@ -2569,7 +2553,7 @@ Sint16 SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis)
CHECK_GAMEPAD_MAGIC(gamepad, 0);
for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS && binding->output.axis.axis == axis) {
int value = 0;
SDL_bool valid_input_range;
@@ -2625,25 +2609,17 @@ Sint16 SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis)
*/
SDL_bool SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_GamepadButton button)
{
- SDL_bool retval = SDL_FALSE;
+ SDL_GamepadBinding bind;
SDL_LockJoysticks();
{
- int i;
-
CHECK_GAMEPAD_MAGIC(gamepad, SDL_FALSE);
- for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
- if (binding->outputType == SDL_GAMEPAD_BINDTYPE_BUTTON && binding->output.button == button) {
- retval = SDL_TRUE;
- break;
- }
- }
+ bind = SDL_GetGamepadBindForButton(gamepad, button);
}
SDL_UnlockJoysticks();
- return retval;
+ return (bind.bindType != SDL_GAMEPAD_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE;
}
/*
@@ -2660,7 +2636,7 @@ Uint8 SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button)
CHECK_GAMEPAD_MAGIC(gamepad, 0);
for (i = 0; i < gamepad->num_bindings; ++i) {
- SDL_GamepadBinding *binding = &gamepad->bindings[i];
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
if (binding->outputType == SDL_GAMEPAD_BINDTYPE_BUTTON && binding->output.button == button) {
if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS) {
SDL_bool valid_input_range;
@@ -3180,6 +3156,81 @@ SDL_Gamepad *SDL_GetGamepadFromPlayerIndex(int player_index)
return retval;
}
+/*
+ * Get the SDL joystick layer binding for this gamepad axis mapping
+ */
+SDL_GamepadBinding SDL_GetGamepadBindForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis)
+{
+ SDL_GamepadBinding bind;
+
+ SDL_zero(bind);
+
+ SDL_LockJoysticks();
+ {
+ CHECK_GAMEPAD_MAGIC(gamepad, bind);
+
+ if (axis != SDL_GAMEPAD_AXIS_INVALID) {
+ int i;
+ for (i = 0; i < gamepad->num_bindings; ++i) {
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
+ if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS && binding->output.axis.axis == axis) {
+ bind.bindType = binding->inputType;
+ if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS) {
+ /* FIXME: There might be multiple axes bound now that we have axis ranges... */
+ bind.value.axis = binding->input.axis.axis;
+ } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_BUTTON) {
+ bind.value.button = binding->input.button;
+ } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_HAT) {
+ bind.value.hat.hat = binding->input.hat.hat;
+ bind.value.hat.hat_mask = binding->input.hat.hat_mask;
+ }
+ break;
+ }
+ }
+ }
+ }
+ SDL_UnlockJoysticks();
+
+ return bind;
+}
+
+/*
+ * Get the SDL joystick layer binding for this gamepad button mapping
+ */
+SDL_GamepadBinding SDL_GetGamepadBindForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button)
+{
+ SDL_GamepadBinding bind;
+
+ SDL_zero(bind);
+
+ SDL_LockJoysticks();
+ {
+ CHECK_GAMEPAD_MAGIC(gamepad, bind);
+
+ if (button != SDL_GAMEPAD_BUTTON_INVALID) {
+ int i;
+ for (i = 0; i < gamepad->num_bindings; ++i) {
+ SDL_ExtendedGamepadBind *binding = &gamepad->bindings[i];
+ if (binding->outputType == SDL_GAMEPAD_BINDTYPE_BUTTON && binding->output.button == button) {
+ bind.bindType = binding->inputType;
+ if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS) {
+ bind.value.axis = binding->input.axis.axis;
+ } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_BUTTON) {
+ bind.value.button = binding->input.button;
+ } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_HAT) {
+ bind.value.hat.hat = binding->input.hat.hat;
+ bind.value.hat.hat_mask = binding->input.hat.hat_mask;
+ }
+ break;
+ }
+ }
+ }
+ }
+ SDL_UnlockJoysticks();
+
+ return bind;
+}
+
int SDL_RumbleGamepad(SDL_Gamepad *gamepad, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{
SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);