Added the ability to specify a gamepad type in the mapping

Also renamed most cases of SDL_GAMEPAD_TYPE_UNKNOWN to SDL_GAMEPAD_TYPE_STANDARD, and SDL_GetGamepadType() will return SDL_GAMEPAD_TYPE_UNKNOWN only if the gamepad is invalid.
main
Sam Lantinga 2023-07-17 12:14:37 -07:00
parent 57820071a4
commit b271e92c6e
14 changed files with 530 additions and 65 deletions

View File

@ -390,17 +390,14 @@ The following symbols have been renamed:
* SDL_CONTROLLER_BUTTON_TOUCHPAD => SDL_GAMEPAD_BUTTON_TOUCHPAD
* SDL_CONTROLLER_BUTTON_X => SDL_GAMEPAD_BUTTON_X
* SDL_CONTROLLER_BUTTON_Y => SDL_GAMEPAD_BUTTON_Y
* SDL_CONTROLLER_TYPE_AMAZON_LUNA => SDL_GAMEPAD_TYPE_AMAZON_LUNA
* SDL_CONTROLLER_TYPE_GOOGLE_STADIA => SDL_GAMEPAD_TYPE_GOOGLE_STADIA
* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT
* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
* SDL_CONTROLLER_TYPE_NVIDIA_SHIELD => SDL_GAMEPAD_TYPE_NVIDIA_SHIELD
* SDL_CONTROLLER_TYPE_PS3 => SDL_GAMEPAD_TYPE_PS3
* SDL_CONTROLLER_TYPE_PS4 => SDL_GAMEPAD_TYPE_PS4
* SDL_CONTROLLER_TYPE_PS5 => SDL_GAMEPAD_TYPE_PS5
* SDL_CONTROLLER_TYPE_UNKNOWN => SDL_GAMEPAD_TYPE_UNKNOWN
* SDL_CONTROLLER_TYPE_UNKNOWN => SDL_GAMEPAD_TYPE_STANDARD
* SDL_CONTROLLER_TYPE_VIRTUAL => SDL_GAMEPAD_TYPE_VIRTUAL
* SDL_CONTROLLER_TYPE_XBOX360 => SDL_GAMEPAD_TYPE_XBOX360
* SDL_CONTROLLER_TYPE_XBOXONE => SDL_GAMEPAD_TYPE_XBOXONE

View File

@ -61,6 +61,7 @@ typedef struct SDL_Gamepad SDL_Gamepad;
typedef enum
{
SDL_GAMEPAD_TYPE_UNKNOWN = 0,
SDL_GAMEPAD_TYPE_STANDARD,
SDL_GAMEPAD_TYPE_XBOX360,
SDL_GAMEPAD_TYPE_XBOXONE,
SDL_GAMEPAD_TYPE_PS3,
@ -70,6 +71,7 @@ typedef enum
SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT,
SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT,
SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR,
SDL_GAMEPAD_TYPE_MAX
} SDL_GamepadType;
/**
@ -411,6 +413,18 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceProductVersion(SDL_Joystick
*/
extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadInstanceType(SDL_JoystickID instance_id);
/**
* Get the type of a gamepad, ignoring any mapping override.
*
* This can be called before any gamepads are opened.
*
* \param instance_id the joystick instance ID
* \returns the gamepad type.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetRealGamepadInstanceType(SDL_JoystickID instance_id);
/**
* Get the mapping of a gamepad.
*
@ -481,9 +495,6 @@ extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetGamepadInstanceID(SDL_Gamepad *gam
/**
* Get the implementation-dependent name for an opened gamepad.
*
* This is the same name as returned by SDL_GetGamepadNameForIndex(), but it
* takes a gamepad identifier instead of the (unstable) device index.
*
* \param gamepad a gamepad identifier previously returned by
* SDL_OpenGamepad()
* \returns the implementation dependent name for the gamepad, or NULL if
@ -499,9 +510,6 @@ extern DECLSPEC const char *SDLCALL SDL_GetGamepadName(SDL_Gamepad *gamepad);
/**
* Get the implementation-dependent path for an opened gamepad.
*
* This is the same path as returned by SDL_GetGamepadNameForIndex(), but it
* takes a gamepad identifier instead of the (unstable) device index.
*
* \param gamepad a gamepad identifier previously returned by
* SDL_OpenGamepad()
* \returns the implementation dependent path for the gamepad, or NULL if
@ -514,18 +522,29 @@ extern DECLSPEC const char *SDLCALL SDL_GetGamepadName(SDL_Gamepad *gamepad);
extern DECLSPEC const char *SDLCALL SDL_GetGamepadPath(SDL_Gamepad *gamepad);
/**
* Get the type of this currently opened gamepad
*
* This is the same name as returned by SDL_GetGamepadInstanceType(), but it
* takes a gamepad identifier instead of the (unstable) device index.
* Get the type of an opened gamepad.
*
* \param gamepad the gamepad object to query.
* \returns the gamepad type.
* \returns the gamepad type, or SDL_GAMEPAD_TYPE_INVALID if it's not available.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetGamepadInstanceType
*/
extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadType(SDL_Gamepad *gamepad);
/**
* Get the type of an opened gamepad, ignoring any mapping override.
*
* \param gamepad the gamepad object to query.
* \returns the gamepad type, or SDL_GAMEPAD_TYPE_INVALID if it's not available.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetRealGamepadInstanceType
*/
extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetRealGamepadType(SDL_Gamepad *gamepad);
/**
* Get the player index of an opened gamepad.
*
@ -697,6 +716,39 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadEventsEnabled(void);
*/
extern DECLSPEC void SDLCALL SDL_UpdateGamepads(void);
/**
* Convert a string into SDL_GamepadType enum.
*
* This function is called internally to translate SDL_Gamepad mapping strings
* for the underlying joystick device into the consistent SDL_Gamepad mapping.
* You do not normally need to call this function unless you are parsing
* SDL_Gamepad mappings in your own code.
*
* \param str string representing a SDL_GamepadType type
* \returns the SDL_GamepadType enum corresponding to the input string, or
* `SDL_GAMEPAD_TYPE_INVALID` if no match was found.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetGamepadStringForType
*/
extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadTypeFromString(const char *str);
/**
* Convert from an SDL_GamepadType enum to a string.
*
* The caller should not SDL_free() the returned string.
*
* \param type an enum value for a given SDL_GamepadType
* \returns a string for the given type, or NULL if an invalid type is
* specified. The string returned is of the format used by
* SDL_Gamepad mapping strings.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetGamepadTypeFromString
*/
extern DECLSPEC const char *SDLCALL SDL_GetGamepadStringForType(SDL_GamepadType type);
/**
* Convert a string into SDL_GamepadAxis enum.

View File

@ -184,17 +184,14 @@
#define SDL_CONTROLLER_BUTTON_TOUCHPAD SDL_GAMEPAD_BUTTON_TOUCHPAD
#define SDL_CONTROLLER_BUTTON_X SDL_GAMEPAD_BUTTON_X
#define SDL_CONTROLLER_BUTTON_Y SDL_GAMEPAD_BUTTON_Y
#define SDL_CONTROLLER_TYPE_AMAZON_LUNA SDL_GAMEPAD_TYPE_AMAZON_LUNA
#define SDL_CONTROLLER_TYPE_GOOGLE_STADIA SDL_GAMEPAD_TYPE_GOOGLE_STADIA
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
#define SDL_CONTROLLER_TYPE_NVIDIA_SHIELD SDL_GAMEPAD_TYPE_NVIDIA_SHIELD
#define SDL_CONTROLLER_TYPE_PS3 SDL_GAMEPAD_TYPE_PS3
#define SDL_CONTROLLER_TYPE_PS4 SDL_GAMEPAD_TYPE_PS4
#define SDL_CONTROLLER_TYPE_PS5 SDL_GAMEPAD_TYPE_PS5
#define SDL_CONTROLLER_TYPE_UNKNOWN SDL_GAMEPAD_TYPE_UNKNOWN
#define SDL_CONTROLLER_TYPE_UNKNOWN SDL_GAMEPAD_TYPE_STANDARD
#define SDL_CONTROLLER_TYPE_VIRTUAL SDL_GAMEPAD_TYPE_VIRTUAL
#define SDL_CONTROLLER_TYPE_XBOX360 SDL_GAMEPAD_TYPE_XBOX360
#define SDL_CONTROLLER_TYPE_XBOXONE SDL_GAMEPAD_TYPE_XBOXONE
@ -626,17 +623,14 @@
#define SDL_CONTROLLER_BUTTON_TOUCHPAD SDL_CONTROLLER_BUTTON_TOUCHPAD_renamed_SDL_GAMEPAD_BUTTON_TOUCHPAD
#define SDL_CONTROLLER_BUTTON_X SDL_CONTROLLER_BUTTON_X_renamed_SDL_GAMEPAD_BUTTON_X
#define SDL_CONTROLLER_BUTTON_Y SDL_CONTROLLER_BUTTON_Y_renamed_SDL_GAMEPAD_BUTTON_Y
#define SDL_CONTROLLER_TYPE_AMAZON_LUNA SDL_CONTROLLER_TYPE_AMAZON_LUNA_renamed_SDL_GAMEPAD_TYPE_AMAZON_LUNA
#define SDL_CONTROLLER_TYPE_GOOGLE_STADIA SDL_CONTROLLER_TYPE_GOOGLE_STADIA_renamed_SDL_GAMEPAD_TYPE_GOOGLE_STADIA
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT_renamed_SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR_renamed_SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT_renamed_SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO_renamed_SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
#define SDL_CONTROLLER_TYPE_NVIDIA_SHIELD SDL_CONTROLLER_TYPE_NVIDIA_SHIELD_renamed_SDL_GAMEPAD_TYPE_NVIDIA_SHIELD
#define SDL_CONTROLLER_TYPE_PS3 SDL_CONTROLLER_TYPE_PS3_renamed_SDL_GAMEPAD_TYPE_PS3
#define SDL_CONTROLLER_TYPE_PS4 SDL_CONTROLLER_TYPE_PS4_renamed_SDL_GAMEPAD_TYPE_PS4
#define SDL_CONTROLLER_TYPE_PS5 SDL_CONTROLLER_TYPE_PS5_renamed_SDL_GAMEPAD_TYPE_PS5
#define SDL_CONTROLLER_TYPE_UNKNOWN SDL_CONTROLLER_TYPE_UNKNOWN_renamed_SDL_GAMEPAD_TYPE_UNKNOWN
#define SDL_CONTROLLER_TYPE_UNKNOWN SDL_CONTROLLER_TYPE_UNKNOWN_renamed_SDL_GAMEPAD_TYPE_STANDARD
#define SDL_CONTROLLER_TYPE_VIRTUAL SDL_CONTROLLER_TYPE_VIRTUAL_renamed_SDL_GAMEPAD_TYPE_VIRTUAL
#define SDL_CONTROLLER_TYPE_XBOX360 SDL_CONTROLLER_TYPE_XBOX360_renamed_SDL_GAMEPAD_TYPE_XBOX360
#define SDL_CONTROLLER_TYPE_XBOXONE SDL_CONTROLLER_TYPE_XBOXONE_renamed_SDL_GAMEPAD_TYPE_XBOXONE

View File

@ -871,6 +871,10 @@ SDL3_0.0.0 {
SDL_GetGamepadPowerLevel;
SDL_SetGamepadMapping;
SDL_strndup;
SDL_GetGamepadTypeFromString;
SDL_GetGamepadStringForType;
SDL_GetRealGamepadInstanceType;
SDL_GetRealGamepadType;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@ -897,3 +897,7 @@
#define SDL_GetGamepadPowerLevel SDL_GetGamepadPowerLevel_REAL
#define SDL_SetGamepadMapping SDL_SetGamepadMapping_REAL
#define SDL_strndup SDL_strndup_REAL
#define SDL_GetGamepadTypeFromString SDL_GetGamepadTypeFromString_REAL
#define SDL_GetGamepadStringForType SDL_GetGamepadStringForType_REAL
#define SDL_GetRealGamepadInstanceType SDL_GetRealGamepadInstanceType_REAL
#define SDL_GetRealGamepadType SDL_GetRealGamepadType_REAL

View File

@ -942,3 +942,7 @@ SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetGamepadInstanceID,(SDL_Gamepad *a),(a),ret
SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_GetGamepadPowerLevel,(SDL_Gamepad *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SetGamepadMapping,(SDL_JoystickID a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(char*,SDL_strndup,(const char *a, size_t b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadTypeFromString,(const char *a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_GetGamepadStringForType,(SDL_GamepadType a),(a),return)
SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadInstanceType,(SDL_JoystickID a),(a),return)
SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadType,(SDL_Gamepad *a),(a),return)

View File

@ -43,6 +43,8 @@
#define SDL_GAMEPAD_CRC_FIELD "crc:"
#define SDL_GAMEPAD_CRC_FIELD_SIZE 4 /* hard-coded for speed */
#define SDL_GAMEPAD_TYPE_FIELD "type:"
#define SDL_GAMEPAD_TYPE_FIELD_SIZE SDL_strlen(SDL_GAMEPAD_TYPE_FIELD)
#define SDL_GAMEPAD_PLATFORM_FIELD "platform:"
#define SDL_GAMEPAD_PLATFORM_FIELD_SIZE SDL_strlen(SDL_GAMEPAD_PLATFORM_FIELD)
#define SDL_GAMEPAD_HINT_FIELD "hint:"
@ -864,22 +866,71 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForGUID(SDL_JoystickGUID gu
return mapping;
}
static const char *map_StringForGamepadType[] = {
"unknown",
"standard",
"xbox360",
"xboxone",
"ps3",
"ps4",
"ps5",
"switchpro",
"joyconleft",
"joyconright",
"joyconpair"
};
SDL_COMPILE_TIME_ASSERT(map_StringForGamepadType, SDL_arraysize(map_StringForGamepadType) == SDL_GAMEPAD_TYPE_MAX);
/*
* convert a string to its enum equivalent
*/
SDL_GamepadType SDL_GetGamepadTypeFromString(const char *str)
{
int i;
if (str == NULL || str[0] == '\0') {
return SDL_GAMEPAD_TYPE_UNKNOWN;
}
if (*str == '+' || *str == '-') {
++str;
}
for (i = 0; i < SDL_arraysize(map_StringForGamepadType); ++i) {
if (SDL_strcasecmp(str, map_StringForGamepadType[i]) == 0) {
return (SDL_GamepadType)i;
}
}
return SDL_GAMEPAD_TYPE_UNKNOWN;
}
/*
* convert an enum to its string equivalent
*/
const char *SDL_GetGamepadStringForType(SDL_GamepadType type)
{
if (type >= SDL_GAMEPAD_TYPE_STANDARD && type < SDL_GAMEPAD_TYPE_MAX) {
return map_StringForGamepadType[type];
}
return NULL;
}
static const char *map_StringForGamepadAxis[] = {
"leftx",
"lefty",
"rightx",
"righty",
"lefttrigger",
"righttrigger",
NULL
"righttrigger"
};
SDL_COMPILE_TIME_ASSERT(map_StringForGamepadAxis, SDL_arraysize(map_StringForGamepadAxis) == SDL_GAMEPAD_AXIS_MAX);
/*
* convert a string to its enum equivalent
*/
SDL_GamepadAxis SDL_GetGamepadAxisFromString(const char *str)
{
int entry;
int i;
if (str == NULL || str[0] == '\0') {
return SDL_GAMEPAD_AXIS_INVALID;
@ -889,9 +940,9 @@ SDL_GamepadAxis SDL_GetGamepadAxisFromString(const char *str)
++str;
}
for (entry = 0; map_StringForGamepadAxis[entry]; ++entry) {
if (SDL_strcasecmp(str, map_StringForGamepadAxis[entry]) == 0) {
return (SDL_GamepadAxis)entry;
for (i = 0; i < SDL_arraysize(map_StringForGamepadAxis); ++i) {
if (SDL_strcasecmp(str, map_StringForGamepadAxis[i]) == 0) {
return (SDL_GamepadAxis)i;
}
}
return SDL_GAMEPAD_AXIS_INVALID;
@ -929,23 +980,24 @@ static const char *map_StringForGamepadButton[] = {
"paddle2",
"paddle3",
"paddle4",
"touchpad",
NULL
"touchpad"
};
SDL_COMPILE_TIME_ASSERT(map_StringForGamepadButton, SDL_arraysize(map_StringForGamepadButton) == SDL_GAMEPAD_BUTTON_MAX);
/*
* convert a string to its enum equivalent
*/
SDL_GamepadButton SDL_GetGamepadButtonFromString(const char *str)
{
int entry;
int i;
if (str == NULL || str[0] == '\0') {
return SDL_GAMEPAD_BUTTON_INVALID;
}
for (entry = 0; map_StringForGamepadButton[entry]; ++entry) {
if (SDL_strcasecmp(str, map_StringForGamepadButton[entry]) == 0) {
return (SDL_GamepadButton)entry;
for (i = 0; i < SDL_arraysize(map_StringForGamepadButton); ++i) {
if (SDL_strcasecmp(str, map_StringForGamepadButton[i]) == 0) {
return (SDL_GamepadButton)i;
}
}
return SDL_GAMEPAD_BUTTON_INVALID;
@ -2048,6 +2100,37 @@ Uint16 SDL_GetGamepadInstanceProductVersion(SDL_JoystickID instance_id)
}
SDL_GamepadType SDL_GetGamepadInstanceType(SDL_JoystickID instance_id)
{
SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN;
SDL_LockJoysticks();
{
GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id);
if (mapping != NULL) {
char *type_string, *comma;
type_string = SDL_strstr(mapping->mapping, SDL_GAMEPAD_TYPE_FIELD);
if (type_string != NULL) {
type_string += SDL_GAMEPAD_TYPE_FIELD_SIZE;
comma = SDL_strchr(type_string, ',');
if (comma != NULL) {
*comma = '\0';
type = SDL_GetGamepadTypeFromString(type_string);
*comma = ',';
}
}
}
}
SDL_UnlockJoysticks();
if (type != SDL_GAMEPAD_TYPE_UNKNOWN) {
return type;
}
return SDL_GetRealGamepadInstanceType(instance_id);
}
SDL_GamepadType SDL_GetRealGamepadInstanceType(SDL_JoystickID instance_id)
{
return SDL_GetGamepadTypeFromGUID(SDL_GetJoystickInstanceGUID(instance_id), SDL_GetJoystickInstanceName(instance_id));
}
@ -2753,6 +2836,21 @@ const char *SDL_GetGamepadPath(SDL_Gamepad *gamepad)
}
SDL_GamepadType SDL_GetGamepadType(SDL_Gamepad *gamepad)
{
SDL_JoystickID instance_id = 0;
SDL_LockJoysticks();
{
CHECK_GAMEPAD_MAGIC(gamepad, SDL_GAMEPAD_TYPE_UNKNOWN);
instance_id = gamepad->joystick->instance_id;
}
SDL_UnlockJoysticks();
return SDL_GetGamepadInstanceType(instance_id);
}
SDL_GamepadType SDL_GetRealGamepadType(SDL_Gamepad *gamepad)
{
SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);

View File

@ -2271,7 +2271,7 @@ void SDL_SetJoystickGUIDCRC(SDL_JoystickGUID *guid, Uint16 crc)
SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI)
{
SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN;
SDL_GamepadType type = SDL_GAMEPAD_TYPE_STANDARD;
if (vendor == 0x0000 && product == 0x0000) {
/* Some devices are only identifiable by their name */
@ -2284,7 +2284,7 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons
}
} else if (vendor == 0x0001 && product == 0x0001) {
type = SDL_GAMEPAD_TYPE_UNKNOWN;
type = SDL_GAMEPAD_TYPE_STANDARD;
} else if (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) {
type = SDL_GAMEPAD_TYPE_XBOXONE;
@ -2295,7 +2295,7 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
if (name && SDL_strstr(name, "NES Controller") != NULL) {
/* We don't have a type for the Nintendo Online NES Controller */
type = SDL_GAMEPAD_TYPE_UNKNOWN;
type = SDL_GAMEPAD_TYPE_STANDARD;
} else {
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
}
@ -2331,7 +2331,7 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons
if (forUI) {
type = SDL_GAMEPAD_TYPE_PS4;
} else {
type = SDL_GAMEPAD_TYPE_UNKNOWN;
type = SDL_GAMEPAD_TYPE_STANDARD;
}
break;
case k_eControllerType_SwitchProController:
@ -2342,7 +2342,7 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons
if (forUI) {
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
} else {
type = SDL_GAMEPAD_TYPE_UNKNOWN;
type = SDL_GAMEPAD_TYPE_STANDARD;
}
break;
default:
@ -2359,7 +2359,7 @@ SDL_GamepadType SDL_GetGamepadTypeFromGUID(SDL_JoystickGUID guid, const char *na
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
type = SDL_GetGamepadTypeFromVIDPID(vendor, product, name, SDL_TRUE);
if (type == SDL_GAMEPAD_TYPE_UNKNOWN) {
if (type == SDL_GAMEPAD_TYPE_STANDARD) {
if (SDL_IsJoystickXInput(guid)) {
/* This is probably an Xbox One controller */
return SDL_GAMEPAD_TYPE_XBOXONE;

View File

@ -1219,40 +1219,40 @@ static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
break;
case k_eSwitchDeviceInfoControllerType_HVCLeft:
HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (1)");
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_HVCRight:
HIDAPI_SetDeviceName(device, "Nintendo HVC Controller (2)");
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_NESLeft:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)");
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_NESRight:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)");
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_SNES:
HIDAPI_SetDeviceName(device, "Nintendo SNES Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SNES_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_N64:
HIDAPI_SetDeviceName(device, "Nintendo N64 Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_N64_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller");
HIDAPI_SetDeviceProduct(device, USB_VENDOR_NINTENDO, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER);
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
case k_eSwitchDeviceInfoControllerType_Unknown:
/* We couldn't read the device info for this controller, might not be fully compliant */
return;
default:
device->type = SDL_GAMEPAD_TYPE_UNKNOWN;
device->type = SDL_GAMEPAD_TYPE_STANDARD;
break;
}
device->guid.data[15] = ctx->m_eControllerType;

View File

@ -139,7 +139,7 @@ SDL_bool HIDAPI_SupportsPlaystationDetection(Uint16 vendor, Uint16 product)
/* If we already know the controller is a different type, don't try to detect it.
* This fixes a hang with the HORIPAD for Nintendo Switch (0x0f0d/0x00c1)
*/
if (SDL_GetGamepadTypeFromVIDPID(vendor, product, NULL, SDL_FALSE) != SDL_GAMEPAD_TYPE_UNKNOWN) {
if (SDL_GetGamepadTypeFromVIDPID(vendor, product, NULL, SDL_FALSE) != SDL_GAMEPAD_TYPE_STANDARD) {
return SDL_FALSE;
}
@ -208,7 +208,7 @@ static SDL_GamepadType SDL_GetJoystickGameControllerProtocol(const char *name, U
static const int XBONE_IFACE_SUBCLASS = 71;
static const int XBONE_IFACE_PROTOCOL = 208;
SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN;
SDL_GamepadType type = SDL_GAMEPAD_TYPE_STANDARD;
/* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
if (interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
@ -283,7 +283,7 @@ static SDL_GamepadType SDL_GetJoystickGameControllerProtocol(const char *name, U
}
}
if (type == SDL_GAMEPAD_TYPE_UNKNOWN) {
if (type == SDL_GAMEPAD_TYPE_STANDARD) {
type = SDL_GetGamepadTypeFromVIDPID(vendor, product, name, SDL_FALSE);
}
return type;
@ -1284,7 +1284,7 @@ SDL_JoystickType HIDAPI_GetJoystickTypeFromGUID(SDL_JoystickGUID guid)
SDL_GamepadType HIDAPI_GetGamepadTypeFromGUID(SDL_JoystickGUID guid)
{
SDL_HIDAPI_Device *device;
SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN;
SDL_GamepadType type = SDL_GAMEPAD_TYPE_STANDARD;
SDL_LockJoysticks();
for (device = SDL_HIDAPI_devices; device; device = device->next) {

View File

@ -71,6 +71,10 @@ def save_controller(line):
print("Controller '%s' not unique, skipping" % name)
return
pos = find_element("type", bindings)
if pos >= 0:
bindings.insert(0, bindings.pop(pos))
pos = find_element("platform", bindings)
if pos >= 0:
bindings.insert(0, bindings.pop(pos))

View File

@ -1268,6 +1268,177 @@ void DestroyGamepadDisplay(GamepadDisplay *ctx)
SDL_free(ctx);
}
struct GamepadTypeDisplay
{
SDL_Renderer *renderer;
int type_highlighted;
SDL_bool type_pressed;
int type_selected;
SDL_GamepadType real_type;
SDL_Rect area;
};
GamepadTypeDisplay *CreateGamepadTypeDisplay(SDL_Renderer *renderer)
{
GamepadTypeDisplay *ctx = SDL_calloc(1, sizeof(*ctx));
if (ctx) {
ctx->renderer = renderer;
ctx->type_highlighted = SDL_GAMEPAD_TYPE_UNSELECTED;
ctx->type_selected = SDL_GAMEPAD_TYPE_UNSELECTED;
ctx->real_type = SDL_GAMEPAD_TYPE_UNKNOWN;
}
return ctx;
}
void SetGamepadTypeDisplayArea(GamepadTypeDisplay *ctx, const SDL_Rect *area)
{
if (!ctx) {
return;
}
SDL_copyp(&ctx->area, area);
}
void SetGamepadTypeDisplayHighlight(GamepadTypeDisplay *ctx, int type, SDL_bool pressed)
{
if (!ctx) {
return;
}
ctx->type_highlighted = type;
ctx->type_pressed = pressed;
}
void SetGamepadTypeDisplaySelected(GamepadTypeDisplay *ctx, int type)
{
if (!ctx) {
return;
}
ctx->type_selected = type;
}
void SetGamepadTypeDisplayRealType(GamepadTypeDisplay *ctx, SDL_GamepadType type)
{
if (!ctx) {
return;
}
ctx->real_type = type;
}
int GetGamepadTypeDisplayAt(GamepadTypeDisplay *ctx, float x, float y)
{
int i;
const float margin = 8.0f;
const float line_height = 16.0f;
SDL_FRect highlight;
SDL_FPoint point;
if (!ctx) {
return SDL_GAMEPAD_TYPE_UNSELECTED;
}
point.x = x;
point.y = y;
x = ctx->area.x + margin;
y = ctx->area.y + margin;
for (i = SDL_GAMEPAD_TYPE_UNKNOWN; i < SDL_GAMEPAD_TYPE_MAX; ++i) {
highlight.x = x;
highlight.y = y;
highlight.w = (float)ctx->area.w - (margin * 2);
highlight.h = (float)line_height;
if (SDL_PointInRectFloat(&point, &highlight)) {
return i;
}
y += line_height;
}
return SDL_GAMEPAD_TYPE_UNSELECTED;
}
static void RenderGamepadTypeHighlight(GamepadTypeDisplay *ctx, int type, const SDL_FRect *area)
{
if (type == ctx->type_highlighted || type == ctx->type_selected) {
Uint8 r, g, b, a;
SDL_GetRenderDrawColor(ctx->renderer, &r, &g, &b, &a);
if (type == ctx->type_highlighted) {
if (ctx->type_pressed) {
SDL_SetRenderDrawColor(ctx->renderer, PRESSED_COLOR);
} else {
SDL_SetRenderDrawColor(ctx->renderer, HIGHLIGHT_COLOR);
}
} else {
SDL_SetRenderDrawColor(ctx->renderer, SELECTED_COLOR);
}
SDL_RenderFillRect(ctx->renderer, area);
SDL_SetRenderDrawColor(ctx->renderer, r, g, b, a);
}
}
void RenderGamepadTypeDisplay(GamepadTypeDisplay *ctx)
{
float x, y;
int i;
char text[128];
const float margin = 8.0f;
const float line_height = 16.0f;
SDL_FPoint dst;
SDL_FRect highlight;
if (!ctx) {
return;
}
x = ctx->area.x + margin;
y = ctx->area.y + margin;
for (i = SDL_GAMEPAD_TYPE_UNKNOWN; i < SDL_GAMEPAD_TYPE_MAX; ++i) {
highlight.x = x;
highlight.y = y;
highlight.w = (float)ctx->area.w - (margin * 2);
highlight.h = (float)line_height;
RenderGamepadTypeHighlight(ctx, i, &highlight);
if (i == SDL_GAMEPAD_TYPE_UNKNOWN) {
if (ctx->real_type == SDL_GAMEPAD_TYPE_UNKNOWN ||
ctx->real_type == SDL_GAMEPAD_TYPE_STANDARD) {
SDL_strlcpy(text, "Auto (Standard)", sizeof(text));
} else {
SDL_snprintf(text, sizeof(text), "Auto (%s)", GetGamepadTypeString(ctx->real_type));
}
} else if (i == SDL_GAMEPAD_TYPE_STANDARD) {
SDL_strlcpy(text, "Standard", sizeof(text));
} else {
SDL_strlcpy(text, GetGamepadTypeString((SDL_GamepadType)i), sizeof(text));
}
dst.x = x + margin;
dst.y = y + line_height / 2 - FONT_CHARACTER_SIZE / 2;
SDLTest_DrawString(ctx->renderer, dst.x, dst.y, text);
y += line_height;
}
}
void DestroyGamepadTypeDisplay(GamepadTypeDisplay *ctx)
{
if (!ctx) {
return;
}
SDL_free(ctx);
}
struct JoystickDisplay
{
@ -2185,13 +2356,14 @@ static char *JoinMapping(MappingParts *parts)
}
length += 1;
/* The sort order is: crc, platform, *, sdk, hint */
/* The sort order is: crc, platform, type, *, sdk, hint */
sort_order = SDL_stack_alloc(MappingSortEntry, parts->num_elements);
for (i = 0; i < parts->num_elements; ++i) {
sort_order[i].parts = parts;
sort_order[i].index = i;
}
SDL_qsort(sort_order, parts->num_elements, sizeof(*sort_order), SortMapping);
MoveSortedEntry("type", sort_order, parts->num_elements, SDL_TRUE);
MoveSortedEntry("platform", sort_order, parts->num_elements, SDL_TRUE);
MoveSortedEntry("crc", sort_order, parts->num_elements, SDL_TRUE);
MoveSortedEntry("sdk>=", sort_order, parts->num_elements, SDL_FALSE);
@ -2334,7 +2506,7 @@ static char *SetMappingValue(char *mapping, const char *key, const char *value)
return mapping;
}
static char *RemoveMappingKey(char *mapping, const char *key)
static char *RemoveMappingValue(char *mapping, const char *key)
{
MappingParts parts;
int i;
@ -2447,14 +2619,46 @@ char *SetMappingName(char *mapping, const char *name)
return RecreateMapping(&parts, mapping);
}
char *GetMappingType(const char *mapping)
const char *GetGamepadTypeString(SDL_GamepadType type)
{
return GetMappingValue(mapping, "type");
switch (type) {
case SDL_GAMEPAD_TYPE_XBOX360:
return "Xbox 360";
case SDL_GAMEPAD_TYPE_XBOXONE:
return "Xbox One";
case SDL_GAMEPAD_TYPE_PS3:
return "PS3";
case SDL_GAMEPAD_TYPE_PS4:
return "PS4";
case SDL_GAMEPAD_TYPE_PS5:
return "PS5";
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
return "Nintendo Switch";
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
return "Joy-Con (L)";
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
return "Joy-Con (R)";
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
return "Joy-Con Pair";
default:
return "";
}
}
char *SetMappingType(char *mapping, const char *type)
SDL_GamepadType GetMappingType(const char *mapping)
{
return SetMappingValue(mapping, "type", type);
return SDL_GetGamepadTypeFromString(GetMappingValue(mapping, "type"));
}
char *SetMappingType(char *mapping, SDL_GamepadType type)
{
const char *type_string = SDL_GetGamepadStringForType(type);
if (type_string == NULL || type == SDL_GAMEPAD_TYPE_UNKNOWN) {
return RemoveMappingValue(mapping, "type");
} else {
return SetMappingValue(mapping, "type", type_string);
}
}
static const char *GetElementKey(int element)
@ -2527,7 +2731,7 @@ char *SetElementBinding(char *mapping, int element, const char *binding)
if (binding) {
return SetMappingValue(mapping, GetElementKey(element), binding);
} else {
return RemoveMappingKey(mapping, GetElementKey(element));
return RemoveMappingValue(mapping, GetElementKey(element));
}
}

View File

@ -92,6 +92,24 @@ extern void SetGamepadDisplaySelected(GamepadDisplay *ctx, int element);
extern void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad);
extern void DestroyGamepadDisplay(GamepadDisplay *ctx);
/* Gamepad type display */
enum
{
SDL_GAMEPAD_TYPE_UNSELECTED = -1
};
typedef struct GamepadTypeDisplay GamepadTypeDisplay;
extern GamepadTypeDisplay *CreateGamepadTypeDisplay(SDL_Renderer *renderer);
extern void SetGamepadTypeDisplayArea(GamepadTypeDisplay *ctx, const SDL_Rect *area);
extern int GetGamepadTypeDisplayAt(GamepadTypeDisplay *ctx, float x, float y);
extern void SetGamepadTypeDisplayHighlight(GamepadTypeDisplay *ctx, int type, SDL_bool pressed);
extern void SetGamepadTypeDisplaySelected(GamepadTypeDisplay *ctx, int type);
extern void SetGamepadTypeDisplayRealType(GamepadTypeDisplay *ctx, SDL_GamepadType type);
extern void RenderGamepadTypeDisplay(GamepadTypeDisplay *ctx);
extern void DestroyGamepadTypeDisplay(GamepadTypeDisplay *ctx);
/* Joystick element display */
typedef struct JoystickDisplay JoystickDisplay;
@ -131,11 +149,14 @@ extern char *GetMappingName(const char *mapping);
/* Set the name in a mapping, freeing the mapping passed in and returning a new mapping */
extern char *SetMappingName(char *mapping, const char *name);
/* Get the friendly string for an SDL_GamepadType */
extern const char *GetGamepadTypeString(SDL_GamepadType type);
/* Return the type from a mapping, which should be freed using SDL_free(), or NULL if there is no type specified */
extern char *GetMappingType(const char *mapping);
extern SDL_GamepadType GetMappingType(const char *mapping);
/* Set the type in a mapping, freeing the mapping passed in and returning a new mapping */
extern char *SetMappingType(char *mapping, const char *type);
extern char *SetMappingType(char *mapping, SDL_GamepadType type);
/* Return true if a mapping has this element bound */
extern SDL_bool MappingHasElement(const char *mapping, int element);

View File

@ -68,6 +68,7 @@ static SDL_Renderer *screen = NULL;
static ControllerDisplayMode display_mode = CONTROLLER_MODE_TESTING;
static GamepadImage *image = NULL;
static GamepadDisplay *gamepad_elements = NULL;
static GamepadTypeDisplay *gamepad_type = NULL;
static JoystickDisplay *joystick_elements = NULL;
static GamepadButton *setup_mapping_button = NULL;
static GamepadButton *done_mapping_button = NULL;
@ -89,6 +90,9 @@ static Uint64 binding_advance_time = 0;
static SDL_FRect title_area;
static SDL_bool title_highlighted;
static SDL_bool title_pressed;
static SDL_FRect type_area;
static SDL_bool type_highlighted;
static SDL_bool type_pressed;
static char *controller_name;
static SDL_Joystick *virtual_joystick = NULL;
static SDL_GamepadAxis virtual_axis_active = SDL_GAMEPAD_AXIS_INVALID;
@ -210,8 +214,12 @@ static void ClearButtonHighlights(void)
title_highlighted = SDL_FALSE;
title_pressed = SDL_FALSE;
type_highlighted = SDL_FALSE;
type_pressed = SDL_FALSE;
ClearGamepadImage(image);
SetGamepadDisplayHighlight(gamepad_elements, SDL_GAMEPAD_ELEMENT_INVALID, SDL_FALSE);
SetGamepadTypeDisplayHighlight(gamepad_type, SDL_GAMEPAD_TYPE_UNSELECTED, SDL_FALSE);
SetGamepadButtonHighlight(setup_mapping_button, SDL_FALSE, SDL_FALSE);
SetGamepadButtonHighlight(done_mapping_button, SDL_FALSE, SDL_FALSE);
SetGamepadButtonHighlight(cancel_button, SDL_FALSE, SDL_FALSE);
@ -241,6 +249,14 @@ static void UpdateButtonHighlights(float x, float y, SDL_bool button_down)
title_pressed = SDL_FALSE;
}
if (SDL_PointInRectFloat(&point, &type_area)) {
type_highlighted = SDL_TRUE;
type_pressed = button_down;
} else {
type_highlighted = SDL_FALSE;
type_pressed = SDL_FALSE;
}
if (controller->joystick != virtual_joystick) {
gamepad_highlight_element = GetGamepadImageElementAt(image, x, y);
}
@ -249,6 +265,11 @@ static void UpdateButtonHighlights(float x, float y, SDL_bool button_down)
}
SetGamepadDisplayHighlight(gamepad_elements, gamepad_highlight_element, button_down);
if (binding_element == SDL_GAMEPAD_ELEMENT_TYPE) {
int gamepad_highlight_type = GetGamepadTypeDisplayAt(gamepad_type, x, y);
SetGamepadTypeDisplayHighlight(gamepad_type, gamepad_highlight_type, button_down);
}
joystick_highlight_element = GetJoystickDisplayElementAt(joystick_elements, controller->joystick, x, y);
SetJoystickDisplayHighlight(joystick_elements, joystick_highlight_element, button_down);
SDL_free(joystick_highlight_element);
@ -606,6 +627,19 @@ static void PasteControllerName(void)
CommitControllerName();
}
static void CommitGamepadType(SDL_GamepadType type)
{
char *mapping = NULL;
if (controller->mapping) {
mapping = SDL_strdup(controller->mapping);
} else {
mapping = NULL;
}
mapping = SetMappingType(mapping, type);
SetAndFreeGamepadMapping(mapping);
}
static const char *GetBindingInstruction(void)
{
switch (binding_element) {
@ -1097,6 +1131,7 @@ static void DrawGamepadWaiting(SDL_Renderer *renderer)
static void DrawGamepadInfo(SDL_Renderer *renderer)
{
const char *type;
const char *serial;
char text[128];
float x, y;
@ -1116,9 +1151,24 @@ static void DrawGamepadInfo(SDL_Renderer *renderer)
SDL_SetRenderDrawColor(renderer, r, g, b, a);
}
if (type_highlighted) {
Uint8 r, g, b, a;
SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);
if (type_pressed) {
SDL_SetRenderDrawColor(renderer, PRESSED_COLOR);
} else {
SDL_SetRenderDrawColor(renderer, HIGHLIGHT_COLOR);
}
SDL_RenderFillRect(renderer, &type_area);
SDL_SetRenderDrawColor(renderer, r, g, b, a);
}
if (controller_name && *controller_name) {
x = (float)SCREEN_WIDTH / 2 - (FONT_CHARACTER_SIZE * SDL_strlen(controller_name)) / 2;
y = (float)TITLE_HEIGHT / 2 - FONT_CHARACTER_SIZE / 2;
x = title_area.x + title_area.w / 2 - (FONT_CHARACTER_SIZE * SDL_strlen(controller_name)) / 2;
y = title_area.y + title_area.h / 2 - FONT_CHARACTER_SIZE / 2;
SDLTest_DrawString(renderer, x, y, controller_name);
}
@ -1129,6 +1179,11 @@ static void DrawGamepadInfo(SDL_Renderer *renderer)
SDLTest_DrawString(renderer, x, y, text);
}
type = GetGamepadTypeString(SDL_GetGamepadType(controller->gamepad));
x = type_area.x + type_area.w / 2 - (FONT_CHARACTER_SIZE * SDL_strlen(type)) / 2;
y = type_area.y + type_area.h / 2 - FONT_CHARACTER_SIZE / 2;
SDLTest_DrawString(renderer, x, y, type);
if (display_mode == CONTROLLER_MODE_TESTING) {
SDL_snprintf(text, SDL_arraysize(text), "VID: 0x%.4x PID: 0x%.4x",
SDL_GetJoystickVendor(controller->joystick),
@ -1185,6 +1240,8 @@ static void DrawBindingTips(SDL_Renderer *renderer)
if (binding_element == SDL_GAMEPAD_ELEMENT_NAME) {
text = "(press RETURN to complete)";
} else if (binding_element == SDL_GAMEPAD_ELEMENT_TYPE) {
text = "(press ESC to cancel)";
} else {
bound_A = MappingHasElement(controller->mapping, SDL_GAMEPAD_BUTTON_A);
bound_B = MappingHasElement(controller->mapping, SDL_GAMEPAD_BUTTON_B);
@ -1467,6 +1524,14 @@ static void loop(void *arg)
PasteMapping();
} else if (title_pressed) {
SetCurrentBindingElement(SDL_GAMEPAD_ELEMENT_NAME, SDL_FALSE);
} else if (type_pressed) {
SetCurrentBindingElement(SDL_GAMEPAD_ELEMENT_TYPE, SDL_FALSE);
} else if (binding_element == SDL_GAMEPAD_ELEMENT_TYPE) {
int type = GetGamepadTypeDisplayAt(gamepad_type, event.button.x, event.button.y);
if (type != SDL_GAMEPAD_TYPE_UNSELECTED) {
CommitGamepadType((SDL_GamepadType)type);
StopBinding();
}
} else {
int gamepad_element = SDL_GAMEPAD_ELEMENT_INVALID;
char *joystick_element;
@ -1599,7 +1664,12 @@ static void loop(void *arg)
}
RenderGamepadImage(image);
RenderGamepadDisplay(gamepad_elements, controller->gamepad);
if (binding_element == SDL_GAMEPAD_ELEMENT_TYPE) {
SetGamepadTypeDisplayRealType(gamepad_type, SDL_GetRealGamepadType(controller->gamepad));
RenderGamepadTypeDisplay(gamepad_type);
} else {
RenderGamepadDisplay(gamepad_elements, controller->gamepad);
}
RenderJoystickDisplay(joystick_elements, controller->joystick);
if (display_mode == CONTROLLER_MODE_TESTING) {
@ -1741,6 +1811,11 @@ int main(int argc, char *argv[])
title_area.x = (float)PANEL_WIDTH + PANEL_SPACING;
title_area.y = (float)TITLE_HEIGHT / 2 - title_area.h / 2;
type_area.w = (float)PANEL_WIDTH - 2 * BUTTON_MARGIN;
type_area.h = (float)FONT_CHARACTER_SIZE + 2 * BUTTON_MARGIN;
type_area.x = (float)BUTTON_MARGIN;
type_area.y = (float)TITLE_HEIGHT / 2 - type_area.h / 2;
image = CreateGamepadImage(screen);
if (image == NULL) {
SDL_DestroyRenderer(screen);
@ -1756,6 +1831,13 @@ int main(int argc, char *argv[])
area.h = GAMEPAD_HEIGHT;
SetGamepadDisplayArea(gamepad_elements, &area);
gamepad_type = CreateGamepadTypeDisplay(screen);
area.x = 0;
area.y = TITLE_HEIGHT;
area.w = PANEL_WIDTH;
area.h = GAMEPAD_HEIGHT;
SetGamepadTypeDisplayArea(gamepad_type, &area);
joystick_elements = CreateJoystickDisplay(screen);
area.x = PANEL_WIDTH + PANEL_SPACING + GAMEPAD_WIDTH + PANEL_SPACING;
area.y = TITLE_HEIGHT;
@ -1829,6 +1911,7 @@ int main(int argc, char *argv[])
}
DestroyGamepadImage(image);
DestroyGamepadDisplay(gamepad_elements);
DestroyGamepadTypeDisplay(gamepad_type);
DestroyJoystickDisplay(joystick_elements);
DestroyGamepadButton(copy_button);
SDL_DestroyRenderer(screen);