mirror of
https://github.com/yquake2/yquake2
synced 2026-08-20 00:26:04 -04:00
Merge pull request #1294 from protocultor/gamepad_refactor
New Gamepad code refactor
This commit is contained in:
commit
b2ce7bf6bd
8 changed files with 280 additions and 268 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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]))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue