mirror of
https://github.com/fabiangreffrath/woof.git
synced 2025-09-22 03:12:00 -04:00
Add gamepad device selection to menu (#2197)
* Add gamepad device selection to menu * Prevent accidentally disabling gamepad when it's being used
This commit is contained in:
parent
703e9e4aaa
commit
2a4eff0d59
@ -46,6 +46,7 @@ enum
|
||||
};
|
||||
|
||||
static boolean joy_enable;
|
||||
int joy_device, last_joy_device;
|
||||
joy_platform_t joy_platform;
|
||||
static int joy_stick_layout;
|
||||
static int joy_forward_sensitivity;
|
||||
@ -489,6 +490,7 @@ static void RefreshSettings(void)
|
||||
void I_BindGamepadVariables(void)
|
||||
{
|
||||
BIND_BOOL(joy_enable, true, "Enable gamepad");
|
||||
BIND_NUM_GENERAL(joy_device, 1, 0, UL, "Gamepad device (do not modify)");
|
||||
BIND_NUM(joy_platform, PLATFORM_AUTO, PLATFORM_AUTO, NUM_PLATFORMS - 1,
|
||||
"Gamepad platform (0 = Auto; 1 = Xbox 360; 2 = Xbox One/Series; "
|
||||
"3 = Playstation 3; 4 = Playstation 4; 5 = Playstation 5; 6 = Switch)");
|
||||
|
@ -70,6 +70,7 @@ typedef struct axes_s
|
||||
float outer_deadzone; // Normalized outer deadzone.
|
||||
} axes_t;
|
||||
|
||||
extern int joy_device, last_joy_device; // Gamepad device.
|
||||
extern joy_platform_t joy_platform; // Gamepad platform (button names).
|
||||
extern boolean joy_invert_forward; // Invert forward axis.
|
||||
extern boolean joy_invert_strafe; // Invert strafe axis.
|
||||
|
221
src/i_input.c
221
src/i_input.c
@ -30,13 +30,17 @@
|
||||
#include "i_rumble.h"
|
||||
#include "i_system.h"
|
||||
#include "i_timer.h"
|
||||
#include "m_array.h"
|
||||
#include "m_config.h"
|
||||
#include "m_input.h"
|
||||
#include "m_misc.h"
|
||||
#include "mn_menu.h"
|
||||
|
||||
#define AXIS_BUTTON_DEADZONE (SDL_JOYSTICK_AXIS_MAX / 3)
|
||||
|
||||
static const char **gamepad_strings;
|
||||
static SDL_GameController *gamepad;
|
||||
static SDL_JoystickID gamepad_instance_id = -1;
|
||||
static boolean gyro_supported;
|
||||
static joy_platform_t platform;
|
||||
|
||||
@ -430,9 +434,23 @@ static void DisableGamepadEvents(void)
|
||||
static void I_ShutdownGamepad(void)
|
||||
{
|
||||
I_ShutdownRumble();
|
||||
|
||||
if (gamepad)
|
||||
{
|
||||
SDL_GameControllerSetPlayerIndex(gamepad, -1);
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
}
|
||||
|
||||
static int NumJoysticks(void)
|
||||
{
|
||||
const int num_joysticks = SDL_NumJoysticks();
|
||||
return MAX(0, num_joysticks);
|
||||
}
|
||||
|
||||
void I_OpenGamepad(int device_index);
|
||||
|
||||
void I_InitGamepad(void)
|
||||
{
|
||||
UpdatePlatform();
|
||||
@ -460,63 +478,196 @@ void I_InitGamepad(void)
|
||||
I_Printf(VB_INFO, "I_InitGamepad: Initialize gamepad.");
|
||||
|
||||
I_AtExit(I_ShutdownGamepad, true);
|
||||
}
|
||||
|
||||
void I_OpenGamepad(int which)
|
||||
{
|
||||
if (gamepad)
|
||||
if (joy_device > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_IsGameController(which))
|
||||
{
|
||||
gamepad = SDL_GameControllerOpen(which);
|
||||
if (gamepad)
|
||||
if (SDL_IsGameController(joy_device - 1))
|
||||
{
|
||||
I_Printf(VB_INFO,
|
||||
"I_OpenGamepad: Found a valid gamepad, named: %s",
|
||||
SDL_GameControllerName(gamepad));
|
||||
|
||||
I_SetRumbleSupported(gamepad);
|
||||
I_ResetGamepad();
|
||||
I_LoadGyroCalibration();
|
||||
UpdatePlatform();
|
||||
EnableGamepadEvents();
|
||||
I_OpenGamepad(joy_device - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
joy_device = 1;
|
||||
MN_UpdateAllGamepadItems();
|
||||
}
|
||||
}
|
||||
|
||||
if (gamepad == NULL)
|
||||
else
|
||||
{
|
||||
I_Printf(VB_ERROR,
|
||||
"I_OpenGamepad: Could not open gamepad %i: %s",
|
||||
which, SDL_GetError());
|
||||
MN_UpdateAllGamepadItems();
|
||||
}
|
||||
|
||||
last_joy_device = joy_device;
|
||||
SDL_FlushEvents(SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED);
|
||||
}
|
||||
|
||||
static boolean CheckActiveGamepad(void)
|
||||
{
|
||||
if (gamepad_instance_id != -1)
|
||||
{
|
||||
const int num_joysticks = NumJoysticks();
|
||||
|
||||
for (int i = 0; i < num_joysticks; i++)
|
||||
{
|
||||
if (SDL_JoystickGetDeviceInstanceID(i) == gamepad_instance_id)
|
||||
{
|
||||
joy_device = i + 1;
|
||||
last_joy_device = joy_device;
|
||||
MN_UpdateAllGamepadItems();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void CloseGamepad(void)
|
||||
{
|
||||
if (gamepad_instance_id != -1)
|
||||
{
|
||||
I_ResetAllRumbleChannels();
|
||||
I_SetRumbleSupported(NULL);
|
||||
SDL_GameControllerSetPlayerIndex(gamepad, -1);
|
||||
SDL_GameControllerClose(gamepad);
|
||||
gamepad = NULL;
|
||||
gamepad_instance_id = -1;
|
||||
joy_device = 0;
|
||||
last_joy_device = joy_device;
|
||||
DisableGamepadEvents();
|
||||
UpdatePlatform();
|
||||
I_ResetGamepad();
|
||||
}
|
||||
}
|
||||
|
||||
void I_OpenGamepad(int device_index)
|
||||
{
|
||||
if (CheckActiveGamepad())
|
||||
{
|
||||
// Ignore when already using a gamepad.
|
||||
return;
|
||||
}
|
||||
|
||||
CloseGamepad();
|
||||
gamepad = SDL_GameControllerOpen(device_index);
|
||||
|
||||
if (gamepad)
|
||||
{
|
||||
I_Printf(VB_INFO, "I_OpenGamepad: Found a valid gamepad, named: %s",
|
||||
SDL_GameControllerName(gamepad));
|
||||
|
||||
gamepad_instance_id =
|
||||
SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamepad));
|
||||
joy_device = device_index + 1;
|
||||
last_joy_device = joy_device;
|
||||
I_SetRumbleSupported(gamepad);
|
||||
I_ResetAllRumbleChannels();
|
||||
I_ResetGamepad();
|
||||
UpdatePlatform();
|
||||
EnableGamepadEvents();
|
||||
SDL_GameControllerSetPlayerIndex(gamepad, 0);
|
||||
|
||||
if (gyro_supported)
|
||||
{
|
||||
I_LoadGyroCalibration();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
I_Printf(VB_ERROR, "I_OpenGamepad: Could not open gamepad %d: %s",
|
||||
device_index, SDL_GetError());
|
||||
}
|
||||
|
||||
MN_UpdateAllGamepadItems();
|
||||
}
|
||||
|
||||
void I_CloseGamepad(SDL_JoystickID instance_id)
|
||||
{
|
||||
if (gamepad == NULL)
|
||||
if (gamepad_instance_id != -1)
|
||||
{
|
||||
if (instance_id == gamepad_instance_id)
|
||||
{
|
||||
CloseGamepad();
|
||||
|
||||
if (NumJoysticks() && SDL_IsGameController(0))
|
||||
{
|
||||
// Fall back to another detected gamepad.
|
||||
I_OpenGamepad(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (CheckActiveGamepad())
|
||||
{
|
||||
// Ignore when already using a gamepad.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MN_UpdateAllGamepadItems();
|
||||
}
|
||||
|
||||
void I_UpdateGamepadDevice(boolean gamepad_input)
|
||||
{
|
||||
if (gamepad_input && joy_device == 0)
|
||||
{
|
||||
// Prevent accidentally disabling gamepad when it's being used.
|
||||
joy_device = last_joy_device;
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_JoystickID active_instance_id =
|
||||
SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamepad));
|
||||
last_joy_device = joy_device;
|
||||
const int device_index = joy_device - 1;
|
||||
CloseGamepad();
|
||||
|
||||
if (instance_id == active_instance_id)
|
||||
if (device_index >= 0)
|
||||
{
|
||||
I_OpenGamepad(device_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_GameControllerClose(gamepad);
|
||||
gamepad = NULL;
|
||||
I_SetRumbleSupported(NULL);
|
||||
DisableGamepadEvents();
|
||||
UpdatePlatform();
|
||||
I_ResetGamepad();
|
||||
MN_UpdateAllGamepadItems();
|
||||
}
|
||||
}
|
||||
|
||||
const char **I_GamepadDeviceList(void)
|
||||
{
|
||||
if (!I_GamepadEnabled())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
array_free(gamepad_strings);
|
||||
array_push(gamepad_strings, "None");
|
||||
|
||||
const int num_joysticks = NumJoysticks();
|
||||
int num_gamepads = 0;
|
||||
|
||||
for (int i = 0; i < num_joysticks; i++)
|
||||
{
|
||||
if (SDL_IsGameController(i))
|
||||
{
|
||||
char *name = M_StringDuplicate(SDL_GameControllerNameForIndex(i));
|
||||
array_push(gamepad_strings, name);
|
||||
num_gamepads++;
|
||||
}
|
||||
}
|
||||
|
||||
if (joy_device > num_gamepads)
|
||||
{
|
||||
for (int i = num_gamepads; i < joy_device; i++)
|
||||
{
|
||||
array_push(gamepad_strings, "None");
|
||||
}
|
||||
}
|
||||
|
||||
return gamepad_strings;
|
||||
}
|
||||
|
||||
boolean I_GamepadDevices(void)
|
||||
{
|
||||
return (array_size(gamepad_strings) > 1
|
||||
&& strncmp(gamepad_strings[1], "None", strlen(gamepad_strings[1])));
|
||||
}
|
||||
|
||||
static uint64_t GetSensorTimeUS(const SDL_ControllerSensorEvent *csensor)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 26, 0)
|
||||
|
@ -32,8 +32,11 @@ void I_FlushGamepadEvents(void);
|
||||
void I_SetSensorEventState(boolean condition);
|
||||
void I_SetSensorsEnabled(boolean condition);
|
||||
void I_InitGamepad(void);
|
||||
void I_OpenGamepad(int which);
|
||||
void I_OpenGamepad(int device_index);
|
||||
void I_CloseGamepad(SDL_JoystickID instance_id);
|
||||
void I_UpdateGamepadDevice(boolean gamepad_input);
|
||||
const char **I_GamepadDeviceList(void);
|
||||
boolean I_GamepadDevices(void);
|
||||
|
||||
void I_ReadMouse(void);
|
||||
void I_ReadGyro(void);
|
||||
|
@ -351,6 +351,7 @@ enum
|
||||
|
||||
str_mouse_accel,
|
||||
|
||||
str_gamepad_device,
|
||||
str_gyro_space,
|
||||
str_gyro_action,
|
||||
str_gyro_sens,
|
||||
@ -2900,15 +2901,34 @@ static const char *curve_strings[] = {
|
||||
static void MN_PadAdv(void);
|
||||
static void MN_Gyro(void);
|
||||
|
||||
static void UpdateGamepadDevice(void)
|
||||
{
|
||||
I_UpdateGamepadDevice(menu_input == pad_mode);
|
||||
}
|
||||
|
||||
static setup_menu_t gen_settings4[] = {
|
||||
|
||||
{"Device", S_CHOICE | S_ACTION | S_WRAP_LINE, CNTR_X, M_SPC * 2,
|
||||
{"joy_device"}, .strings_id = str_gamepad_device,
|
||||
.action = UpdateGamepadDevice},
|
||||
|
||||
MI_GAP_Y(1),
|
||||
|
||||
{"Turn Speed", S_THERMO | S_THRM_SIZE11, CNTR_X, M_THRM_SPC,
|
||||
{"joy_turn_speed"}, .action = I_ResetGamepad},
|
||||
|
||||
{"Look Speed", S_THERMO | S_THRM_SIZE11, CNTR_X, M_THRM_SPC,
|
||||
{"joy_look_speed"}, .action = I_ResetGamepad},
|
||||
|
||||
MI_GAP_Y(4),
|
||||
MI_GAP_Y(2),
|
||||
|
||||
{"Free Look", S_ONOFF, CNTR_X, M_SPC, {"padlook"},
|
||||
.action = MN_UpdatePadLook},
|
||||
|
||||
{"Invert Look", S_ONOFF, CNTR_X, M_SPC, {"joy_invert_look"},
|
||||
.action = I_ResetGamepad},
|
||||
|
||||
MI_GAP_Y(2),
|
||||
|
||||
{"Movement Deadzone", S_THERMO | S_PCT, CNTR_X, M_THRM_SPC,
|
||||
{"joy_movement_inner_deadzone"}, .action = I_ResetGamepad},
|
||||
@ -2916,20 +2936,10 @@ static setup_menu_t gen_settings4[] = {
|
||||
{"Camera Deadzone", S_THERMO | S_PCT, CNTR_X, M_THRM_SPC,
|
||||
{"joy_camera_inner_deadzone"}, .action = I_ResetGamepad},
|
||||
|
||||
MI_GAP_Y(4),
|
||||
|
||||
{"Rumble", S_THERMO, CNTR_X, M_THRM_SPC, {"joy_rumble"},
|
||||
.strings_id = str_percent, .action = UpdateRumble},
|
||||
|
||||
MI_GAP_Y(5),
|
||||
|
||||
{"Free Look", S_ONOFF, CNTR_X, M_SPC, {"padlook"},
|
||||
.action = MN_UpdatePadLook},
|
||||
|
||||
{"Invert Look", S_ONOFF, CNTR_X, M_SPC, {"joy_invert_look"},
|
||||
.action = I_ResetGamepad},
|
||||
|
||||
MI_GAP_Y(8),
|
||||
MI_GAP_Y(2),
|
||||
|
||||
{"Advanced Options", S_FUNC, CNTR_X, M_SPC, .action = MN_PadAdv},
|
||||
|
||||
@ -3037,13 +3047,15 @@ void MN_DrawPadAdv(void)
|
||||
|
||||
static void UpdateGamepadItems(void)
|
||||
{
|
||||
const boolean gamepad = (I_UseGamepad() && I_GamepadEnabled());
|
||||
const boolean devices = (I_GamepadEnabled() && I_GamepadDevices());
|
||||
const boolean gamepad = (I_UseGamepad() && devices);
|
||||
const boolean gyro = (I_GyroEnabled() && I_GyroSupported());
|
||||
const boolean sticks = I_UseStickLayout();
|
||||
const boolean flick = (gamepad && sticks && !I_StandardLayout());
|
||||
const boolean ramp = (gamepad && sticks && I_RampTimeEnabled());
|
||||
const boolean condition = (!gamepad || !sticks);
|
||||
|
||||
DisableItem(!devices, gen_settings4, "joy_device");
|
||||
DisableItem(!gamepad, gen_settings4, "Advanced Options");
|
||||
DisableItem(!gamepad || !I_GyroSupported(), gen_settings4, "Gyro Options");
|
||||
DisableItem(!gamepad || !I_RumbleSupported(), gen_settings4, "joy_rumble");
|
||||
@ -3194,13 +3206,6 @@ static void UpdateGyroItems(void)
|
||||
DisableItem(condition, gyro_settings1, "Calibrate");
|
||||
}
|
||||
|
||||
void MN_UpdateAllGamepadItems(void)
|
||||
{
|
||||
UpdateWeaponSlotSelection();
|
||||
UpdateGamepadItems();
|
||||
UpdateGyroItems();
|
||||
}
|
||||
|
||||
static setup_tab_t gyro_tabs[] = {{"Gyro"}, {NULL}};
|
||||
|
||||
static void MN_Gyro(void)
|
||||
@ -4813,6 +4818,7 @@ static const char **selectstrings[] = {
|
||||
NULL, // str_resampler
|
||||
equalizer_preset_strings,
|
||||
NULL, // str_mouse_accel
|
||||
NULL, // str_gamepad_device
|
||||
gyro_space_strings,
|
||||
gyro_action_strings,
|
||||
NULL, // str_gyro_sens
|
||||
@ -4837,6 +4843,19 @@ static const char **GetStrings(int id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char **GetGamepadDeviceStrings(void)
|
||||
{
|
||||
return I_GamepadDeviceList();
|
||||
}
|
||||
|
||||
void MN_UpdateAllGamepadItems(void)
|
||||
{
|
||||
selectstrings[str_gamepad_device] = GetGamepadDeviceStrings();
|
||||
UpdateWeaponSlotSelection();
|
||||
UpdateGamepadItems();
|
||||
UpdateGyroItems();
|
||||
}
|
||||
|
||||
static void UpdateWeaponSlotStrings(void)
|
||||
{
|
||||
selectstrings[str_weapon_slots] = GetWeaponSlotStrings();
|
||||
@ -4879,6 +4898,7 @@ void MN_InitMenuStrings(void)
|
||||
selectstrings[str_mouse_accel] = GetMouseAccelStrings();
|
||||
selectstrings[str_ms_time] = GetMsTimeStrings();
|
||||
selectstrings[str_movement_sensitivity] = GetMovementSensitivityStrings();
|
||||
selectstrings[str_gamepad_device] = GetGamepadDeviceStrings();
|
||||
selectstrings[str_gyro_sens] = GetGyroSensitivityStrings();
|
||||
selectstrings[str_gyro_accel] = GetGyroAccelStrings();
|
||||
selectstrings[str_resampler] = GetResamplerStrings();
|
||||
|
Loading…
x
Reference in New Issue
Block a user