Button labels by type of Gamepad

Visible only in "customize button" menus.
Cvar set to 'autodetect' by default, which requires SDL 2.0.12
This commit is contained in:
Jaime Moreira 2025-02-02 15:49:37 -03:00
parent f995839e4b
commit 1d6d17beb3
7 changed files with 257 additions and 5 deletions

View file

@ -593,6 +593,15 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
Back / Select / Minus, or `2` = Guide / Home / PS. Requires a game
restart, or gamepad replug, when changed.
* **joy_labels**: Defines style of button labels in binding menus. Note
that binding through console only uses the SDL nomenclature (`0`).
Default is `-1`, which requires at least SDL 2.0.12 to work.
- `-1`: *Autodetect*, sets to `0` if gamepad type isn't detected
- `0`: *SDL*, face buttons appear as cardinal points
- `1`: *Xbox*, with One / Series X / S labels
- `2`: *Playstation*, 4 & 5 format
- `3`: *Switch*, traditional Nintendo button format
* **joy_layout**: Allows to select the stick layout of the gamepad.
- `0`: *Default*, left stick moves, right aims
- `1`: *Southpaw*, same as previous one with inverted sticks

View file

@ -211,7 +211,7 @@ keyname_t keynames[] = {
{NULL, 0}
};
static char * gamepadbtns[] =
static char *gamepadbtns[] =
{
// It is imperative that this list of buttons follow EXACTLY the order they
// appear in QKEYS enum in keyboard.h, which in turn is the same order as
@ -277,6 +277,81 @@ static char * gamepadbtns[] =
#define NUM_GAMEPAD_BTNS (sizeof gamepadbtns / sizeof gamepadbtns[0])
static char *gpbtns_face[] =
{
// Xbox
"A",
"B",
"X",
"Y",
"VIEW",
"XBOX",
"MENU",
"LS",
"RS",
"LB",
"RB",
// Playstation
"CROSS",
"CIRCLE",
"SQUARE",
"TRIANGLE",
"CREATE",
"PS",
"OPTIONS",
"L3",
"R3",
"L1",
"R1",
// Nintendo Switch
"B",
"A",
"Y",
"X",
"-",
"HOME",
"+",
"L stick",
"R stick",
"L btn",
"R btn",
};
static char *gpbtns_paddles[] =
{
// Xbox
"SHARE",
"P1",
"P3",
"P2",
"P4",
// Playstation
"MIC",
"RB",
"LB",
"Right Fn",
"Left Fn",
// Switch
"CAPTURE",
"Right SR",
"Left SL",
"Right SL",
"Left SR" // JoyCon btn positions suck
};
static char *gpbtns_triggers[] =
{
// Xbox
"LT",
"RT",
// Playstation
"L2",
"R2",
// Switch
"ZL",
"ZR"
};
/* ------------------------------------------------------------------ */
static void
@ -820,6 +895,49 @@ Key_KeynumToString(int keynum)
return "<UNKNOWN KEYNUM>";
}
/*
* Same as Key_KeynumToString(), but for joystick/gamepad buttons.
*/
char *
Key_KeynumToString_Joy(int key)
{
extern gamepad_labels_t joy_current_lbls;
const int lbl_style = (int)joy_current_lbls - 1;
if (key < K_JOY_FIRST_BTN)
{
return Key_KeynumToString(key);
}
// Don't print the _ALT buttons (buttons with the alt modifier pressed)
if (key >= K_JOY_FIRST_BTN_ALT)
{
key -= K_JOY_FIRST_BTN_ALT - K_JOY_FIRST_BTN;
}
if (lbl_style < 0) // was SDL
{
goto exit_sdl;
}
// Alter this logic if new gamepad buttons are added in SDL
if (key < K_DPAD_UP) // face & shoulder buttons
{
return gpbtns_face[lbl_style * (K_DPAD_UP - K_BTN_SOUTH) + key - K_BTN_SOUTH];
}
else if (key >= K_TRIG_LEFT) // triggers
{
return gpbtns_triggers[lbl_style * (K_JOY_FIRST_BTN_ALT - K_TRIG_LEFT) + key - K_TRIG_LEFT];
}
else if (key > K_DPAD_RIGHT && key < K_TOUCHPAD) // paddles & misc1
{
return gpbtns_paddles[lbl_style * (K_TOUCHPAD - K_BTN_MISC1) + key - K_BTN_MISC1];
}
exit_sdl:
return gamepadbtns[key - K_JOY_FIRST_BTN];
}
void
Key_SetBinding(int keynum, char *binding)
{

View file

@ -486,8 +486,18 @@ void CL_BaseMove (usercmd_t *cmd);
void IN_CenterView (void);
typedef enum
{
LBL_SDL = 0,
LBL_XBOX,
LBL_PLAYSTATION,
LBL_SWITCH,
LBL_MAX_COUNT
} gamepad_labels_t;
float CL_KeyState (kbutton_t *key);
char *Key_KeynumToString (int keynum);
char *Key_KeynumToString_Joy (int key);
void CL_WriteDemoMessage (void);
void CL_Stop_f (void);

View file

@ -240,6 +240,7 @@ enum QKEYS {
// Add other gamepad keys before this one, adjust from SDL 2/3 definitions, and
// add the corresponding _ALT key below! Respect the order, must be the same as above.
// Also, verify if cl_keyboard.c needs a refactor on its arrays.
K_BTN_SOUTH_ALT,
K_JOY_FIRST_BTN_ALT = K_BTN_SOUTH_ALT,

View file

@ -91,6 +91,9 @@ int sys_frame_time;
// is pressed
qboolean joy_altselector_pressed = false;
// Gamepad labels' style (Xbox, Playstation, etc.) in use, normally set after detection
gamepad_labels_t joy_current_lbls = LBL_SDL;
// Console Variables
cvar_t *freelook;
cvar_t *lookstrafe;
@ -134,6 +137,9 @@ static int last_haptic_effect_size = HAPTIC_EFFECT_LIST_SIZE;
static int last_haptic_effect_pos = 0;
static haptic_effects_cache_t last_haptic_effect[HAPTIC_EFFECT_LIST_SIZE];
// Gamepad labels' style (Xbox, Playstation, etc.) requested by user
static cvar_t *joy_labels;
// Joystick sensitivity
static cvar_t *joy_yawsensitivity;
static cvar_t *joy_pitchsensitivity;
@ -506,6 +512,53 @@ IN_TranslateScancodeToQ2Key(SDL_Scancode sc)
static void IN_Controller_Init(qboolean notify_user);
static void IN_Controller_Shutdown(qboolean notify_user);
/*
* Sets the gamepad buttons' style of labels (SDL, Xbox, PS, Switch).
* They are only visible in the gamepad binding options.
* Traditional binding uses SDL style, no matter the gamepad.
*/
static void
IN_GamepadLabels_Changed(void)
{
const int requested = (int)joy_labels->value;
joy_labels->modified = false;
joy_current_lbls = LBL_SDL;
#if SDL_VERSION_ATLEAST(2, 0, 12)
if (requested < 0 && controller) // try to autodetect...
{
switch (SDL_GameControllerGetType(controller))
{
case SDL_CONTROLLER_TYPE_XBOX360:
case SDL_CONTROLLER_TYPE_XBOXONE:
joy_current_lbls = LBL_XBOX;
return;
case SDL_CONTROLLER_TYPE_PS3:
case SDL_CONTROLLER_TYPE_PS4:
#if SDL_VERSION_ATLEAST(2, 0, 14)
case SDL_CONTROLLER_TYPE_PS5:
#endif // SDL_VERSION_ATLEAST(2, 0, 14)
joy_current_lbls = LBL_PLAYSTATION;
return;
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
#if SDL_VERSION_ATLEAST(2, 24, 0)
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
#endif // SDL_VERSION_ATLEAST(2, 24, 0)
joy_current_lbls = LBL_SWITCH;
default:
return;
}
}
else
#endif // SDL_VERSION_ATLEAST(2, 0, 12)
if (requested >= LBL_SDL && requested < LBL_MAX_COUNT)
{
joy_current_lbls = (gamepad_labels_t)requested;
}
}
qboolean IN_NumpadIsOn()
{
SDL_Keymod mod = SDL_GetModState();
@ -986,6 +1039,11 @@ IN_Update(void)
countdown_reason = REASON_NONE;
}
}
if (joy_labels->modified)
{
IN_GamepadLabels_Changed();
}
}
/*
@ -2294,6 +2352,8 @@ IN_Controller_Init(qboolean notify_user)
#endif
}
}
IN_GamepadLabels_Changed();
}
/*
@ -2329,6 +2389,7 @@ IN_Init(void)
joy_forwardsensitivity = Cvar_Get("joy_forwardsensitivity", "1.0", CVAR_ARCHIVE);
joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
joy_labels = Cvar_Get("joy_labels", "-1", CVAR_ARCHIVE);
joy_layout = Cvar_Get("joy_layout", "0", CVAR_ARCHIVE);
joy_left_expo = Cvar_Get("joy_left_expo", "2.0", CVAR_ARCHIVE);
joy_left_snapaxis = Cvar_Get("joy_left_snapaxis", "0.15", CVAR_ARCHIVE);

View file

@ -94,6 +94,9 @@ int sys_frame_time;
// is pressed
qboolean joy_altselector_pressed = false;
// Gamepad labels' style (Xbox, Playstation, etc.) in use, normally set after detection
gamepad_labels_t joy_current_lbls = LBL_SDL;
// Console Variables
cvar_t *freelook;
cvar_t *lookstrafe;
@ -137,6 +140,9 @@ static int last_haptic_effect_size = HAPTIC_EFFECT_LIST_SIZE;
static int last_haptic_effect_pos = 0;
static haptic_effects_cache_t last_haptic_effect[HAPTIC_EFFECT_LIST_SIZE];
// Gamepad labels' style (Xbox, Playstation, etc.) requested by user
static cvar_t *joy_labels;
// Joystick sensitivity
static cvar_t *joy_yawsensitivity;
static cvar_t *joy_pitchsensitivity;
@ -504,6 +510,46 @@ IN_TranslateScancodeToQ2Key(SDL_Scancode sc)
static void IN_Controller_Init(qboolean notify_user);
static void IN_Controller_Shutdown(qboolean notify_user);
/*
* Sets the gamepad buttons' style of labels (SDL, Xbox, PS, Switch).
* They are only visible in the gamepad binding options.
* Traditional binding uses SDL style, no matter the gamepad.
*/
static void
IN_GamepadLabels_Changed(void)
{
const int requested = (int)joy_labels->value;
joy_labels->modified = false;
joy_current_lbls = LBL_SDL;
if (requested < 0 && controller) // try to autodetect...
{
switch (SDL_GetGamepadType(controller))
{
case SDL_GAMEPAD_TYPE_XBOX360:
case SDL_GAMEPAD_TYPE_XBOXONE:
joy_current_lbls = LBL_XBOX;
return;
case SDL_GAMEPAD_TYPE_PS3:
case SDL_GAMEPAD_TYPE_PS4:
case SDL_GAMEPAD_TYPE_PS5:
joy_current_lbls = LBL_PLAYSTATION;
return;
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
joy_current_lbls = LBL_SWITCH;
default:
return;
}
}
else if (requested >= LBL_SDL && requested < LBL_MAX_COUNT)
{
joy_current_lbls = (gamepad_labels_t)requested;
}
}
qboolean IN_NumpadIsOn()
{
SDL_Keymod mod = SDL_GetModState();
@ -983,6 +1029,11 @@ IN_Update(void)
countdown_reason = REASON_NONE;
}
}
if (joy_labels->modified)
{
IN_GamepadLabels_Changed();
}
}
/*
@ -2280,6 +2331,7 @@ IN_Controller_Init(qboolean notify_user)
}
SDL_free((void *)joysticks);
IN_GamepadLabels_Changed();
}
/*
@ -2315,6 +2367,7 @@ IN_Init(void)
joy_forwardsensitivity = Cvar_Get("joy_forwardsensitivity", "1.0", CVAR_ARCHIVE);
joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
joy_labels = Cvar_Get("joy_labels", "-1", CVAR_ARCHIVE);
joy_layout = Cvar_Get("joy_layout", "0", CVAR_ARCHIVE);
joy_left_expo = Cvar_Get("joy_left_expo", "2.0", CVAR_ARCHIVE);
joy_left_snapaxis = Cvar_Get("joy_left_snapaxis", "0.15", CVAR_ARCHIVE);

View file

@ -1374,7 +1374,7 @@ DrawControllerButtonBindingFunc(void *self)
int x;
const char *name;
name = Key_KeynumToString(keys[0]);
name = Key_KeynumToString_Joy(keys[0]);
Menu_DrawString(a->generic.x + a->generic.parent->x + RCOLUMN_OFFSET * scale,
a->generic.y + a->generic.parent->y, name);
@ -1387,7 +1387,7 @@ DrawControllerButtonBindingFunc(void *self)
a->generic.y + a->generic.parent->y, "or");
Menu_DrawString(a->generic.x + a->generic.parent->x + 48 * scale + (x * scale),
a->generic.y + a->generic.parent->y,
Key_KeynumToString(keys[1]));
Key_KeynumToString_Joy(keys[1]));
}
}
}
@ -1548,7 +1548,7 @@ DrawControllerAltButtonBindingFunc(void *self)
size_t x;
const char *name;
name = Key_KeynumToString(keys[0]);
name = Key_KeynumToString_Joy(keys[0]);
Menu_DrawString(a->generic.x + a->generic.parent->x + RCOLUMN_OFFSET * scale,
a->generic.y + a->generic.parent->y, name);
@ -1561,7 +1561,7 @@ DrawControllerAltButtonBindingFunc(void *self)
a->generic.y + a->generic.parent->y, "or");
Menu_DrawString(a->generic.x + a->generic.parent->x + 48 * scale + (x * scale),
a->generic.y + a->generic.parent->y,
Key_KeynumToString(keys[1]));
Key_KeynumToString_Joy(keys[1]));
}
}
}