mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-16 09:48:26 +00:00
Use SDL_HINT_GAMECONTROLLER_SENSOR_FUSION as a list of controllers to enable sensor fusion
There are too many wraparound style controllers out there to enumerate them all, so instead make this a user option in applications that support it.
This commit is contained in:
parent
610c31c7b7
commit
d91e96e7f5
4 changed files with 112 additions and 96 deletions
|
@ -620,11 +620,18 @@ extern "C" {
|
|||
* \brief Controls whether the device's built-in accelerometer and gyro should be used as sensors for gamepads.
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
* "auto" - Sensor fusion is enabled for known wraparound controllers like the Razer Kishi and Backbone One
|
||||
* "0" - Sensor fusion is disabled
|
||||
* "1" - Sensor fusion is enabled for all controllers that lack sensors
|
||||
*
|
||||
* The default value is "auto". This hint is checked when a gamepad is opened.
|
||||
* Or the variable can be a comma separated list of USB VID/PID pairs
|
||||
* in hexadecimal form, e.g.
|
||||
*
|
||||
* 0xAAAA/0xBBBB,0xCCCC/0xDDDD
|
||||
*
|
||||
* The variable can also take the form of @file, in which case the named
|
||||
* file will be loaded and interpreted as the value of the variable.
|
||||
*
|
||||
* This hint is checked when a gamepad is opened.
|
||||
*/
|
||||
#define SDL_HINT_GAMECONTROLLER_SENSOR_FUSION "SDL_GAMECONTROLLER_SENSOR_FUSION"
|
||||
|
||||
|
|
|
@ -150,61 +150,9 @@ struct SDL_Gamepad
|
|||
return retval; \
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int num_entries;
|
||||
int max_entries;
|
||||
Uint32 *entries;
|
||||
} SDL_vidpid_list;
|
||||
|
||||
static SDL_vidpid_list SDL_allowed_gamepads;
|
||||
static SDL_vidpid_list SDL_ignored_gamepads;
|
||||
|
||||
static void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list)
|
||||
{
|
||||
Uint32 entry;
|
||||
char *spot;
|
||||
char *file = NULL;
|
||||
|
||||
list->num_entries = 0;
|
||||
|
||||
if (hint && *hint == '@') {
|
||||
spot = file = (char *)SDL_LoadFile(hint + 1, NULL);
|
||||
} else {
|
||||
spot = (char *)hint;
|
||||
}
|
||||
|
||||
if (spot == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ((spot = SDL_strstr(spot, "0x")) != NULL) {
|
||||
entry = (Uint16)SDL_strtol(spot, &spot, 0);
|
||||
entry <<= 16;
|
||||
spot = SDL_strstr(spot, "0x");
|
||||
if (spot == NULL) {
|
||||
break;
|
||||
}
|
||||
entry |= (Uint16)SDL_strtol(spot, &spot, 0);
|
||||
|
||||
if (list->num_entries == list->max_entries) {
|
||||
int max_entries = list->max_entries + 16;
|
||||
Uint32 *entries = (Uint32 *)SDL_realloc(list->entries, max_entries * sizeof(*list->entries));
|
||||
if (entries == NULL) {
|
||||
/* Out of memory, go with what we have already */
|
||||
break;
|
||||
}
|
||||
list->entries = entries;
|
||||
list->max_entries = max_entries;
|
||||
}
|
||||
list->entries[list->num_entries++] = entry;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
SDL_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_GamepadIgnoreDevicesChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_LoadVIDPIDListFromHint(hint, &SDL_ignored_gamepads);
|
||||
|
@ -2112,11 +2060,9 @@ static SDL_bool SDL_endswith(const char *string, const char *suffix)
|
|||
*/
|
||||
SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid)
|
||||
{
|
||||
int i;
|
||||
Uint16 vendor;
|
||||
Uint16 product;
|
||||
Uint16 version;
|
||||
Uint32 vidpid;
|
||||
|
||||
#ifdef __LINUX__
|
||||
if (SDL_endswith(name, " Motion Sensors")) {
|
||||
|
@ -2165,20 +2111,14 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid)
|
|||
}
|
||||
}
|
||||
|
||||
vidpid = MAKE_VIDPID(vendor, product);
|
||||
|
||||
if (SDL_allowed_gamepads.num_entries > 0) {
|
||||
for (i = 0; i < SDL_allowed_gamepads.num_entries; ++i) {
|
||||
if (vidpid == SDL_allowed_gamepads.entries[i]) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
if (SDL_VIDPIDInList(vendor, product, &SDL_allowed_gamepads)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
for (i = 0; i < SDL_ignored_gamepads.num_entries; ++i) {
|
||||
if (vidpid == SDL_ignored_gamepads.entries[i]) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
if (SDL_VIDPIDInList(vendor, product, &SDL_ignored_gamepads)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
@ -3100,14 +3040,8 @@ void SDL_QuitGamepadMappings(void)
|
|||
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT,
|
||||
SDL_GamepadIgnoreDevicesExceptChanged, NULL);
|
||||
|
||||
if (SDL_allowed_gamepads.entries) {
|
||||
SDL_free(SDL_allowed_gamepads.entries);
|
||||
SDL_zero(SDL_allowed_gamepads);
|
||||
}
|
||||
if (SDL_ignored_gamepads.entries) {
|
||||
SDL_free(SDL_ignored_gamepads.entries);
|
||||
SDL_zero(SDL_ignored_gamepads);
|
||||
}
|
||||
SDL_FreeVIDPIDList(&SDL_allowed_gamepads);
|
||||
SDL_FreeVIDPIDList(&SDL_ignored_gamepads);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -564,19 +564,8 @@ static SDL_bool IsROGAlly(SDL_Joystick *joystick)
|
|||
|
||||
static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *invert_sensors)
|
||||
{
|
||||
static Uint32 wraparound_gamepads[] = {
|
||||
MAKE_VIDPID(0x1532, 0x0709), /* Razer Junglecat (L) */
|
||||
MAKE_VIDPID(0x1532, 0x070a), /* Razer Junglecat (R) */
|
||||
MAKE_VIDPID(0x1532, 0x0717), /* Razer Edge controller */
|
||||
MAKE_VIDPID(0x1949, 0x0402), /* Ipega PG-9083S */
|
||||
MAKE_VIDPID(0x27f8, 0x0bbc), /* Gamevice */
|
||||
MAKE_VIDPID(0x27f8, 0x0bbf), /* Razer Kishi */
|
||||
};
|
||||
SDL_JoystickGUID guid;
|
||||
Uint16 vendor, product;
|
||||
Uint32 vidpid;
|
||||
int i;
|
||||
int hint;
|
||||
const char *hint;
|
||||
int hint_value;
|
||||
|
||||
*invert_sensors = SDL_FALSE;
|
||||
|
||||
|
@ -590,20 +579,28 @@ static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *inve
|
|||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
hint = SDL_GetStringInteger(SDL_GetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION), -1);
|
||||
if (hint > 0) {
|
||||
hint = SDL_GetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION);
|
||||
hint_value = SDL_GetStringInteger(hint, -1);
|
||||
if (hint_value > 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
if (hint == 0) {
|
||||
if (hint_value == 0) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* See if the controller is in our list of wraparound gamepads */
|
||||
guid = SDL_GetJoystickGUID(joystick);
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
|
||||
vidpid = MAKE_VIDPID(vendor, product);
|
||||
for (i = 0; i < SDL_arraysize(wraparound_gamepads); ++i) {
|
||||
if (vidpid == wraparound_gamepads[i]) {
|
||||
if (hint) {
|
||||
SDL_vidpid_list gamepads;
|
||||
SDL_JoystickGUID guid;
|
||||
Uint16 vendor, product;
|
||||
SDL_bool enabled;
|
||||
|
||||
/* See if the gamepad is in our list of devices to enable */
|
||||
guid = SDL_GetJoystickGUID(joystick);
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
|
||||
SDL_LoadVIDPIDListFromHint(hint, &gamepads);
|
||||
enabled = SDL_VIDPIDInList(vendor, product, &gamepads);
|
||||
SDL_FreeVIDPIDList(&gamepads);
|
||||
if (enabled) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -3263,3 +3260,69 @@ int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorT
|
|||
}
|
||||
return posted;
|
||||
}
|
||||
|
||||
void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list)
|
||||
{
|
||||
Uint32 entry;
|
||||
char *spot;
|
||||
char *file = NULL;
|
||||
|
||||
list->num_entries = 0;
|
||||
|
||||
if (hint && *hint == '@') {
|
||||
spot = file = (char *)SDL_LoadFile(hint + 1, NULL);
|
||||
} else {
|
||||
spot = (char *)hint;
|
||||
}
|
||||
|
||||
if (spot == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ((spot = SDL_strstr(spot, "0x")) != NULL) {
|
||||
entry = (Uint16)SDL_strtol(spot, &spot, 0);
|
||||
entry <<= 16;
|
||||
spot = SDL_strstr(spot, "0x");
|
||||
if (spot == NULL) {
|
||||
break;
|
||||
}
|
||||
entry |= (Uint16)SDL_strtol(spot, &spot, 0);
|
||||
|
||||
if (list->num_entries == list->max_entries) {
|
||||
int max_entries = list->max_entries + 16;
|
||||
Uint32 *entries = (Uint32 *)SDL_realloc(list->entries, max_entries * sizeof(*list->entries));
|
||||
if (entries == NULL) {
|
||||
/* Out of memory, go with what we have already */
|
||||
break;
|
||||
}
|
||||
list->entries = entries;
|
||||
list->max_entries = max_entries;
|
||||
}
|
||||
list->entries[list->num_entries++] = entry;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
SDL_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_list *list)
|
||||
{
|
||||
int i;
|
||||
Uint32 vidpid = MAKE_VIDPID(vendor_id, product_id);
|
||||
|
||||
for (i = 0; i < list->num_entries; ++i) {
|
||||
if (vidpid == list->entries[i]) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
void SDL_FreeVIDPIDList(SDL_vidpid_list *list)
|
||||
{
|
||||
if (list->entries) {
|
||||
SDL_free(list->entries);
|
||||
SDL_zerop(list);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,18 @@ typedef struct SDL_GamepadMapping
|
|||
extern SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(SDL_JoystickID instance_id,
|
||||
SDL_GamepadMapping *out);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int num_entries;
|
||||
int max_entries;
|
||||
Uint32 *entries;
|
||||
} SDL_vidpid_list;
|
||||
|
||||
extern void SDL_LoadVIDPIDListFromHint(const char *hint, SDL_vidpid_list *list);
|
||||
extern SDL_bool SDL_VIDPIDInList(Uint16 vendor_id, Uint16 product_id, const SDL_vidpid_list *list);
|
||||
extern void SDL_FreeVIDPIDList(SDL_vidpid_list *list);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue