Merge pull request #1294 from protocultor/gamepad_refactor

New Gamepad code refactor
This commit is contained in:
Yamagi 2026-03-08 18:28:06 +01:00 committed by GitHub
commit b2ce7bf6bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 280 additions and 268 deletions

View file

@ -667,12 +667,6 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
with `1` (default); `0` disables gamepad usage. Can only be set from
command line.
* **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` = 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.

View file

@ -108,7 +108,7 @@ static void SetExecutablePath(char* exePath)
int name[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
#endif
size_t len = PATH_MAX-1;
int ret = sysctl(name, sizeof(name)/sizeof(name[0]), exePath, &len, NULL, 0);
int ret = sysctl(name, ARRLEN(name), exePath, &len, NULL, 0);
if(ret != 0)
{
// an error occured, clear exe path

View file

@ -622,7 +622,7 @@ Sys_Realpath(const char *in, char *out, size_t size)
WCHAR win[MAX_OSPATH] = {0};
WCHAR wconverted[MAX_OSPATH] = {0};
MultiByteToWideChar(CP_UTF8, 0, in, -1, win, sizeof(win)/sizeof(win[0]));
MultiByteToWideChar(CP_UTF8, 0, in, -1, win, ARRLEN(win));
if (_wfullpath(wconverted, win, size) == NULL)
{
@ -706,7 +706,7 @@ Sys_GetWorkDir(char *buffer, size_t len)
{
WCHAR wbuffer[MAX_OSPATH];
if (GetCurrentDirectoryW(sizeof(wbuffer)/sizeof(wbuffer[0]), wbuffer) != 0)
if (GetCurrentDirectoryW(ARRLEN(wbuffer), wbuffer) != 0)
{
WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, len, NULL, NULL);
return;
@ -720,7 +720,7 @@ Sys_SetWorkDir(char *path)
{
WCHAR wpath[MAX_OSPATH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof(wpath)/sizeof(wpath[0]));
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, ARRLEN(wpath));
if (SetCurrentDirectoryW(wpath) != 0)
{
@ -760,8 +760,8 @@ Sys_RedirectStdout(void)
snprintf(path_stdout, sizeof(path_stdout), "%s/%s", dir, "stdout.txt");
snprintf(path_stderr, sizeof(path_stderr), "%s/%s", dir, "stderr.txt");
MultiByteToWideChar(CP_UTF8, 0, path_stdout, -1, wpath_stdout, sizeof(wpath_stdout)/sizeof(wpath_stdout[0]));
MultiByteToWideChar(CP_UTF8, 0, path_stderr, -1, wpath_stderr, sizeof(wpath_stderr)/sizeof( wpath_stderr[0] ) );
MultiByteToWideChar(CP_UTF8, 0, path_stdout, -1, wpath_stdout, ARRLEN(wpath_stdout));
MultiByteToWideChar(CP_UTF8, 0, path_stderr, -1, wpath_stderr, ARRLEN(wpath_stderr));
_wfreopen(wpath_stdout, L"w", stdout);
_wfreopen(wpath_stderr, L"w", stderr);

View file

@ -222,7 +222,7 @@ static char *gamepadbtns[] =
"BTN_NORTH",
"BTN_BACK",
"BTN_GUIDE",
"BTN_START",
"", // START
"STICK_LEFT",
"STICK_RIGHT",
"SHOULDR_LEFT",
@ -251,7 +251,7 @@ static char *gamepadbtns[] =
"BTN_NORTH_ALT",
"BTN_BACK_ALT",
"BTN_GUIDE_ALT",
"BTN_START_ALT",
"", // START ALT
"STICK_LEFT_ALT",
"STICK_RIGHT_ALT",
"SHOULDR_LEFT_ALT",
@ -275,8 +275,6 @@ static char *gamepadbtns[] =
"TRIG_RIGHT_ALT"
};
#define NUM_GAMEPAD_BTNS (sizeof gamepadbtns / sizeof gamepadbtns[0])
static char *gpbtns_face[] =
{
// Xbox
@ -284,9 +282,9 @@ static char *gpbtns_face[] =
"B",
"X",
"Y",
"VIEW",
"VIEW", // BACK
"XBOX",
"MENU",
"", // MENU / START
"LS",
"RS",
"LB",
@ -296,9 +294,9 @@ static char *gpbtns_face[] =
"CIRCLE",
"SQUARE",
"TRIANGLE",
"CREATE",
"CREATE", // SELECT
"PS",
"OPTIONS",
"", // OPTIONS / START
"L3",
"R3",
"L1",
@ -310,7 +308,7 @@ static char *gpbtns_face[] =
"X",
"-",
"HOME",
"+",
"", // "+"
"L stick",
"R stick",
"L btn",
@ -822,6 +820,7 @@ Key_Message(int key)
static int
Key_StringToKeynum(char *str)
{
static const int num_gamepad_btns = ARRLEN(gamepadbtns);
keyname_t *kn;
int i;
@ -843,7 +842,7 @@ Key_StringToKeynum(char *str)
}
}
for (i = 0; i < NUM_GAMEPAD_BTNS; i++)
for (i = 0; i < num_gamepad_btns; i++)
{
if (!Q_stricmp(str, gamepadbtns[i]))
{

View file

@ -93,7 +93,6 @@ 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 joy_escbutton = SDL_CONTROLLER_BUTTON_START;
static int joystick_left_x, joystick_left_y, joystick_right_x, joystick_right_y;
static qboolean mlooking;
@ -1049,12 +1048,10 @@ IN_Update(void)
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERBUTTONDOWN:
{
qboolean down = (event.type == SDL_CONTROLLERBUTTONDOWN);
unsigned char btn = event.cbutton.button;
// Handle Esc button first, to override its original key
Key_Event( (btn == joy_escbutton)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
down, true );
Key_Event( (btn == SDL_CONTROLLER_BUTTON_START)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
(event.type == SDL_CONTROLLERBUTTONDOWN), true );
break;
}
@ -2534,44 +2531,136 @@ IN_Haptic_Prepare(void)
}
/*
* Game Controller
* Helper functions for Gyro initialization.
* Their nature depend on NO_SDL_GYRO.
*/
#ifndef NO_SDL_GYRO
static void
IN_Joy_IMU_Treatment(SDL_Joystick *joystick, const char* joystick_name, int joy_num)
{
SDL_JoystickClose(joystick);
joystick = NULL;
Com_Printf ("Skipping IMU device.\n");
}
static void
IN_Gyro_and_LED_Enabling(void)
{
if (!controller) return;
const qboolean found_gyro =
SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO)
&& !SDL_GameControllerSetSensorEnabled(
controller, SDL_SENSOR_GYRO, SDL_TRUE);
const qboolean found_accel =
SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL)
&& !SDL_GameControllerSetSensorEnabled(
controller, SDL_SENSOR_ACCEL, SDL_TRUE);
if (found_gyro && found_accel)
{
show_gyro = true;
#if SDL_VERSION_ATLEAST(2, 0, 16)
Com_Printf("Sensors enabled: Gyro at %.2f Hz, Accelerometer at %.2f Hz\n",
SDL_GameControllerGetSensorDataRate(controller, SDL_SENSOR_GYRO),
SDL_GameControllerGetSensorDataRate(controller, SDL_SENSOR_ACCEL));
#else
Com_Printf("Gyro and accelerometer sensors enabled.\n");
#endif // #if SDL_VERSION_ATLEAST(2, 0, 16)
}
else
{
if (!found_gyro)
{
Com_Printf("Gyro sensor not found.\n");
}
if (!found_accel)
{
Com_Printf("Accelerometer sensor not found.\n");
}
// Both were required for gyro support, so disable them completely.
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_FALSE);
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_FALSE);
}
if ( SDL_GameControllerHasLED(controller) )
{
SDL_GameControllerSetLED(controller, 0, 80, 0); // green light
}
}
static qboolean
IN_GameController_Verify_Init_Complete(void)
{
return show_gamepad;
}
#else // with NO_SDL_GYRO
static void
IN_Joy_IMU_Treatment(SDL_Joystick *joystick, const char* joystick_name, int joy_num)
{
// If it's not a Left JoyCon, use it as Gyro
const qboolean using_imu = !imu_joystick &&
!( strstr(joystick_name, "Joy-Con") && strstr(joystick_name, "L") );
Com_Printf ("IMU device found... ");
SDL_JoystickClose(joystick);
joystick = NULL;
if (using_imu)
{
imu_joystick = SDL_JoystickOpen(joy_num);
if (imu_joystick)
{
show_gyro = true;
Com_Printf ("using it as Gyro sensor.\n");
}
else
{
Com_Printf ("\nCouldn't open IMU: %s.\n", SDL_GetError());
}
}
else
{
Com_Printf ("skipping.\n");
}
}
static void
IN_Gyro_and_LED_Enabling(void)
{
// Unavailable in this case
}
static qboolean
IN_GameController_Verify_Init_Complete(void)
{
return (show_gamepad && show_gyro);
}
#endif // NO_SDL_GYRO
/*
* Game Controller initialization
*/
static void
IN_Controller_Init(qboolean notify_user)
{
cvar_t *cvar;
int nummappings, numjoysticks, joy_num, i;
int numjoysticks, joy_num, i;
char controllerdb[MAX_OSPATH] = {0};
SDL_Joystick *joystick = NULL;
SDL_bool is_controller = SDL_FALSE;
cvar = Cvar_Get("joy_escbutton", "0", CVAR_ARCHIVE);
if (cvar)
{
switch ((int)cvar->value)
{
case 1:
joy_escbutton = SDL_CONTROLLER_BUTTON_BACK;
break;
case 2:
joy_escbutton = SDL_CONTROLLER_BUTTON_GUIDE;
break;
default:
joy_escbutton = SDL_CONTROLLER_BUTTON_START;
}
}
cvar = Cvar_Get("in_initjoy", "1", CVAR_NOSET);
cvar_t *cvar = Cvar_Get("in_initjoy", "1", CVAR_NOSET);
joy_num = (int)cvar->value;
if (joy_num < 1)
{
return;
}
if (joy_num < 1) return;
if (notify_user)
{
Com_Printf("- Game Controller init attempt -\n");
}
if (notify_user) Com_Printf("- Game Controller init attempt -\n");
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER))
{
@ -2606,7 +2695,7 @@ IN_Controller_Init(qboolean notify_user)
for (const char* rawPath = FS_GetNextRawPath(NULL); rawPath != NULL; rawPath = FS_GetNextRawPath(rawPath))
{
snprintf(controllerdb, MAX_OSPATH, "%s/gamecontrollerdb.txt", rawPath);
nummappings = SDL_GameControllerAddMappingsFromFile(controllerdb);
int nummappings = SDL_GameControllerAddMappingsFromFile(controllerdb);
if (nummappings > 0)
Com_Printf ("%d mappings loaded from gamecontrollerdb.txt\n", nummappings);
}
@ -2616,9 +2705,6 @@ IN_Controller_Init(qboolean notify_user)
i = joy_num;
do
{
const char* joystick_name;
size_t name_len;
joystick = SDL_JoystickOpen(i);
if (!joystick)
{
@ -2626,43 +2712,15 @@ IN_Controller_Init(qboolean notify_user)
goto next_joy; // try next joystick
}
joystick_name = SDL_JoystickName(joystick);
name_len = strlen(joystick_name);
const char* joystick_name = SDL_JoystickName(joystick);
const size_t name_len = strlen(joystick_name);
Com_Printf ("Trying joystick %d, '%s'\n", i+1, joystick_name);
// Ugly hack to detect IMU-only devices - works for Switch controllers at least
if ( name_len > 6 && strstr(joystick_name + name_len - 6, "IMU") )
{
#ifndef NO_SDL_GYRO
SDL_JoystickClose(joystick);
joystick = NULL;
Com_Printf ("Skipping IMU device.\n");
#else // if it's not a Left JoyCon, use it as Gyro
qboolean using_imu = !imu_joystick && !( strstr(joystick_name, "Joy-Con") && strstr(joystick_name, "L") );
Com_Printf ("IMU device found... ");
SDL_JoystickClose(joystick);
joystick = NULL;
if (using_imu)
{
imu_joystick = SDL_JoystickOpen(i);
if (imu_joystick)
{
show_gyro = true;
Com_Printf ("using it as Gyro sensor.\n");
}
else
{
Com_Printf ("\nCouldn't open IMU: %s.\n", SDL_GetError());
}
}
else
{
Com_Printf ("skipping.\n");
}
#endif
IN_Joy_IMU_Treatment(joystick, joystick_name, i);
goto next_joy;
}
@ -2674,7 +2732,6 @@ IN_Controller_Init(qboolean notify_user)
{
char joystick_guid[65] = {0};
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(i);
SDL_JoystickGetGUIDString(guid, joystick_guid, 64);
Com_Printf ("To use joystick as game controller, provide its config by either:\n"
@ -2684,6 +2741,7 @@ IN_Controller_Init(qboolean notify_user)
}
SDL_JoystickClose(joystick);
joystick = NULL;
if (is_controller && !controller)
{
@ -2696,53 +2754,7 @@ IN_Controller_Init(qboolean notify_user)
show_gamepad = true;
Com_Printf("Enabled as Game Controller, settings:\n%s\n", SDL_GameControllerMapping(controller));
#ifndef NO_SDL_GYRO
const qboolean found_gyro =
SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO)
&& !SDL_GameControllerSetSensorEnabled(
controller, SDL_SENSOR_GYRO, SDL_TRUE);
const qboolean found_accel =
SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL)
&& !SDL_GameControllerSetSensorEnabled(
controller, SDL_SENSOR_ACCEL, SDL_TRUE);
if (found_gyro && found_accel)
{
show_gyro = true;
#if SDL_VERSION_ATLEAST(2, 0, 16)
Com_Printf("Sensors enabled: Gyro at %.2f Hz, Accelerometer at %.2f Hz\n",
SDL_GameControllerGetSensorDataRate(controller, SDL_SENSOR_GYRO),
SDL_GameControllerGetSensorDataRate(controller, SDL_SENSOR_ACCEL));
#else
Com_Printf("Gyro and accelerometer sensors enabled.\n");
#endif // #if SDL_VERSION_ATLEAST(2, 0, 16)
}
else
{
if (!found_gyro)
{
Com_Printf("Gyro sensor not found.\n");
}
if (!found_accel)
{
Com_Printf("Accelerometer sensor not found.\n");
}
// Both were required for gyro support, so disable them completely.
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_FALSE);
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_FALSE);
}
if ( SDL_GameControllerHasLED(controller) )
{
SDL_GameControllerSetLED(controller, 0, 80, 0); // green light
}
#endif // !NO_SDL_GYRO
IN_Gyro_and_LED_Enabling();
joystick_haptic = SDL_HapticOpenFromJoystick(SDL_GameControllerGetJoystick(controller));
IN_Haptic_Prepare();
@ -2762,13 +2774,10 @@ IN_Controller_Init(qboolean notify_user)
{
Com_Printf("Controller doesn't support rumble.\n");
}
#ifndef NO_SDL_GYRO // "native SDL gyro" exits when finding a single working gamepad
break;
#endif
}
next_joy:
if (IN_GameController_Verify_Init_Complete()) break;
i++;
if (i == numjoysticks) i = 0;
}
@ -2804,7 +2813,7 @@ static const joy_preset_t joy_presets[] = {
void
IN_ApplyJoyPreset(void)
{
const int final_preset = ARRLEN(joy_presets) - 1;
static const int final_preset = ARRLEN(joy_presets) - 1;
const int i = lroundf(Q_clamp(joy_sensitivity->value, 0, final_preset));
joy_sensitivity->modified = false;
@ -2822,7 +2831,7 @@ IN_ApplyJoyPreset(void)
qboolean
IN_MatchJoyPreset(void)
{
const int num_presets = ARRLEN(joy_presets);
static const int num_presets = ARRLEN(joy_presets);
for (int i = 0; i < num_presets; i++)
{

View file

@ -96,7 +96,6 @@ 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 joy_escbutton = SDL_GAMEPAD_BUTTON_START;
static int joystick_left_x, joystick_left_y, joystick_right_x, joystick_right_y;
static qboolean mlooking;
@ -1030,12 +1029,10 @@ IN_Update(void)
case SDL_EVENT_GAMEPAD_BUTTON_UP :
case SDL_EVENT_GAMEPAD_BUTTON_DOWN :
{
qboolean down = (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
unsigned char btn = event.gbutton.button;
// Handle Esc button first, to override its original key
Key_Event( (btn == joy_escbutton)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
down, true );
Key_Event( (btn == SDL_GAMEPAD_BUTTON_START)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
(event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN), true );
break;
}
@ -2515,44 +2512,134 @@ IN_Haptic_Prepare(void)
}
/*
* Game Controller
* Helper functions for Gyro initialization.
* Their nature depend on NO_SDL_GYRO.
*/
#ifndef NO_SDL_GYRO
static void
IN_Joy_IMU_Treatment(SDL_Joystick *joystick, const char* joystick_name, SDL_JoystickID joy_id)
{
SDL_CloseJoystick(joystick);
joystick = NULL;
Com_Printf ("Skipping IMU device.\n");
}
static void
IN_Gyro_and_LED_Enabling(void)
{
if (!controller) return;
const qboolean found_gyro =
SDL_GamepadHasSensor(controller, SDL_SENSOR_GYRO)
&& SDL_SetGamepadSensorEnabled(
controller, SDL_SENSOR_GYRO, true);
const qboolean found_accel =
SDL_GamepadHasSensor(controller, SDL_SENSOR_ACCEL)
&& SDL_SetGamepadSensorEnabled(
controller, SDL_SENSOR_ACCEL, true);
if (found_gyro && found_accel)
{
show_gyro = true;
Com_Printf("Sensors enabled: Gyro at %.2f Hz, Accelerometer at %.2f Hz\n",
SDL_GetGamepadSensorDataRate(controller, SDL_SENSOR_GYRO),
SDL_GetGamepadSensorDataRate(controller, SDL_SENSOR_ACCEL));
}
else
{
if (!found_gyro)
{
Com_Printf("Gyro sensor not found.\n");
}
if (!found_accel)
{
Com_Printf("Accelerometer sensor not found.\n");
}
// Both were required for gyro support, so disable them completely.
SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, false);
SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, false);
}
const bool hasLED = SDL_GetBooleanProperty( SDL_GetGamepadProperties(controller),
SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, false );
if (hasLED)
{
SDL_SetGamepadLED(controller, 0, 80, 0); // green light
}
}
static qboolean
IN_GameController_Verify_Init_Complete(void)
{
return show_gamepad;
}
#else // with NO_SDL_GYRO
static void
IN_Joy_IMU_Treatment(SDL_Joystick *joystick, const char* joystick_name, SDL_JoystickID joy_id)
{
// If it's not a Left JoyCon, use it as Gyro
const qboolean using_imu = !imu_joystick &&
!( strstr(joystick_name, "Joy-Con") && strstr(joystick_name, "L") );
Com_Printf ("IMU device found... ");
SDL_CloseJoystick(joystick);
joystick = NULL;
if (using_imu)
{
imu_joystick = SDL_OpenJoystick(joy_id);
if (imu_joystick)
{
show_gyro = true;
Com_Printf ("using it as Gyro sensor.\n");
}
else
{
Com_Printf ("\nCouldn't open IMU: %s.\n", SDL_GetError());
}
}
else
{
Com_Printf ("skipping.\n");
}
}
static void
IN_Gyro_and_LED_Enabling(void)
{
// Unavailable in this case
}
static qboolean
IN_GameController_Verify_Init_Complete(void)
{
return (show_gamepad && show_gyro);
}
#endif // NO_SDL_GYRO
/*
* Game Controller initialization
*/
static void
IN_Controller_Init(qboolean notify_user)
{
cvar_t *cvar;
int nummappings, numjoysticks, joy_num, i;
int numjoysticks, joy_num, i;
char controllerdb[MAX_OSPATH] = {0};
SDL_Joystick *joystick = NULL;
bool is_controller = false;
cvar = Cvar_Get("joy_escbutton", "0", CVAR_ARCHIVE);
if (cvar)
{
switch ((int)cvar->value)
{
case 1:
joy_escbutton = SDL_GAMEPAD_BUTTON_BACK;
break;
case 2:
joy_escbutton = SDL_GAMEPAD_BUTTON_GUIDE;
break;
default:
joy_escbutton = SDL_GAMEPAD_BUTTON_START;
}
}
cvar = Cvar_Get("in_initjoy", "1", CVAR_NOSET);
cvar_t *cvar = Cvar_Get("in_initjoy", "1", CVAR_NOSET);
joy_num = (int)cvar->value;
if (joy_num < 1)
{
return;
}
if (joy_num < 1) return;
if (notify_user)
{
Com_Printf("- Gamepad init attempt -\n");
}
if (notify_user) Com_Printf("- Gamepad init attempt -\n");
if (!SDL_WasInit(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC))
{
@ -2576,14 +2663,13 @@ IN_Controller_Init(qboolean notify_user)
IN_Haptic_Prepare();
SDL_free((void *)joysticks);
return;
}
for (const char* rawPath = FS_GetNextRawPath(NULL); rawPath != NULL; rawPath = FS_GetNextRawPath(rawPath))
{
snprintf(controllerdb, MAX_OSPATH, "%s/gamecontrollerdb.txt", rawPath);
nummappings = SDL_AddGamepadMappingsFromFile(controllerdb);
int nummappings = SDL_AddGamepadMappingsFromFile(controllerdb);
if (nummappings > 0)
Com_Printf ("%d mappings loaded from gamecontrollerdb.txt\n", nummappings);
}
@ -2601,54 +2687,25 @@ IN_Controller_Init(qboolean notify_user)
}
const char* joystick_name = SDL_GetJoystickName(joystick);
const int name_len = strlen(joystick_name);
const size_t name_len = strlen(joystick_name);
Com_Printf ("Trying joystick %d, '%s'\n", i+1, joystick_name);
// Ugly hack to detect IMU-only devices - works for Switch controllers at least
if ( name_len > 6 && strstr(joystick_name + name_len - 6, "IMU") )
{
#ifndef NO_SDL_GYRO
SDL_CloseJoystick(joystick);
joystick = NULL;
Com_Printf ("Skipping IMU device.\n");
#else // if it's not a Left JoyCon, use it as Gyro
qboolean using_imu = !imu_joystick && !( strstr(joystick_name, "Joy-Con") && strstr(joystick_name, "L") );
Com_Printf ("IMU device found... ");
SDL_CloseJoystick(joystick);
joystick = NULL;
if (using_imu)
{
imu_joystick = SDL_OpenJoystick(joysticks[i]);
if (imu_joystick)
{
show_gyro = true;
Com_Printf ("using it as Gyro sensor.\n");
}
else
{
Com_Printf ("\nCouldn't open IMU: %s.\n", SDL_GetError());
}
}
else
{
Com_Printf ("skipping.\n");
}
#endif
IN_Joy_IMU_Treatment(joystick, joystick_name, joysticks[i]);
goto next_joy;
}
Com_Printf ("Buttons = %d, Axes = %d, Hats = %d\n", SDL_GetNumJoystickButtons(joystick),
SDL_GetNumJoystickAxes(joystick), SDL_GetNumJoystickHats(joystick));
SDL_GetNumJoystickAxes(joystick), SDL_GetNumJoystickHats(joystick));
is_controller = SDL_IsGamepad(joysticks[i]);
if (!is_controller)
{
char joystick_guid[65] = {0};
SDL_GUID guid = SDL_GetJoystickGUIDForID(joysticks[i]);
SDL_GUIDToString(guid, joystick_guid, 64);
Com_Printf ("To identify joystick as Gamepad, provide its config by either:\n"
@ -2670,57 +2727,14 @@ IN_Controller_Init(qboolean notify_user)
}
show_gamepad = true;
Com_Printf("Enabled as Gamepad, settings:\n%s\n",
SDL_GetGamepadMapping(controller));
#ifndef NO_SDL_GYRO
const qboolean found_gyro =
SDL_GamepadHasSensor(controller, SDL_SENSOR_GYRO)
&& SDL_SetGamepadSensorEnabled(
controller, SDL_SENSOR_GYRO, true);
const qboolean found_accel =
SDL_GamepadHasSensor(controller, SDL_SENSOR_ACCEL)
&& SDL_SetGamepadSensorEnabled(
controller, SDL_SENSOR_ACCEL, true);
if (found_gyro && found_accel)
{
show_gyro = true;
Com_Printf("Sensors enabled: Gyro at %.2f Hz, Accelerometer at %.2f Hz\n",
SDL_GetGamepadSensorDataRate(controller, SDL_SENSOR_GYRO),
SDL_GetGamepadSensorDataRate(controller, SDL_SENSOR_ACCEL));
}
else
{
if (!found_gyro)
{
Com_Printf("Gyro sensor not found.\n");
}
if (!found_accel)
{
Com_Printf("Accelerometer sensor not found.\n");
}
// Both were required for gyro support, so disable them completely.
SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, false);
SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, false);
}
bool hasLED = SDL_GetBooleanProperty(SDL_GetGamepadProperties(controller), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, false);
if (hasLED)
{
SDL_SetGamepadLED(controller, 0, 80, 0); // green light
}
#endif // !NO_SDL_GYRO
Com_Printf("Enabled as Gamepad, settings:\n%s\n", SDL_GetGamepadMapping(controller));
IN_Gyro_and_LED_Enabling();
joystick_haptic = SDL_OpenHapticFromJoystick(SDL_GetGamepadJoystick(controller));
IN_Haptic_Prepare();
bool hasRumble = SDL_GetBooleanProperty(SDL_GetGamepadProperties(controller), SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false);
const bool hasRumble = SDL_GetBooleanProperty( SDL_GetGamepadProperties(controller),
SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false );
if (hasRumble)
{
show_haptic = true;
@ -2730,13 +2744,10 @@ IN_Controller_Init(qboolean notify_user)
{
Com_Printf("Gamepad doesn't support rumble.\n");
}
#ifndef NO_SDL_GYRO // "native SDL gyro" exits when finding a single working gamepad
break;
#endif
}
next_joy:
if (IN_GameController_Verify_Init_Complete()) break;
i++;
if (i == numjoysticks) i = 0;
}
@ -2773,7 +2784,7 @@ static const joy_preset_t joy_presets[] = {
void
IN_ApplyJoyPreset(void)
{
const int final_preset = ARRLEN(joy_presets) - 1;
static const int final_preset = ARRLEN(joy_presets) - 1;
const int i = lroundf(Q_clamp(joy_sensitivity->value, 0, final_preset));
joy_sensitivity->modified = false;
@ -2791,7 +2802,7 @@ IN_ApplyJoyPreset(void)
qboolean
IN_MatchJoyPreset(void)
{
const int num_presets = ARRLEN(joy_presets);
static const int num_presets = ARRLEN(joy_presets);
for (int i = 0; i < num_presets; i++)
{

View file

@ -167,8 +167,7 @@ static voidpf ZCALLBACK fopen_file_func_utf(voidpf opaque, const char *filename,
if (!((filename == NULL) || (mode_fopen == NULL)))
{
MultiByteToWideChar(CP_UTF8, 0, filename, -1, wfilename,
sizeof(wfilename) / sizeof(*wfilename));
MultiByteToWideChar(CP_UTF8, 0, filename, -1, wfilename, ARRLEN(wfilename));
file = _wfopen((const wchar_t *) wfilename, mode_fopen);
}
@ -1492,7 +1491,7 @@ static int
Q_sort_modcmp(const void *p1, const void *p2)
{
static const char *first_mods[] = {BASEDIRNAME, "xatrix", "rogue", "ctf"};
static const unsigned short int first_mods_qty = 4;
static const unsigned short int first_mods_qty = ARRLEN(first_mods);
const char * s1 = * (char * const *)p1;
const char * s2 = * (char * const *)p2;

View file

@ -1104,7 +1104,7 @@ flooded(edict_t *ent)
}
cl = ent->client;
mx = sizeof(cl->flood_when) / sizeof(cl->flood_when[0]);
mx = ARRLEN(cl->flood_when);
if (num_msgs > mx)
{