Skip to content
Permalink
Browse files
Automatically assign player indexes to game controllers, and allow ch…
…anging the player index for game controllers and joysticks.

Added the functions SDL_JoystickFromPlayerIndex(), SDL_JoystickSetPlayerIndex(), SDL_GameControllerFromPlayerIndex(), and SDL_GameControllerSetPlayerIndex()
  • Loading branch information
slouken committed Dec 21, 2019
1 parent f050309 commit 46e1377d49ddd2d25b3c2b2c23b91788093f2392
@@ -214,6 +214,11 @@ extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerOpen(int joystick_
*/
extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL_JoystickID joyid);

/**
* Return the SDL_GameController associated with a player index.
*/
extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromPlayerIndex(int player_index);

/**
* Return the name for this currently opened controller
*/
@@ -231,6 +236,11 @@ extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerGetType(SDL_Gam
*/
extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller);

/**
* Set the player index of an opened game controller
*/
extern DECLSPEC void SDLCALL SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index);

/**
* Get the USB vendor ID of an opened controller, if available.
* If the vendor ID isn't available this function returns 0.
@@ -192,7 +192,12 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index);
/**
* Return the SDL_Joystick associated with an instance id.
*/
extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID joyid);
extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID instance_id);

/**
* Return the SDL_Joystick associated with a player index.
*/
extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index);

/**
* Return the name for this currently opened joystick.
@@ -207,6 +212,11 @@ extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick * joystick);
*/
extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick);

/**
* Set the player index of an opened joystick
*/
extern DECLSPEC void SDLCALL SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index);

/**
* Return the GUID for this opened joystick
*/
@@ -733,3 +733,7 @@
#define SDL_wcsncmp SDL_wcsncmp_REAL
#define SDL_GameControllerTypeForIndex SDL_GameControllerTypeForIndex_REAL
#define SDL_GameControllerGetType SDL_GameControllerGetType_REAL
#define SDL_GameControllerFromPlayerIndex SDL_GameControllerFromPlayerIndex_REAL
#define SDL_GameControllerSetPlayerIndex SDL_GameControllerSetPlayerIndex_REAL
#define SDL_JoystickFromPlayerIndex SDL_JoystickFromPlayerIndex_REAL
#define SDL_JoystickSetPlayerIndex SDL_JoystickSetPlayerIndex_REAL
@@ -789,3 +789,7 @@ SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),r
SDL_DYNAPI_PROC(int,SDL_wcsncmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerTypeForIndex,(int a),(a),return)
SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerGetType,(SDL_GameController *a),(a),return)
SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromPlayerIndex,(int a),(a),return)
SDL_DYNAPI_PROC(void,SDL_GameControllerSetPlayerIndex,(SDL_GameController *a, int b),(a,b),)
SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromPlayerIndex,(int a),(a),return)
SDL_DYNAPI_PROC(void,SDL_JoystickSetPlayerIndex,(SDL_Joystick *a, int b),(a,b),)
@@ -1765,6 +1765,15 @@ SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller)
return SDL_JoystickGetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller));
}

/**
* Set the player index of an opened game controller
*/
void
SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index)
{
SDL_JoystickSetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller), player_index);
}

Uint16
SDL_GameControllerGetVendor(SDL_GameController * gamecontroller)
{
@@ -1809,7 +1818,7 @@ SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController * gamecontroller)


/*
* Find the SDL_GameController that owns this instance id
* Return the SDL_GameController associated with an instance id.
*/
SDL_GameController *
SDL_GameControllerFromInstanceID(SDL_JoystickID joyid)
@@ -1830,6 +1839,19 @@ SDL_GameControllerFromInstanceID(SDL_JoystickID joyid)
}


/**
* Return the SDL_GameController associated with a player index.
*/
SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index)
{
SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index);
if (joystick) {
return SDL_GameControllerFromInstanceID(joystick->instance_id);
}
return NULL;
}


/*
* Get the SDL joystick layer binding for this controller axis mapping
*/
@@ -83,6 +83,8 @@ static SDL_Joystick *SDL_joysticks = NULL;
static SDL_bool SDL_updating_joystick = SDL_FALSE;
static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
static SDL_atomic_t SDL_next_joystick_instance_id;
static int SDL_joystick_player_count = 0;
static SDL_JoystickID *SDL_joystick_players = NULL;

void
SDL_LockJoysticks(void)
@@ -100,6 +102,81 @@ SDL_UnlockJoysticks(void)
}
}

static int
SDL_FindFreePlayerIndex()
{
int player_index;

for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
if (SDL_joystick_players[player_index] == -1) {
return player_index;
}
}
return player_index;
}

static int
SDL_GetPlayerIndexForJoystickID(SDL_JoystickID instance_id)
{
int player_index;

for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
if (instance_id == SDL_joystick_players[player_index]) {
break;
}
}
if (player_index == SDL_joystick_player_count) {
player_index = -1;
}
return player_index;
}

static SDL_JoystickID
SDL_GetJoystickIDForPlayerIndex(int player_index)
{
if (player_index < 0 || player_index >= SDL_joystick_player_count) {
return -1;
}
return SDL_joystick_players[player_index];
}

static SDL_bool
SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id)
{
SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex(player_index);
SDL_JoystickDriver *driver;
int device_index;

if (player_index < 0) {
return SDL_FALSE;
}
if (player_index >= SDL_joystick_player_count) {
SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1)*sizeof(*SDL_joystick_players));
if (!new_players) {
SDL_OutOfMemory();
return SDL_FALSE;
}

SDL_joystick_players = new_players;
while (SDL_joystick_player_count <= player_index) {
SDL_joystick_players[SDL_joystick_player_count++] = -1;
}
}

SDL_joystick_players[player_index] = instance_id;

/* Update the driver with the new index */
device_index = SDL_JoystickGetDeviceIndexFromInstanceID(instance_id);
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
driver->SetDevicePlayerIndex(device_index, player_index);
}

/* Move any existing joystick to another slot */
if (existing_instance >= 0) {
SDL_SetJoystickIDForPlayerIndex(SDL_FindFreePlayerIndex(), existing_instance);
}
return SDL_TRUE;
}

static void SDLCALL
SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
@@ -228,16 +305,16 @@ SDL_JoystickNameForIndex(int device_index)
return name;
}

/*
* Get the player index of a joystick, or -1 if it's not available
*/
int
SDL_JoystickGetDevicePlayerIndex(int device_index)
{
SDL_JoystickDriver *driver;
int player_index = -1;
int player_index;

SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
player_index = driver->GetDevicePlayerIndex(device_index);
}
player_index = SDL_GetPlayerIndexForJoystickID(SDL_JoystickGetDeviceInstanceID(device_index));
SDL_UnlockJoysticks();

return player_index;
@@ -323,7 +400,6 @@ SDL_JoystickOpen(int device_index)
joystick->driver = driver;
joystick->instance_id = instance_id;
joystick->attached = SDL_TRUE;
joystick->player_index = -1;
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;

if (driver->Open(joystick, device_index) < 0) {
@@ -391,16 +467,16 @@ SDL_JoystickOpen(int device_index)
/*
* Checks to make sure the joystick is valid.
*/
int
SDL_bool
SDL_PrivateJoystickValid(SDL_Joystick * joystick)
{
int valid;
SDL_bool valid;

if (joystick == NULL) {
SDL_SetError("Joystick hasn't been opened yet");
valid = 0;
valid = SDL_FALSE;
} else {
valid = 1;
valid = SDL_TRUE;
}

return valid;
@@ -589,16 +665,36 @@ SDL_JoystickInstanceID(SDL_Joystick * joystick)
}

/*
* Find the SDL_Joystick that owns this instance id
* Return the SDL_Joystick associated with an instance id.
*/
SDL_Joystick *
SDL_JoystickFromInstanceID(SDL_JoystickID joyid)
SDL_JoystickFromInstanceID(SDL_JoystickID instance_id)
{
SDL_Joystick *joystick;

SDL_LockJoysticks();
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->instance_id == joyid) {
if (joystick->instance_id == instance_id) {
break;
}
}
SDL_UnlockJoysticks();
return joystick;
}

/**
* Return the SDL_Joystick associated with a player index.
*/
SDL_Joystick *
SDL_JoystickFromPlayerIndex(int player_index)
{
SDL_JoystickID instance_id;
SDL_Joystick *joystick;

SDL_LockJoysticks();
instance_id = SDL_GetJoystickIDForPlayerIndex(player_index);
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->instance_id == instance_id) {
break;
}
}
@@ -619,13 +715,38 @@ SDL_JoystickName(SDL_Joystick * joystick)
return SDL_FixupJoystickName(joystick->name);
}

/**
* Get the player index of an opened joystick, or -1 if it's not available
*/
int
SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick)
{
int player_index;

if (!SDL_PrivateJoystickValid(joystick)) {
return -1;
}
return joystick->player_index;

SDL_LockJoysticks();
player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id);
SDL_UnlockJoysticks();

return player_index;
}

/**
* Set the player index of an opened joystick
*/
void
SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return;
}

SDL_LockJoysticks();
SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id);
SDL_UnlockJoysticks();
}

int
@@ -718,6 +839,11 @@ SDL_JoystickQuit(void)
SDL_joystick_drivers[i]->Quit();
}

if (SDL_joystick_players) {
SDL_free(SDL_joystick_players);
SDL_joystick_players = NULL;
SDL_joystick_player_count = 0;
}
SDL_UnlockJoysticks();

#if !SDL_EVENTS_DISABLED
@@ -755,20 +881,36 @@ SDL_PrivateJoystickShouldIgnoreEvent()

void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
{
#if !SDL_EVENTS_DISABLED
SDL_Event event;
int device_index;

device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
SDL_JoystickDriver *driver;
int driver_device_index;
int player_index = -1;
int device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
if (device_index < 0) {
return;
}

event.type = SDL_JOYDEVICEADDED;
SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
player_index = driver->GetDevicePlayerIndex(driver_device_index);
}
if (player_index < 0 && SDL_IsGameController(device_index)) {
player_index = SDL_FindFreePlayerIndex();
}
if (player_index >= 0) {
SDL_SetJoystickIDForPlayerIndex(player_index, device_instance);
}
SDL_UnlockJoysticks();

if (SDL_GetEventState(event.type) == SDL_ENABLE) {
event.jdevice.which = device_index;
SDL_PushEvent(&event);
#if !SDL_EVENTS_DISABLED
{
SDL_Event event;

event.type = SDL_JOYDEVICEADDED;

if (SDL_GetEventState(event.type) == SDL_ENABLE) {
event.jdevice.which = device_index;
SDL_PushEvent(&event);
}
}
#endif /* !SDL_EVENTS_DISABLED */
}
@@ -101,7 +101,7 @@ extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick,
SDL_JoystickPowerLevel ePowerLevel);

/* Internal sanity checking functions */
extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
extern SDL_bool SDL_PrivateJoystickValid(SDL_Joystick * joystick);

#endif /* SDL_joystick_c_h_ */

0 comments on commit 46e1377

Please sign in to comment.