Cvar to set gamepad's confirm & cancel buttons

Autodetect again needs SDL 2.0.12.
Status bar has correct button prompts in gamepad binding menus.
This commit is contained in:
Jaime Moreira 2025-02-02 16:58:22 -03:00
parent 1d6d17beb3
commit 9e07dc2485
4 changed files with 141 additions and 9 deletions

View file

@ -602,6 +602,12 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
- `2`: *Playstation*, 4 & 5 format
- `3`: *Switch*, traditional Nintendo button format
* **joy_confirm**: Style of *confirm* and *cancel* buttons in menus. As
with the previous one, SDL 2.0.12 is required for `-1` to work.
- `-1`: *Autodetect*, sets to `1` if Nintendo, `0` otherwise
- `0`: SOUTH to confirm, EAST to cancel (standard style)
- `1`: EAST to confirm, SOUTH to cancel (Japanese style)
* **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

@ -94,6 +94,9 @@ 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;
// Confirm & cancel buttons' keynums
int btn_confirm = K_BTN_SOUTH, btn_cancel = K_BTN_EAST;
// Console Variables
cvar_t *freelook;
cvar_t *lookstrafe;
@ -140,6 +143,9 @@ 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;
// Gamepad style for confirm and cancel buttons (traditional or japanese)
static cvar_t *joy_confirm;
// Joystick sensitivity
static cvar_t *joy_yawsensitivity;
static cvar_t *joy_pitchsensitivity;
@ -559,6 +565,50 @@ IN_GamepadLabels_Changed(void)
}
}
/*
* Sets which gamepad button works as "confirm", and which
* works as "cancel", in menus.
*/
static void
IN_GamepadConfirm_Changed(void)
{
const int requested = (int)joy_confirm->value;
qboolean japanese_style = false;
joy_confirm->modified = false;
#if SDL_VERSION_ATLEAST(2, 0, 12)
if (requested < 0 && controller) // try to autodetect...
{
switch (SDL_GameControllerGetType(controller))
{
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)
japanese_style = true;
default:
break;
}
}
else
#endif // SDL_VERSION_ATLEAST(2, 0, 12)
if (requested == 1)
{
japanese_style = true;
}
if (japanese_style)
{
btn_confirm = K_BTN_EAST;
btn_cancel = K_BTN_SOUTH;
}
else
{
btn_confirm = K_BTN_SOUTH;
btn_cancel = K_BTN_EAST;
}
}
qboolean IN_NumpadIsOn()
{
SDL_Keymod mod = SDL_GetModState();
@ -1044,6 +1094,10 @@ IN_Update(void)
{
IN_GamepadLabels_Changed();
}
if (joy_confirm->modified)
{
IN_GamepadConfirm_Changed();
}
}
/*
@ -2354,6 +2408,7 @@ IN_Controller_Init(qboolean notify_user)
}
IN_GamepadLabels_Changed();
IN_GamepadConfirm_Changed();
}
/*
@ -2390,6 +2445,7 @@ IN_Init(void)
joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
joy_labels = Cvar_Get("joy_labels", "-1", CVAR_ARCHIVE);
joy_confirm = Cvar_Get("joy_confirm", "-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

@ -97,6 +97,9 @@ 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;
// Confirm & cancel buttons' keynums
int btn_confirm = K_BTN_SOUTH, btn_cancel = K_BTN_EAST;
// Console Variables
cvar_t *freelook;
cvar_t *lookstrafe;
@ -143,6 +146,9 @@ 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;
// Gamepad style for confirm and cancel buttons (traditional or japanese)
static cvar_t *joy_confirm;
// Joystick sensitivity
static cvar_t *joy_yawsensitivity;
static cvar_t *joy_pitchsensitivity;
@ -550,6 +556,45 @@ IN_GamepadLabels_Changed(void)
}
}
/*
* Sets which gamepad button works as "confirm", and which
* works as "cancel", in menus.
*/
static void
IN_GamepadConfirm_Changed(void)
{
const int requested = (int)joy_confirm->value;
qboolean japanese_style = false;
joy_confirm->modified = false;
if (requested < 0 && controller) // try to autodetect...
{
switch (SDL_GetGamepadType(controller))
{
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
japanese_style = true;
default:
break;
}
}
else if (requested == 1)
{
japanese_style = true;
}
if (japanese_style)
{
btn_confirm = K_BTN_EAST;
btn_cancel = K_BTN_SOUTH;
}
else
{
btn_confirm = K_BTN_SOUTH;
btn_cancel = K_BTN_EAST;
}
}
qboolean IN_NumpadIsOn()
{
SDL_Keymod mod = SDL_GetModState();
@ -1030,10 +1075,15 @@ IN_Update(void)
}
}
// Gamepad labels' type and "confirm & cancel style" change handling
if (joy_labels->modified)
{
IN_GamepadLabels_Changed();
}
if (joy_confirm->modified)
{
IN_GamepadConfirm_Changed();
}
}
/*
@ -2332,6 +2382,7 @@ IN_Controller_Init(qboolean notify_user)
SDL_free((void *)joysticks);
IN_GamepadLabels_Changed();
IN_GamepadConfirm_Changed();
}
/*
@ -2368,6 +2419,7 @@ IN_Init(void)
joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
joy_labels = Cvar_Get("joy_labels", "-1", CVAR_ARCHIVE);
joy_confirm = Cvar_Get("joy_confirm", "-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

@ -240,6 +240,8 @@ M_PushMenu(menuframework_s* menu)
cls.key_dest = key_menu;
}
extern int btn_confirm, btn_cancel;
int
Key_GetMenuKey(int key)
{
@ -280,13 +282,8 @@ Key_GetMenuKey(int key)
case K_KP_ENTER:
case K_ENTER:
case K_BTN_SOUTH:
return K_ENTER;
case K_ESCAPE:
case K_BTN_EAST:
return K_ESCAPE;
case K_KP_DEL:
if (IN_NumpadIsOn() == true) { break; }
case K_BACKSPACE:
@ -300,6 +297,15 @@ Key_GetMenuKey(int key)
return K_INS;
}
if (key == btn_confirm)
{
return K_ENTER;
}
if (key == btn_cancel)
{
return K_ESCAPE;
}
return key;
}
@ -1319,6 +1325,18 @@ M_Menu_Multiplayer_Keys_f(void)
* GAME CONTROLLER ( GAMEPAD / JOYSTICK ) BUTTONS MENU
*/
static void
GamepadMenu_StatusPrompt(menuframework_s *m)
{
static char m_gamepadbind_statusbar[64];
snprintf(m_gamepadbind_statusbar, 64, "%s assigns, %s clears, %s exits",
Key_KeynumToString_Joy(btn_confirm), Key_KeynumToString_Joy(K_BTN_NORTH),
Key_KeynumToString_Joy(btn_cancel));
Menu_SetStatusBar(m, m_gamepadbind_statusbar);
}
char *controller_bindnames[][2] =
{
{"+attack", "attack"},
@ -1432,7 +1450,7 @@ ControllerButtons_MenuInit(void)
Menu_AddItem(&s_controller_buttons_menu, (void *)&s_controller_buttons_actions[i]);
}
Menu_SetStatusBar(&s_controller_buttons_menu, "BTN_SOUTH assigns, BTN_NORTH clears, BTN_EAST exits");
GamepadMenu_StatusPrompt(&s_controller_buttons_menu);
Menu_Center(&s_controller_buttons_menu);
}
@ -1460,7 +1478,7 @@ ControllerButtons_MenuKey(int key)
Cbuf_InsertText(cmd);
}
Menu_SetStatusBar(&s_controller_buttons_menu, "BTN_SOUTH assigns, BTN_NORTH clears, BTN_EAST exits");
GamepadMenu_StatusPrompt(&s_controller_buttons_menu);
menukeyitem_bind = false;
return menu_out_sound;
}
@ -1606,7 +1624,7 @@ ControllerAltButtons_MenuInit(void)
Menu_AddItem(&s_controller_alt_buttons_menu, (void *)&s_controller_alt_buttons_actions[i]);
}
Menu_SetStatusBar(&s_controller_alt_buttons_menu, "BTN_SOUTH assigns, BTN_NORTH clears, BTN_EAST exits");
GamepadMenu_StatusPrompt(&s_controller_alt_buttons_menu);
Menu_Center(&s_controller_alt_buttons_menu);
}
@ -1635,7 +1653,7 @@ ControllerAltButtons_MenuKey(int key)
Cbuf_InsertText(cmd);
}
Menu_SetStatusBar(&s_controller_alt_buttons_menu, "BTN_SOUTH assigns, BTN_NORTH clears, BTN_EAST exits");
GamepadMenu_StatusPrompt(&s_controller_alt_buttons_menu);
menukeyitem_bind = false;
return menu_out_sound;
}