Merge pull request #1183 from protocultor/sdl3_buttons

Consistent binding between multiple gamepad types + labels by style
This commit is contained in:
Yamagi 2025-02-08 16:55:59 +01:00 committed by GitHub
commit 4fe0d0be6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 681 additions and 223 deletions

View file

@ -581,18 +581,33 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
* **sw_colorlight**: enable experimental color lighting.
## Game Controller
## Gamepad
* **in_initjoy**: Toggles initialization of game controller. Default is
`1`, which enables gamepad usage; `0` disables its detection at
startup. Can only be set from command line.
* **in_sdlbackbutton**: Defines which button is used in the gamepad as
* **joy_escbutton**: Defines which button is used in the gamepad as
the `Esc` key, to pull the main menu and 'cancel' / 'go back' on its
options. Valid values are `0` = Back / Select / Minus, `1` = Start /
Menu / Plus (default), or `2` = Guide / Home / PS. Requires a game
options. Valid values are `0` = Start / Menu / Plus (default), `1` =
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_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

@ -139,62 +139,6 @@ keyname_t keynames[] = {
{"MWHEELUP", K_MWHEELUP},
{"MWHEELDOWN", K_MWHEELDOWN},
{"BTN_A", K_BTN_A},
{"BTN_B", K_BTN_B},
{"BTN_X", K_BTN_X},
{"BTN_Y", K_BTN_Y},
{"STICK_LEFT", K_STICK_LEFT},
{"STICK_RIGHT", K_STICK_RIGHT},
{"SHOULDR_LEFT", K_SHOULDER_LEFT},
{"SHOULDR_RIGHT", K_SHOULDER_RIGHT},
{"TRIG_LEFT", K_TRIG_LEFT},
{"TRIG_RIGHT", K_TRIG_RIGHT},
{"DP_UP", K_DPAD_UP},
{"DP_DOWN", K_DPAD_DOWN},
{"DP_LEFT", K_DPAD_LEFT},
{"DP_RIGHT", K_DPAD_RIGHT},
{"PADDLE_1", K_PADDLE_1},
{"PADDLE_2", K_PADDLE_2},
{"PADDLE_3", K_PADDLE_3},
{"PADDLE_4", K_PADDLE_4},
{"BTN_MISC1", K_BTN_MISC1},
{"TOUCHPAD", K_TOUCHPAD},
{"BTN_BACK", K_BTN_BACK},
{"BTN_GUIDE", K_BTN_GUIDE},
{"BTN_START", K_BTN_START},
// virtual keys you get by pressing the corresponding normal joy key
// and the altselector key
{"BTN_A_ALT", K_BTN_A_ALT},
{"BTN_B_ALT", K_BTN_B_ALT},
{"BTN_X_ALT", K_BTN_X_ALT},
{"BTN_Y_ALT", K_BTN_Y_ALT},
{"STICK_LEFT_ALT", K_STICK_LEFT_ALT},
{"STICK_RIGHT_ALT", K_STICK_RIGHT_ALT},
{"SHOULDR_LEFT_ALT", K_SHOULDER_LEFT_ALT},
{"SHOULDR_RIGHT_ALT", K_SHOULDER_RIGHT_ALT},
{"TRIG_LEFT_ALT", K_TRIG_LEFT_ALT},
{"TRIG_RIGHT_ALT", K_TRIG_RIGHT_ALT},
{"DP_UP_ALT", K_DPAD_UP_ALT},
{"DP_DOWN_ALT", K_DPAD_DOWN_ALT},
{"DP_LEFT_ALT", K_DPAD_LEFT_ALT},
{"DP_RIGHT_ALT", K_DPAD_RIGHT_ALT},
{"PADDLE_1_ALT", K_PADDLE_1_ALT},
{"PADDLE_2_ALT", K_PADDLE_2_ALT},
{"PADDLE_3_ALT", K_PADDLE_3_ALT},
{"PADDLE_4_ALT", K_PADDLE_4_ALT},
{"BTN_MISC1_ALT", K_BTN_MISC1_ALT},
{"TOUCHPAD_ALT", K_TOUCHPAD_ALT},
{"BTN_BACK_ALT", K_BTN_BACK_ALT},
{"BTN_GUIDE_ALT", K_BTN_GUIDE_ALT},
{"BTN_START_ALT", K_BTN_START_ALT},
{"JOY_BACK", K_JOY_BACK},
{"SUPER", K_SUPER},
{"COMPOSE", K_COMPOSE},
{"MODE", K_MODE},
@ -267,6 +211,147 @@ keyname_t keynames[] = {
{NULL, 0}
};
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
// they appear in SDL_GamepadButton / SDL_GameControllerButton enum.
"BTN_SOUTH",
"BTN_EAST",
"BTN_WEST",
"BTN_NORTH",
"BTN_BACK",
"BTN_GUIDE",
"BTN_START",
"STICK_LEFT",
"STICK_RIGHT",
"SHOULDR_LEFT",
"SHOULDR_RIGHT",
"DP_UP",
"DP_DOWN",
"DP_LEFT",
"DP_RIGHT",
"BTN_MISC1",
"PADDL_RIGHT1",
"PADDL_LEFT1",
"PADDL_RIGHT2",
"PADDL_LEFT2",
"TOUCHPAD",
"BTN_MISC2",
"BTN_MISC3",
"BTN_MISC4",
"BTN_MISC5",
"BTN_MISC6",
"TRIG_LEFT",
"TRIG_RIGHT",
// Same with _ALT buttons ( button + 'alt modifier' pressed )
"BTN_SOUTH_ALT",
"BTN_EAST_ALT",
"BTN_WEST_ALT",
"BTN_NORTH_ALT",
"BTN_BACK_ALT",
"BTN_GUIDE_ALT",
"BTN_START_ALT",
"STICK_LEFT_ALT",
"STICK_RIGHT_ALT",
"SHOULDR_LEFT_ALT",
"SHOULDR_RIGHT_ALT",
"DP_UP_ALT",
"DP_DOWN_ALT",
"DP_LEFT_ALT",
"DP_RIGHT_ALT",
"BTN_MISC1_ALT",
"PADDL_RIGHT1_ALT",
"PADDL_LEFT1_ALT",
"PADDL_RIGHT2_ALT",
"PADDL_LEFT2_ALT",
"TOUCHPAD_ALT",
"BTN_MISC2_ALT",
"BTN_MISC3_ALT",
"BTN_MISC4_ALT",
"BTN_MISC5_ALT",
"BTN_MISC6_ALT",
"TRIG_LEFT_ALT",
"TRIG_RIGHT_ALT"
};
#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
@ -739,6 +824,7 @@ static int
Key_StringToKeynum(char *str)
{
keyname_t *kn;
int i;
if (!str || !str[0])
{
@ -758,6 +844,14 @@ Key_StringToKeynum(char *str)
}
}
for (i = 0; i < NUM_GAMEPAD_BTNS; i++)
{
if (!Q_stricmp(str, gamepadbtns[i]))
{
return K_JOY_FIRST_BTN + i;
}
}
return -1;
}
@ -785,6 +879,11 @@ Key_KeynumToString(int keynum)
return tinystr;
}
if (keynum >= K_JOY_FIRST_BTN) // gamepad button
{
return gamepadbtns[keynum - K_JOY_FIRST_BTN];
}
for (kn = keynames; kn->name; kn++)
{
if (keynum == kn->keynum)
@ -796,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)
{
@ -885,7 +1027,7 @@ Key_Bind_f(void)
}
/* don't allow binding escape or the special console keys */
if(b == K_ESCAPE || b == '^' || b == '`' || b == '~' || b == K_JOY_BACK)
if(b == K_ESCAPE || b == '^' || b == '`' || b == '~')
{
if(doneWithDefaultCfg)
{
@ -1203,12 +1345,12 @@ Key_Event(int key, qboolean down, qboolean special)
unsigned int time = Sys_Milliseconds();
// evil hack for the joystick key altselector, which turns K_BTN_x into K_BTN_x_ALT
if(joy_altselector_pressed && key >= K_JOY_FIRST_REGULAR && key <= K_JOY_LAST_REGULAR)
if(joy_altselector_pressed && key >= K_JOY_FIRST_BTN && key < K_JOY_FIRST_BTN_ALT)
{
// make sure key is not the altselector itself (which we won't turn into *_ALT)
if(keybindings[key] == NULL || strcmp(keybindings[key], "+joyaltselector") != 0)
{
int altkey = key + (K_JOY_FIRST_REGULAR_ALT - K_JOY_FIRST_REGULAR);
int altkey = key + (K_JOY_FIRST_BTN_ALT - K_JOY_FIRST_BTN);
// allow fallback to binding with non-alt key
if(keybindings[altkey] != NULL || keybindings[key] == NULL)
key = altkey;
@ -1275,7 +1417,7 @@ Key_Event(int key, qboolean down, qboolean special)
}
/* Key is unbound */
if ((key >= K_MOUSE1 && key != K_JOY_BACK) && !keybindings[key] && (cls.key_dest != key_console) &&
if ((key >= K_MOUSE1) && !keybindings[key] && (cls.key_dest != key_console) &&
(cls.state == ca_active))
{
Com_Printf("%s (%d) is unbound, hit F4 to set.\n", Key_KeynumToString(key), key);
@ -1296,47 +1438,43 @@ Key_Event(int key, qboolean down, qboolean special)
- moves one menu level up
- closes the menu
- closes the help computer
- closes the chat window
Fully same logic for K_JOY_BACK */
if (!cls.disable_screen)
- closes the chat window */
if (key == K_ESCAPE && !cls.disable_screen)
{
if (key == K_ESCAPE || key == K_JOY_BACK)
if (!down)
{
if (!down)
{
return;
}
/* Close the help computer */
if (cl.frame.playerstate.stats[STAT_LAYOUTS] &&
(cls.key_dest == key_game))
{
Cbuf_AddText("cmd putaway\n");
return;
}
switch (cls.key_dest)
{
/* Close chat window */
case key_message:
Key_Message(key);
break;
/* Close menu or one layer up */
case key_menu:
M_Keydown(key);
break;
/* Pause game and / or leave console,
break into the menu. */
case key_game:
case key_console:
M_Menu_Main_f();
break;
}
return;
}
/* Close the help computer */
if (cl.frame.playerstate.stats[STAT_LAYOUTS] &&
(cls.key_dest == key_game))
{
Cbuf_AddText("cmd putaway\n");
return;
}
switch (cls.key_dest)
{
/* Close chat window */
case key_message:
Key_Message(key);
break;
/* Close menu or one layer up */
case key_menu:
M_Keydown(key);
break;
/* Pause game and / or leave console,
break into the menu. */
case key_game:
case key_console:
M_Menu_Main_f();
break;
}
return;
}
/* This is one of the most ugly constructs I've

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

@ -208,11 +208,11 @@ enum QKEYS {
// From here on, only gamepad controls must be allowed.
// Otherwise, separate bindings (keyboard / controller) menu options will not work.
K_BTN_A,
K_JOY_FIRST_REGULAR = K_BTN_A,
K_BTN_B,
K_BTN_X,
K_BTN_Y,
K_BTN_SOUTH,
K_JOY_FIRST_BTN = K_BTN_SOUTH,
K_BTN_EAST,
K_BTN_WEST,
K_BTN_NORTH,
K_BTN_BACK,
K_BTN_GUIDE,
K_BTN_START,
@ -225,26 +225,28 @@ enum QKEYS {
K_DPAD_LEFT,
K_DPAD_RIGHT,
K_BTN_MISC1,
K_PADDLE_1,
K_PADDLE_2,
K_PADDLE_3,
K_PADDLE_4,
K_TOUCHPAD, // SDL_CONTROLLER_BUTTON_MAX - 1
K_PADDLE_RIGHT_1,
K_PADDLE_LEFT_1,
K_PADDLE_RIGHT_2,
K_PADDLE_LEFT_2,
K_TOUCHPAD, // SDL_CONTROLLER_BUTTON_MAX - 1, SDL2 limit
K_BTN_MISC2,
K_BTN_MISC3,
K_BTN_MISC4,
K_BTN_MISC5,
K_BTN_MISC6, // SDL_GAMEPAD_BUTTON_COUNT - 1, current SDL3 count
K_TRIG_LEFT, // buttons for triggers (axes)
K_TRIG_RIGHT,
// add other joystick/controller keys before this one
// and adjust it accordingly, also remember to add corresponding _ALT key below!
K_JOY_LAST_REGULAR = K_TRIG_RIGHT,
// 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.
/* Can't be mapped to any action (=> not regular) */
K_JOY_BACK,
K_BTN_A_ALT,
K_JOY_FIRST_REGULAR_ALT = K_BTN_A_ALT,
K_BTN_B_ALT,
K_BTN_X_ALT,
K_BTN_Y_ALT,
K_BTN_SOUTH_ALT,
K_JOY_FIRST_BTN_ALT = K_BTN_SOUTH_ALT,
K_BTN_EAST_ALT,
K_BTN_WEST_ALT,
K_BTN_NORTH_ALT,
K_BTN_BACK_ALT,
K_BTN_GUIDE_ALT,
K_BTN_START_ALT,
@ -257,11 +259,16 @@ enum QKEYS {
K_DPAD_LEFT_ALT,
K_DPAD_RIGHT_ALT,
K_BTN_MISC1_ALT,
K_PADDLE_1_ALT,
K_PADDLE_2_ALT,
K_PADDLE_3_ALT,
K_PADDLE_4_ALT,
K_PADDLE_RIGHT_1_ALT,
K_PADDLE_LEFT_1_ALT,
K_PADDLE_RIGHT_2_ALT,
K_PADDLE_LEFT_2_ALT,
K_TOUCHPAD_ALT,
K_BTN_MISC2_ALT,
K_BTN_MISC3_ALT,
K_BTN_MISC4_ALT,
K_BTN_MISC5_ALT,
K_BTN_MISC6_ALT,
K_TRIG_LEFT_ALT,
K_TRIG_RIGHT_ALT,

View file

@ -78,7 +78,7 @@ typedef enum
// IN_Update() called at the beginning of a frame to the
// actual movement functions called at a later time.
static float mouse_x, mouse_y;
static unsigned char sdl_back_button = SDL_CONTROLLER_BUTTON_START;
static unsigned char joy_escbutton = SDL_CONTROLLER_BUTTON_START;
static int joystick_left_x, joystick_left_y, joystick_right_x, joystick_right_y;
static float gyro_yaw, gyro_pitch;
static qboolean mlooking;
@ -91,6 +91,12 @@ 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;
// Using japanese style for confirm & cancel buttons on gamepad
qboolean japanese_confirm = false;
// Console Variables
cvar_t *freelook;
cvar_t *lookstrafe;
@ -134,6 +140,12 @@ 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;
// 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;
@ -506,6 +518,110 @@ 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;
}
}
/*
* 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;
japanese_confirm = 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_confirm = true;
default:
return;
}
}
else
#endif // SDL_VERSION_ATLEAST(2, 0, 12)
if (requested == 1)
{
japanese_confirm = true;
}
}
static void
IN_GyroMode_Changed(void)
{
if (gyro_mode->value < 2)
{
gyro_active = false;
}
else
{
gyro_active = true;
}
gyro_mode->modified = false;
}
static void
IN_VirtualKeyEvent(int keynum, qboolean *state_store, qboolean new_state)
{
if (new_state != *state_store)
{
*state_store = new_state;
Key_Event(keynum, *state_store, true);
}
}
qboolean IN_NumpadIsOn()
{
SDL_Keymod mod = SDL_GetModState();
@ -534,6 +650,7 @@ IN_Update(void)
static qboolean left_trigger = false;
static qboolean right_trigger = false;
static qboolean left_stick[4] = {false, false, false, false}; // left, right, up, down virtual keys
static int consoleKeyCode = 0;
@ -734,8 +851,8 @@ IN_Update(void)
qboolean down = (event.type == SDL_CONTROLLERBUTTONDOWN);
unsigned char btn = event.cbutton.button;
// Handle Back Button, to override its original key
Key_Event( (btn == sdl_back_button)? K_JOY_BACK : K_BTN_A + btn,
// Handle Esc button first, to override its original key
Key_Event( (btn == joy_escbutton)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
down, true );
break;
}
@ -747,26 +864,12 @@ IN_Update(void)
switch (event.caxis.axis)
{
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
{
qboolean new_left_trigger = axis_value > 8192;
if (new_left_trigger != left_trigger)
{
left_trigger = new_left_trigger;
Key_Event(K_TRIG_LEFT, left_trigger, true);
}
IN_VirtualKeyEvent(K_TRIG_LEFT, &left_trigger, axis_value > 8192);
break;
}
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
{
qboolean new_right_trigger = axis_value > 8192;
if (new_right_trigger != right_trigger)
{
right_trigger = new_right_trigger;
Key_Event(K_TRIG_RIGHT, right_trigger, true);
}
IN_VirtualKeyEvent(K_TRIG_RIGHT, &right_trigger, axis_value > 8192);
break;
}
}
if (!cl_paused->value && cls.key_dest == key_game)
@ -786,6 +889,24 @@ IN_Update(void)
joystick_right_y = axis_value;
break;
}
break;
}
// Virtual keys to navigate menus with left stick
if (cls.key_dest == key_menu)
{
switch (event.caxis.axis)
{
case SDL_CONTROLLER_AXIS_LEFTX:
IN_VirtualKeyEvent(K_LEFTARROW, &left_stick[0], axis_value < -16896);
IN_VirtualKeyEvent(K_RIGHTARROW, &left_stick[1], axis_value > 16896);
break;
case SDL_CONTROLLER_AXIS_LEFTY:
IN_VirtualKeyEvent(K_UPARROW, &left_stick[2], axis_value < -16896);
IN_VirtualKeyEvent(K_DOWNARROW, &left_stick[3], axis_value > 16896);
break;
}
}
break;
}
@ -834,8 +955,7 @@ IN_Update(void)
#endif // !NO_SDL_GYRO
if (gyro_active && gyro_mode->value &&
!cl_paused->value && cls.key_dest == key_game)
if (gyro_active && !cl_paused->value && cls.key_dest == key_game)
{
#ifndef NO_SDL_GYRO
if (!gyro_turning_axis->value)
@ -986,6 +1106,19 @@ IN_Update(void)
countdown_reason = REASON_NONE;
}
}
if (joy_labels->modified)
{
IN_GamepadLabels_Changed();
}
if (joy_confirm->modified)
{
IN_GamepadConfirm_Changed();
}
if (gyro_mode->modified)
{
IN_GyroMode_Changed();
}
}
/*
@ -2070,19 +2203,19 @@ IN_Controller_Init(qboolean notify_user)
SDL_Joystick *joystick = NULL;
SDL_bool is_controller = SDL_FALSE;
cvar = Cvar_Get("in_sdlbackbutton", "1", CVAR_ARCHIVE);
cvar = Cvar_Get("joy_escbutton", "0", CVAR_ARCHIVE);
if (cvar)
{
switch ((int)cvar->value)
{
case 0:
sdl_back_button = SDL_CONTROLLER_BUTTON_BACK;
case 1:
joy_escbutton = SDL_CONTROLLER_BUTTON_BACK;
break;
case 2:
sdl_back_button = SDL_CONTROLLER_BUTTON_GUIDE;
joy_escbutton = SDL_CONTROLLER_BUTTON_GUIDE;
break;
default:
sdl_back_button = SDL_CONTROLLER_BUTTON_START;
joy_escbutton = SDL_CONTROLLER_BUTTON_START;
}
}
@ -2106,6 +2239,9 @@ IN_Controller_Init(qboolean notify_user)
#ifdef SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE
SDL_SetHint( SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1" );
#endif
#ifdef SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS // use button positions instead of labels, like SDL3
SDL_SetHint( SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0" );
#endif
if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == -1)
{
@ -2291,6 +2427,10 @@ IN_Controller_Init(qboolean notify_user)
#endif
}
}
IN_GamepadLabels_Changed();
IN_GamepadConfirm_Changed();
IN_GyroMode_Changed();
}
/*
@ -2326,6 +2466,8 @@ 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_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);
@ -2340,16 +2482,11 @@ IN_Init(void)
gyro_calibration_y = Cvar_Get("gyro_calibration_y", "0.0", CVAR_ARCHIVE);
gyro_calibration_z = Cvar_Get("gyro_calibration_z", "0.0", CVAR_ARCHIVE);
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE);
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "1.0", CVAR_ARCHIVE);
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "2.5", CVAR_ARCHIVE);
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "2.5", CVAR_ARCHIVE);
gyro_tightening = Cvar_Get("gyro_tightening", "3.5", CVAR_ARCHIVE);
gyro_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE);
gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE);
if ((int)gyro_mode->value == 2)
{
gyro_active = true;
}
windowed_pauseonfocuslost = Cvar_Get("vid_pauseonfocuslost", "0", CVAR_USERINFO | CVAR_ARCHIVE);
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);

View file

@ -81,7 +81,7 @@ typedef enum
// IN_Update() called at the beginning of a frame to the
// actual movement functions called at a later time.
static float mouse_x, mouse_y;
static unsigned char sdl_back_button = SDL_GAMEPAD_BUTTON_START;
static unsigned char joy_escbutton = SDL_GAMEPAD_BUTTON_START;
static int joystick_left_x, joystick_left_y, joystick_right_x, joystick_right_y;
static float gyro_yaw, gyro_pitch;
static qboolean mlooking;
@ -94,6 +94,12 @@ 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;
// Using japanese style for confirm & cancel buttons on gamepad
qboolean japanese_confirm = false;
// Console Variables
cvar_t *freelook;
cvar_t *lookstrafe;
@ -137,6 +143,12 @@ 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;
// 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;
@ -504,6 +516,98 @@ 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;
}
}
/*
* 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;
japanese_confirm = 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_confirm = true;
default:
return;
}
}
else if (requested == 1)
{
japanese_confirm = true;
}
}
static void
IN_GyroMode_Changed(void)
{
if (gyro_mode->value < 2)
{
gyro_active = false;
}
else
{
gyro_active = true;
}
gyro_mode->modified = false;
}
static void
IN_VirtualKeyEvent(int keynum, qboolean *state_store, qboolean new_state)
{
if (new_state != *state_store)
{
*state_store = new_state;
Key_Event(keynum, *state_store, true);
}
}
qboolean IN_NumpadIsOn()
{
SDL_Keymod mod = SDL_GetModState();
@ -532,6 +636,7 @@ IN_Update(void)
static qboolean left_trigger = false;
static qboolean right_trigger = false;
static qboolean left_stick[4] = {false, false, false, false}; // left, right, up, down virtual keys
static int consoleKeyCode = 0;
@ -733,8 +838,8 @@ IN_Update(void)
qboolean down = (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
unsigned char btn = event.gbutton.button;
// Handle Back Button, to override its original key
Key_Event( (btn == sdl_back_button)? K_JOY_BACK : K_BTN_A + btn,
// Handle Esc button first, to override its original key
Key_Event( (btn == joy_escbutton)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
down, true );
break;
}
@ -746,26 +851,12 @@ IN_Update(void)
switch (event.gaxis.axis)
{
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER :
{
qboolean new_left_trigger = axis_value > 8192;
if (new_left_trigger != left_trigger)
{
left_trigger = new_left_trigger;
Key_Event(K_TRIG_LEFT, left_trigger, true);
}
IN_VirtualKeyEvent(K_TRIG_LEFT, &left_trigger, axis_value > 8192);
break;
}
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER :
{
qboolean new_right_trigger = axis_value > 8192;
if (new_right_trigger != right_trigger)
{
right_trigger = new_right_trigger;
Key_Event(K_TRIG_RIGHT, right_trigger, true);
}
IN_VirtualKeyEvent(K_TRIG_RIGHT, &right_trigger, axis_value > 8192);
break;
}
}
if (!cl_paused->value && cls.key_dest == key_game)
@ -785,6 +876,24 @@ IN_Update(void)
joystick_right_y = axis_value;
break;
}
break;
}
// Virtual keys to navigate menus with left stick
if (cls.key_dest == key_menu)
{
switch (event.gaxis.axis)
{
case SDL_GAMEPAD_AXIS_LEFTX :
IN_VirtualKeyEvent(K_LEFTARROW, &left_stick[0], axis_value < -16896);
IN_VirtualKeyEvent(K_RIGHTARROW, &left_stick[1], axis_value > 16896);
break;
case SDL_GAMEPAD_AXIS_LEFTY :
IN_VirtualKeyEvent(K_UPARROW, &left_stick[2], axis_value < -16896);
IN_VirtualKeyEvent(K_DOWNARROW, &left_stick[3], axis_value > 16896);
break;
}
}
break;
}
@ -833,8 +942,7 @@ IN_Update(void)
#endif // !NO_SDL_GYRO
if (gyro_active && gyro_mode->value &&
!cl_paused->value && cls.key_dest == key_game)
if (gyro_active && !cl_paused->value && cls.key_dest == key_game)
{
#ifndef NO_SDL_GYRO
if (!gyro_turning_axis->value)
@ -983,6 +1091,20 @@ IN_Update(void)
countdown_reason = REASON_NONE;
}
}
// Gamepad labels' type and "confirm & cancel style" change handling
if (joy_labels->modified)
{
IN_GamepadLabels_Changed();
}
if (joy_confirm->modified)
{
IN_GamepadConfirm_Changed();
}
if (gyro_mode->modified)
{
IN_GyroMode_Changed();
}
}
/*
@ -2068,19 +2190,19 @@ IN_Controller_Init(qboolean notify_user)
SDL_Joystick *joystick = NULL;
bool is_controller = false;
cvar = Cvar_Get("in_sdlbackbutton", "1", CVAR_ARCHIVE);
cvar = Cvar_Get("joy_escbutton", "0", CVAR_ARCHIVE);
if (cvar)
{
switch ((int)cvar->value)
{
case 0:
sdl_back_button = SDL_GAMEPAD_BUTTON_BACK;
case 1:
joy_escbutton = SDL_GAMEPAD_BUTTON_BACK;
break;
case 2:
sdl_back_button = SDL_GAMEPAD_BUTTON_GUIDE;
joy_escbutton = SDL_GAMEPAD_BUTTON_GUIDE;
break;
default:
sdl_back_button = SDL_GAMEPAD_BUTTON_START;
joy_escbutton = SDL_GAMEPAD_BUTTON_START;
}
}
@ -2280,6 +2402,9 @@ IN_Controller_Init(qboolean notify_user)
}
SDL_free((void *)joysticks);
IN_GamepadLabels_Changed();
IN_GamepadConfirm_Changed();
IN_GyroMode_Changed();
}
/*
@ -2315,6 +2440,8 @@ 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_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);
@ -2329,16 +2456,11 @@ IN_Init(void)
gyro_calibration_y = Cvar_Get("gyro_calibration_y", "0.0", CVAR_ARCHIVE);
gyro_calibration_z = Cvar_Get("gyro_calibration_z", "0.0", CVAR_ARCHIVE);
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE);
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "1.0", CVAR_ARCHIVE);
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "2.5", CVAR_ARCHIVE);
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "2.5", CVAR_ARCHIVE);
gyro_tightening = Cvar_Get("gyro_tightening", "3.5", CVAR_ARCHIVE);
gyro_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE);
gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE);
if ((int)gyro_mode->value == 2)
{
gyro_active = true;
}
windowed_pauseonfocuslost = Cvar_Get("vid_pauseonfocuslost", "0", CVAR_USERINFO | CVAR_ARCHIVE);
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);

View file

@ -240,6 +240,8 @@ M_PushMenu(menuframework_s* menu)
cls.key_dest = key_menu;
}
extern qboolean japanese_confirm;
int
Key_GetMenuKey(int key)
{
@ -280,24 +282,27 @@ Key_GetMenuKey(int key)
case K_KP_ENTER:
case K_ENTER:
case K_BTN_A:
return K_ENTER;
case K_ESCAPE:
case K_JOY_BACK:
case K_BTN_B:
return K_ESCAPE;
case K_BACKSPACE:
case K_DEL:
case K_KP_DEL:
if (IN_NumpadIsOn() == true) { break; }
case K_BTN_Y:
case K_BACKSPACE:
case K_DEL:
case K_BTN_NORTH:
return K_BACKSPACE;
case K_KP_INS:
if (IN_NumpadIsOn() == true) { break; }
case K_INS:
return K_INS;
case K_BTN_SOUTH:
if (japanese_confirm) return K_ESCAPE;
else return K_ENTER;
case K_BTN_EAST:
if (japanese_confirm) return K_ENTER;
else return K_ESCAPE;
}
return key;
@ -940,14 +945,14 @@ M_UnbindCommand(char *command, int scope)
switch (scope)
{
case KEYS_KEYBOARD_MOUSE:
end = K_JOY_FIRST_REGULAR;
end = K_JOY_FIRST_BTN;
break;
case KEYS_CONTROLLER:
begin = K_JOY_FIRST_REGULAR;
end = K_JOY_LAST_REGULAR + 1;
begin = K_JOY_FIRST_BTN;
end = K_JOY_FIRST_BTN_ALT;
break;
case KEYS_CONTROLLER_ALT:
begin = K_JOY_FIRST_REGULAR_ALT;
begin = K_JOY_FIRST_BTN_ALT;
}
for (j = begin; j < end; j++)
@ -976,14 +981,14 @@ M_FindKeysForCommand(char *command, int *twokeys, int scope)
switch (scope)
{
case KEYS_KEYBOARD_MOUSE:
end = K_JOY_FIRST_REGULAR;
end = K_JOY_FIRST_BTN;
break;
case KEYS_CONTROLLER:
begin = K_JOY_FIRST_REGULAR;
end = K_JOY_LAST_REGULAR + 1;
begin = K_JOY_FIRST_BTN;
end = K_JOY_FIRST_BTN_ALT;
break;
case KEYS_CONTROLLER_ALT:
begin = K_JOY_FIRST_REGULAR_ALT;
begin = K_JOY_FIRST_BTN_ALT;
}
twokeys[0] = twokeys[1] = -1;
@ -1124,7 +1129,7 @@ Keys_MenuKey(int key)
if (menukeyitem_bind)
{
// Any key/button except from the game controller and escape keys
if ((key != K_ESCAPE) && (key != '`') && (key < K_JOY_FIRST_REGULAR))
if ((key != K_ESCAPE) && (key != '`') && (key < K_JOY_FIRST_BTN))
{
char cmd[1024];
@ -1277,7 +1282,7 @@ MultiplayerKeys_MenuKey(int key)
if (menukeyitem_bind)
{
// Any key/button but the escape ones
if ((key != K_ESCAPE) && (key != '`') && (key != K_JOY_BACK))
if ((key != K_ESCAPE) && (key != '`'))
{
char cmd[1024];
@ -1319,6 +1324,30 @@ 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];
int btn_confirm, btn_cancel;
if (japanese_confirm)
{
btn_confirm = K_BTN_EAST;
btn_cancel = K_BTN_SOUTH;
}
else
{
btn_confirm = K_BTN_SOUTH;
btn_cancel = K_BTN_EAST;
}
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"},
@ -1374,7 +1403,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 +1416,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]));
}
}
}
@ -1432,7 +1461,7 @@ ControllerButtons_MenuInit(void)
Menu_AddItem(&s_controller_buttons_menu, (void *)&s_controller_buttons_actions[i]);
}
Menu_SetStatusBar(&s_controller_buttons_menu, "BTN_A assigns, BTN_Y clears, BTN_B exits");
GamepadMenu_StatusPrompt(&s_controller_buttons_menu);
Menu_Center(&s_controller_buttons_menu);
}
@ -1451,7 +1480,7 @@ ControllerButtons_MenuKey(int key)
if (menukeyitem_bind)
{
// Only controller buttons allowed
if (key >= K_JOY_FIRST_REGULAR && key != K_JOY_BACK)
if (key >= K_JOY_FIRST_BTN)
{
char cmd[1024];
@ -1460,7 +1489,7 @@ ControllerButtons_MenuKey(int key)
Cbuf_InsertText(cmd);
}
Menu_SetStatusBar(&s_controller_buttons_menu, "BTN_A assigns, BTN_Y clears, BTN_B exits");
GamepadMenu_StatusPrompt(&s_controller_buttons_menu);
menukeyitem_bind = false;
return menu_out_sound;
}
@ -1548,7 +1577,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 +1590,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]));
}
}
}
@ -1606,7 +1635,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_A assigns, BTN_Y clears, BTN_B exits");
GamepadMenu_StatusPrompt(&s_controller_alt_buttons_menu);
Menu_Center(&s_controller_alt_buttons_menu);
}
@ -1625,17 +1654,17 @@ ControllerAltButtons_MenuKey(int key)
if (menukeyitem_bind)
{
// Only controller buttons allowed, different from the alt buttons modifier
if (key >= K_JOY_FIRST_REGULAR && key != K_JOY_BACK && (keybindings[key] == NULL || strcmp(keybindings[key], "+joyaltselector") != 0))
if (key >= K_JOY_FIRST_BTN && (keybindings[key] == NULL || strcmp(keybindings[key], "+joyaltselector") != 0))
{
char cmd[1024];
key = key + (K_JOY_FIRST_REGULAR_ALT - K_JOY_FIRST_REGULAR); // change input to its ALT mode
key = key + (K_JOY_FIRST_BTN_ALT - K_JOY_FIRST_BTN); // change input to its ALT mode
Com_sprintf(cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n",
Key_KeynumToString(key), controller_alt_bindnames[item->generic.localdata[0]][0]);
Cbuf_InsertText(cmd);
}
Menu_SetStatusBar(&s_controller_alt_buttons_menu, "BTN_A assigns, BTN_Y clears, BTN_B exits");
GamepadMenu_StatusPrompt(&s_controller_alt_buttons_menu);
menukeyitem_bind = false;
return menu_out_sound;
}

View file

@ -268,7 +268,7 @@ int RI_InitContext(void* win)
#ifdef YQ2_GL1_GLES
// Load GL pointers through GLAD and check context.
if( !gladLoadGLES1Loader(SDL_GL_GetProcAddress))
if( !gladLoadGLES1Loader( (void * (*)(const char *)) SDL_GL_GetProcAddress ) )
{
R_Printf(PRINT_ALL, "RI_InitContext(): ERROR: loading OpenGL ES function pointers failed!\n");
return false;