Add joy_gamepadLayout CVar to better support nintendo/PS-style gamepads

The button names shown in the controls menu now depend on this CVar.
So if you set it to 1 (Nintendo), the "A" button (which, based on its
position, would be "B" on XBox/XInput gamepads) is actually shown as
"Pad A", and if it's set to 2 (Playstation), it's shown as "Pad Cross".

The "real" names, used in the config, remain the same and are based on
position: JOY_BTN_SOUTH, JOY_BTN_EAST, JOY_BTN_WEST, JOY_BTN_NORTH
This commit is contained in:
Daniel Gibson 2024-01-17 18:54:09 +01:00
parent cf5d10f4e6
commit 86690df24e
2 changed files with 31 additions and 12 deletions

View file

@ -39,6 +39,8 @@ If you have questions concerning this license or the applicable additional terms
idCVar idSessionLocal::gui_configServerRate( "gui_configServerRate", "0", CVAR_GUI | CVAR_ARCHIVE | CVAR_ROM | CVAR_INTEGER, "" ); idCVar idSessionLocal::gui_configServerRate( "gui_configServerRate", "0", CVAR_GUI | CVAR_ARCHIVE | CVAR_ROM | CVAR_INTEGER, "" );
extern idCVar joy_gamepadLayout; // DG: used here to update bindings window when cvar is changed
// implements the setup for, and commands from, the main menu // implements the setup for, and commands from, the main menu
/* /*
@ -1209,6 +1211,14 @@ void idSessionLocal::GuiFrameEvents() {
sysEvent_t ev; sysEvent_t ev;
idUserInterface *gui; idUserInterface *gui;
// DG: if joy_gamepadLayout changes, the binding names in the main/controls menu must be updated
if ( joy_gamepadLayout.IsModified() ) {
if ( guiMainMenu != NULL ) {
guiMainMenu->SetKeyBindingNames();
}
joy_gamepadLayout.ClearModified();
}
// stop generating move and button commands when a local console or menu is active // stop generating move and button commands when a local console or menu is active
// running here so SP, async networking and no game all go through it // running here so SP, async networking and no game all go through it
if ( console->Active() || guiActive ) { if ( console->Active() || guiActive ) {

View file

@ -80,6 +80,9 @@ static idCVar in_nograb("in_nograb", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "prevents
static idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL, static idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
"if enabled, grabs all keyboard input if mouse is grabbed (so keyboard shortcuts from the OS like Alt-Tab or Windows Key won't work)"); "if enabled, grabs all keyboard input if mouse is grabbed (so keyboard shortcuts from the OS like Alt-Tab or Windows Key won't work)");
idCVar joy_gamepadLayout("joy_gamepadLayout", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_INTEGER,
"Button layout of gamepad - 0: XBox-style, 1: Nintendo-style, 2: Playstation-style", idCmdSystem::ArgCompletion_Integer<0, 2> );
// set in handleMouseGrab(), used in Sys_GetEvent() to decide what kind of internal mouse event to generate // set in handleMouseGrab(), used in Sys_GetEvent() to decide what kind of internal mouse event to generate
static bool in_relativeMouseMode = true; static bool in_relativeMouseMode = true;
// set in Sys_GetEvent() on window focus gained/lost events // set in Sys_GetEvent() on window focus gained/lost events
@ -275,9 +278,9 @@ const char* Sys_GetLocalizedJoyKeyName( int key ) {
if (key <= K_JOY_BTN_NORTH) { if (key <= K_JOY_BTN_NORTH) {
#if SDL_VERSION_ATLEAST(3, 0, 0) #if SDL_VERSION_ATLEAST(3, 0, 0)
// TODO: or use the SDL2 code and just set joy_gamepadLayout automatically based on SDL_GetGamepadType() ?
SDL_GamepadButton gpbtn = SDL_GAMEPAD_BUTTON_SOUTH + (key - K_JOY_BTN_SOUTH); SDL_GamepadButton gpbtn = SDL_GAMEPAD_BUTTON_SOUTH + (key - K_JOY_BTN_SOUTH);
SDL_GamepadButtonLabel label = SDL_GetGamepadButtonLabeForTypel(TODO, gpbtn); SDL_GamepadButtonLabel label = SDL_GetGamepadButtonLabelForType(TODO, gpbtn);
switch(label) { switch(label) {
case SDL_GAMEPAD_BUTTON_LABEL_A: case SDL_GAMEPAD_BUTTON_LABEL_A:
return "Pad A"; return "Pad A";
@ -298,16 +301,22 @@ const char* Sys_GetLocalizedJoyKeyName( int key ) {
} }
#else // SDL2 #else // SDL2
// using xbox-style names, like SDL2 does (SDL can't tell us if this is a xbox or PS or nintendo or whatever-style gamepad) // South, East, West, North
switch(key) { static const char* xboxBtnNames[4] = { "Pad A", "Pad B", "Pad X", "Pad Y" };
case K_JOY_BTN_SOUTH: static const char* nintendoBtnNames[4] = { "Pad B", "Pad A", "Pad X", "Pad Y" };
return "Pad A"; static const char* psBtnNames[4] = { "Pad Cross", "Pad Circle", "Pad Square", "Pad Triangle" };
case K_JOY_BTN_EAST:
return "Pad B"; unsigned btnIdx = key - K_JOY_BTN_SOUTH;
case K_JOY_BTN_WEST: assert(btnIdx < 4);
return "Pad X"; switch( joy_gamepadLayout.GetInteger() ) {
case K_JOY_BTN_NORTH: default:
return "Pad Y"; common->Warning( "joy_gamepadLayout has invalid value %d !\n", joy_gamepadLayout.GetInteger() );
case 0:
return xboxBtnNames[btnIdx];
case 1:
return nintendoBtnNames[btnIdx];
case 2:
return psBtnNames[btnIdx];
} }
#endif // face button names for SDL2 #endif // face button names for SDL2
} }