mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Handle gamepads from interface dynamically
Fixes numerous issues with hotswapping, gamepad assignment, and menu responsiveness.
This commit is contained in:
parent
feb70916c1
commit
86a9579e16
18 changed files with 558 additions and 597 deletions
|
|
@ -449,7 +449,7 @@ boolean AM_Responder(event_t *ev)
|
|||
{
|
||||
//faB: prevent alt-tab in win32 version to activate automap just before
|
||||
// minimizing the app; doesn't do any harm to the DOS version
|
||||
if (!gamekeydown[0][KEY_LALT] && !gamekeydown[0][KEY_RALT])
|
||||
if (!G_GetDeviceGameKeyDownArray(0)[KEY_LALT] && !G_GetDeviceGameKeyDownArray(0)[KEY_RALT])
|
||||
{
|
||||
bigstate = 0; //added : 24-01-98 : toggle off large view
|
||||
AM_Start();
|
||||
|
|
|
|||
|
|
@ -1485,7 +1485,7 @@ void CL_UpdateServerList (void)
|
|||
|
||||
static void M_ConfirmConnect(void)
|
||||
{
|
||||
if (G_PlayerInputDown(0, gc_a, 1) || gamekeydown[0][KEY_ENTER])
|
||||
if (G_PlayerInputDown(0, gc_a, 1) || G_GetDeviceGameKeyDownArray(0)[KEY_ENTER])
|
||||
{
|
||||
if (totalfilesrequestednum > 0)
|
||||
{
|
||||
|
|
@ -1512,7 +1512,7 @@ static void M_ConfirmConnect(void)
|
|||
|
||||
M_StopMessage(0);
|
||||
}
|
||||
else if (G_PlayerInputDown(0, gc_b, 1) || G_PlayerInputDown(0, gc_x, 1) || gamekeydown[0][KEY_ESCAPE])
|
||||
else if (G_PlayerInputDown(0, gc_b, 1) || G_PlayerInputDown(0, gc_x, 1) || G_GetDeviceGameKeyDownArray(0)[KEY_ESCAPE])
|
||||
{
|
||||
cl_mode = CL_ABORTED;
|
||||
M_StopMessage(0);
|
||||
|
|
@ -1962,7 +1962,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
renderdeltatics = FRACUNIT;
|
||||
rendertimefrac = FRACUNIT;
|
||||
|
||||
memset(deviceResponding, false, sizeof (deviceResponding));
|
||||
G_ResetAllDeviceResponding();
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
|
|
@ -1979,7 +1979,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
{
|
||||
if (G_PlayerInputDown(0, gc_b, 1)
|
||||
|| G_PlayerInputDown(0, gc_x, 1)
|
||||
|| gamekeydown[0][KEY_ESCAPE])
|
||||
|| G_GetDeviceGameKeyDownArray(0)[KEY_ESCAPE])
|
||||
cl_mode = CL_ABORTED;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ typedef enum
|
|||
ev_keyup,
|
||||
ev_console,
|
||||
ev_mouse,
|
||||
ev_joystick,
|
||||
ev_gamepad_axis,
|
||||
ev_gamepad_device_added,
|
||||
ev_gamepad_device_removed,
|
||||
} evtype_t;
|
||||
|
||||
// Event structure.
|
||||
|
|
@ -38,7 +40,7 @@ struct event_t
|
|||
INT32 data1; // keys / mouse/joystick buttons
|
||||
INT32 data2; // mouse/joystick x move
|
||||
INT32 data3; // mouse/joystick y move
|
||||
INT32 device; // which player's device it belongs to
|
||||
INT32 device; // which device ID it belongs to (controller ID)
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
56
src/d_main.c
56
src/d_main.c
|
|
@ -171,6 +171,54 @@ UINT8 ctrldown = 0; // 0x1 left, 0x2 right
|
|||
UINT8 altdown = 0; // 0x1 left, 0x2 right
|
||||
boolean capslock = 0; // gee i wonder what this does.
|
||||
|
||||
static void HandleGamepadDeviceAdded(event_t *ev)
|
||||
{
|
||||
I_Assert(ev != NULL);
|
||||
I_Assert(ev->type == ev_gamepad_device_added);
|
||||
|
||||
G_RegisterAvailableGamepad(ev->device);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Registered available gamepad device %d\n", ev->device);
|
||||
}
|
||||
|
||||
static void HandleGamepadDeviceRemoved(event_t *ev)
|
||||
{
|
||||
int i = 0;
|
||||
I_Assert(ev != NULL);
|
||||
I_Assert(ev->type == ev_gamepad_device_removed);
|
||||
|
||||
G_UnregisterAvailableGamepad(ev->device);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Unregistered available gamepad device %d\n", ev->device);
|
||||
|
||||
// Downstream responders need to update player gamepad assignments, pause, etc
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
INT32 device = G_GetDeviceForPlayer(i);
|
||||
if (device == ev->device)
|
||||
{
|
||||
G_SetDeviceForPlayer(i, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Respond to added/removed device events, for bookkeeping available gamepads.
|
||||
static void HandleGamepadDeviceEvents(event_t *ev)
|
||||
{
|
||||
I_Assert(ev != NULL);
|
||||
|
||||
switch (ev->type)
|
||||
{
|
||||
case ev_gamepad_device_added:
|
||||
HandleGamepadDeviceAdded(ev);
|
||||
break;
|
||||
case ev_gamepad_device_removed:
|
||||
HandleGamepadDeviceRemoved(ev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// D_ProcessEvents
|
||||
// Send all the events of the given timestamp down the responder chain
|
||||
|
|
@ -183,11 +231,13 @@ void D_ProcessEvents(void)
|
|||
boolean eaten;
|
||||
boolean menuresponse = false;
|
||||
|
||||
memset(deviceResponding, false, sizeof (deviceResponding));
|
||||
G_ResetAllDeviceResponding();
|
||||
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
|
||||
{
|
||||
ev = &events[eventtail];
|
||||
|
||||
HandleGamepadDeviceEvents(ev);
|
||||
|
||||
// Screenshots over everything so that they can be taken anywhere.
|
||||
if (M_ScreenshotResponder(ev))
|
||||
continue; // ate the event
|
||||
|
|
@ -976,7 +1026,7 @@ void D_ClearState(void)
|
|||
|
||||
// clear cmd building stuff
|
||||
memset(gamekeydown, 0, sizeof (gamekeydown));
|
||||
memset(deviceResponding, false, sizeof (deviceResponding));
|
||||
G_ResetAllDeviceResponding();
|
||||
|
||||
// Reset the palette
|
||||
if (rendermode != render_none)
|
||||
|
|
@ -1507,6 +1557,8 @@ void D_SRB2Main(void)
|
|||
CONS_Printf("I_StartupGraphics()...\n");
|
||||
I_StartupGraphics();
|
||||
|
||||
I_StartupInput();
|
||||
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
I_NewTwodeeFrame();
|
||||
|
|
|
|||
|
|
@ -237,9 +237,6 @@ static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force
|
|||
#ifdef LJOYSTICK
|
||||
static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"}, {3, "/dev/js2"},
|
||||
{4, "/dev/js3"}, {0, NULL}};
|
||||
#else
|
||||
// accept whatever value - it is in fact the joystick device number
|
||||
static CV_PossibleValue_t usejoystick_cons_t[] = {{-1, "MIN"}, {MAXGAMEPADS, "MAX"}, {0, NULL}};
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}};
|
||||
|
|
@ -332,13 +329,6 @@ consvar_t cv_skipmapcheck = CVAR_INIT ("skipmapcheck", "Off", CV_SAVE, CV_OnOff,
|
|||
|
||||
consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse);
|
||||
|
||||
consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("use_device", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick1),
|
||||
CVAR_INIT ("use_device2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2),
|
||||
CVAR_INIT ("use_device3", "3", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick3),
|
||||
CVAR_INIT ("use_device4", "4", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick4)
|
||||
};
|
||||
|
||||
#if (defined (LJOYSTICK) || defined (HAVE_SDL))
|
||||
consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale),
|
||||
|
|
@ -1039,7 +1029,6 @@ void D_RegisterClientCommands(void)
|
|||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
CV_RegisterVar(&cv_usejoystick[i]);
|
||||
CV_RegisterVar(&cv_joyscale[i]);
|
||||
#ifdef LJOYSTICK
|
||||
CV_RegisterVar(&cv_joyport[i]);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ extern consvar_t cv_splitplayers;
|
|||
|
||||
extern consvar_t cv_seenames;
|
||||
extern consvar_t cv_usemouse;
|
||||
extern consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS];
|
||||
#ifdef LJOYSTICK
|
||||
extern consvar_t cv_joyport[MAXSPLITSCREENPLAYERS];
|
||||
|
|
|
|||
46
src/g_game.c
46
src/g_game.c
|
|
@ -884,6 +884,7 @@ static INT32 keyboardMenuDefaults[][2] = {
|
|||
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers)
|
||||
{
|
||||
INT32 deviceID;
|
||||
INT32 avail_gamepad_id = 0;
|
||||
INT32 i, j;
|
||||
INT32 deadzone = 0;
|
||||
boolean trydefaults = true;
|
||||
|
|
@ -900,7 +901,22 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers)
|
|||
|
||||
deadzone = (JOYAXISRANGE * cv_deadzone[p].value) / FRACUNIT;
|
||||
|
||||
deviceID = cv_usejoystick[p].value;
|
||||
deviceID = G_GetDeviceForPlayer(p);
|
||||
|
||||
if (deviceID == -1)
|
||||
{
|
||||
INT32 keyboard_player = G_GetPlayerForDevice(KEYBOARD_MOUSE_DEVICE);
|
||||
|
||||
// Player 1 is always allowed to use the keyboard in 1P (there is a check for splitscreen later in this func)
|
||||
if (p == KEYBOARD_MOUSE_DEVICE && keyboard_player == -1)
|
||||
{
|
||||
deviceID = KEYBOARD_MOUSE_DEVICE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto deviceunassigned;
|
||||
}
|
||||
}
|
||||
|
||||
retrygetcontrol:
|
||||
for (i = 0; i < MAXINPUTMAPPING; i++)
|
||||
|
|
@ -910,7 +926,6 @@ retrygetcontrol:
|
|||
INT32 value = 0;
|
||||
boolean processinput = true;
|
||||
|
||||
|
||||
// for menus, keyboards have defaults!
|
||||
if (deviceID == 0)
|
||||
{
|
||||
|
|
@ -951,9 +966,9 @@ retrygetcontrol:
|
|||
// It's possible to access this control right now, so let's disable the default control backup for later.
|
||||
trydefaults = false;
|
||||
|
||||
value = gamekeydown[deviceID][key];
|
||||
if (menukey && gamekeydown[deviceID][menukey])
|
||||
value = gamekeydown[deviceID][menukey];
|
||||
value = G_GetDeviceGameKeyDownArray(deviceID)[key];
|
||||
if (menukey && G_GetDeviceGameKeyDownArray(deviceID)[menukey])
|
||||
value = G_GetDeviceGameKeyDownArray(deviceID)[menukey];
|
||||
|
||||
if (value >= deadzone)
|
||||
{
|
||||
|
|
@ -962,11 +977,13 @@ retrygetcontrol:
|
|||
}
|
||||
}
|
||||
|
||||
deviceunassigned:
|
||||
|
||||
// If you're on controller, try your keyboard-based binds as an immediate backup.
|
||||
// Do not do this if there are more than 1 local player.
|
||||
if (p == 0 && deviceID > 0 && !tryingotherID && menuPlayers < 2 && !splitscreen)
|
||||
{
|
||||
deviceID = 0;
|
||||
deviceID = KEYBOARD_MOUSE_DEVICE;
|
||||
goto retrygetcontrol;
|
||||
}
|
||||
|
||||
|
|
@ -981,16 +998,21 @@ retrygetcontrol:
|
|||
|
||||
if (!tryingotherID)
|
||||
{
|
||||
deviceID = MAXDEVICES;
|
||||
avail_gamepad_id = 0;
|
||||
tryingotherID = true;
|
||||
}
|
||||
loweringid:
|
||||
deviceID--;
|
||||
if (avail_gamepad_id >= G_GetNumAvailableGamepads())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
deviceID = G_GetAvailableGamepadDevice(avail_gamepad_id);
|
||||
avail_gamepad_id += 1;
|
||||
if (deviceID > 0)
|
||||
{
|
||||
for (i = 0; i < menuPlayers; i++)
|
||||
{
|
||||
if (deviceID != cv_usejoystick[i].value)
|
||||
if (deviceID != G_GetDeviceForPlayer(i))
|
||||
continue;
|
||||
// Controller taken? Try again...
|
||||
goto loweringid;
|
||||
|
|
@ -1005,7 +1027,7 @@ loweringid:
|
|||
trydefaults = false;
|
||||
controltable = &(gamecontroldefault[gc][0]);
|
||||
tryingotherID = false;
|
||||
deviceID = cv_usejoystick[p].value;
|
||||
deviceID = G_GetDeviceForPlayer(p);
|
||||
goto retrygetcontrol;
|
||||
|
||||
}
|
||||
|
|
@ -1530,7 +1552,7 @@ void G_DoLoadLevel(boolean resetplayer)
|
|||
|
||||
// clear cmd building stuff
|
||||
memset(gamekeydown, 0, sizeof (gamekeydown));
|
||||
memset(deviceResponding, false, sizeof (deviceResponding));
|
||||
G_ResetAllDeviceResponding();
|
||||
|
||||
// clear hud messages remains (usually from game startup)
|
||||
CON_ClearHUD();
|
||||
|
|
@ -1828,7 +1850,7 @@ boolean G_Responder(event_t *ev)
|
|||
case ev_mouse:
|
||||
return true; // eat events
|
||||
|
||||
case ev_joystick:
|
||||
case ev_gamepad_axis:
|
||||
return true; // eat events
|
||||
|
||||
default:
|
||||
|
|
|
|||
298
src/g_input.c
298
src/g_input.c
|
|
@ -19,6 +19,7 @@
|
|||
#include "d_net.h"
|
||||
#include "console.h"
|
||||
#include "i_joy.h" // JOYAXISRANGE
|
||||
#include "z_zone.h"
|
||||
|
||||
#define MAXMOUSESENSITIVITY 100 // sensitivity steps
|
||||
|
||||
|
|
@ -35,7 +36,6 @@ consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecont
|
|||
// current state of the keys
|
||||
// FRACUNIT for fully pressed, 0 for not pressed
|
||||
INT32 gamekeydown[MAXDEVICES][NUMINPUTS];
|
||||
boolean deviceResponding[MAXDEVICES];
|
||||
|
||||
// two key codes (or virtual key) per game control
|
||||
INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING];
|
||||
|
|
@ -68,13 +68,82 @@ const INT32 gcl_full[num_gcl_full] = {
|
|||
};
|
||||
*/
|
||||
|
||||
INT32 G_GetDevicePlayer(INT32 deviceID)
|
||||
static INT32 g_gamekeydown_device0[NUMINPUTS];
|
||||
|
||||
static INT32 g_available_gamepad_devices;
|
||||
static INT32 g_gamepad_device_ids[MAXGAMEPADS];
|
||||
static INT32* g_gamepad_gamekeydown[MAXGAMEPADS];
|
||||
static boolean g_device0_responding;
|
||||
static boolean g_gamepad_responding[MAXGAMEPADS];
|
||||
static INT32 g_player_devices[MAXSPLITSCREENPLAYERS] = {-1, -1, -1, -1};
|
||||
|
||||
void G_RegisterAvailableGamepad(INT32 device_id)
|
||||
{
|
||||
I_Assert(device_id >= 1);
|
||||
|
||||
if (g_available_gamepad_devices == MAXGAMEPADS)
|
||||
{
|
||||
// too many!
|
||||
return;
|
||||
}
|
||||
|
||||
g_gamepad_device_ids[g_available_gamepad_devices] = device_id;
|
||||
|
||||
g_gamepad_gamekeydown[g_available_gamepad_devices] = Z_CallocAlign(NUMINPUTS * sizeof(INT32), PU_STATIC, NULL, 4);
|
||||
|
||||
g_gamepad_responding[g_available_gamepad_devices] = false;
|
||||
|
||||
g_available_gamepad_devices += 1;
|
||||
}
|
||||
|
||||
void G_UnregisterAvailableGamepad(INT32 device_id)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
I_Assert(device_id >= 1);
|
||||
|
||||
if (g_available_gamepad_devices <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_available_gamepad_devices; i++)
|
||||
{
|
||||
if (g_gamepad_device_ids[i] == device_id)
|
||||
{
|
||||
int32_t *old_gamekeydown = g_gamepad_gamekeydown[i];
|
||||
g_gamepad_device_ids[i] = g_gamepad_device_ids[g_available_gamepad_devices - 1];
|
||||
g_gamepad_gamekeydown[i] = g_gamepad_gamekeydown[g_available_gamepad_devices - 1];
|
||||
g_gamepad_responding[i] = g_gamepad_responding[g_available_gamepad_devices - 1];
|
||||
Z_Free(old_gamekeydown);
|
||||
g_available_gamepad_devices -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT32 G_GetNumAvailableGamepads(void)
|
||||
{
|
||||
return g_available_gamepad_devices;
|
||||
}
|
||||
|
||||
INT32 G_GetAvailableGamepadDevice(INT32 available_index)
|
||||
{
|
||||
if (available_index < 0 || available_index >= G_GetNumAvailableGamepads())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return g_gamepad_device_ids[available_index];
|
||||
}
|
||||
|
||||
INT32 G_GetPlayerForDevice(INT32 device_id)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (deviceID == cv_usejoystick[i].value)
|
||||
if (device_id == g_player_devices[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
|
@ -83,6 +152,172 @@ INT32 G_GetDevicePlayer(INT32 deviceID)
|
|||
return -1;
|
||||
}
|
||||
|
||||
INT32 G_GetDeviceForPlayer(INT32 player)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (G_GetPlayerForDevice(KEYBOARD_MOUSE_DEVICE) == player)
|
||||
{
|
||||
return KEYBOARD_MOUSE_DEVICE;
|
||||
}
|
||||
|
||||
for (i = 0; i < G_GetNumAvailableGamepads() + 1; i++)
|
||||
{
|
||||
INT32 device = G_GetAvailableGamepadDevice(i);
|
||||
if (G_GetPlayerForDevice(device) == player)
|
||||
{
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void G_SetDeviceForPlayer(INT32 player, INT32 device)
|
||||
{
|
||||
int i;
|
||||
|
||||
I_Assert(player >= 0 && player < MAXSPLITSCREENPLAYERS);
|
||||
I_Assert(device >= -1);
|
||||
|
||||
g_player_devices[player] = device;
|
||||
|
||||
if (device == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (device != KEYBOARD_MOUSE_DEVICE)
|
||||
{
|
||||
I_SetGamepadPlayerIndex(device, player);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (i == player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_player_devices[i] == device)
|
||||
{
|
||||
g_player_devices[i] = -1;
|
||||
if (device > 0)
|
||||
{
|
||||
I_SetGamepadPlayerIndex(device, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT32* G_GetDeviceGameKeyDownArray(INT32 device)
|
||||
{
|
||||
int i;
|
||||
|
||||
I_Assert(device >= 0);
|
||||
|
||||
if (device == KEYBOARD_MOUSE_DEVICE)
|
||||
{
|
||||
return g_gamekeydown_device0;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_available_gamepad_devices; i++)
|
||||
{
|
||||
if (g_gamepad_device_ids[i] == device)
|
||||
{
|
||||
return g_gamepad_gamekeydown[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
boolean G_IsDeviceResponding(INT32 device)
|
||||
{
|
||||
int i;
|
||||
|
||||
I_Assert(device >= 0);
|
||||
|
||||
if (device == KEYBOARD_MOUSE_DEVICE)
|
||||
{
|
||||
return g_device0_responding;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_available_gamepad_devices; i++)
|
||||
{
|
||||
INT32 device_id = G_GetAvailableGamepadDevice(i);
|
||||
if (device_id == device)
|
||||
{
|
||||
return g_gamepad_responding[i];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void G_SetDeviceResponding(INT32 device, boolean responding)
|
||||
{
|
||||
int i;
|
||||
|
||||
I_Assert(device >= 0);
|
||||
|
||||
if (device == KEYBOARD_MOUSE_DEVICE)
|
||||
{
|
||||
g_device0_responding = responding;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_available_gamepad_devices; i++)
|
||||
{
|
||||
INT32 device_id = G_GetAvailableGamepadDevice(i);
|
||||
if (device_id == device)
|
||||
{
|
||||
g_gamepad_responding[i] = responding;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G_ResetAllDeviceResponding(void)
|
||||
{
|
||||
int i;
|
||||
int num_gamepads;
|
||||
|
||||
g_device0_responding = false;
|
||||
|
||||
num_gamepads = G_GetNumAvailableGamepads();
|
||||
|
||||
for (i = 0; i < num_gamepads; i++)
|
||||
{
|
||||
g_gamepad_responding[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean AutomaticControllerReassignmentIsAllowed(INT32 device)
|
||||
{
|
||||
boolean device_is_gamepad = device > 0;
|
||||
boolean device_is_unassigned = G_GetPlayerForDevice(device) == -1;
|
||||
boolean gamestate_is_in_level = gamestate == GS_LEVEL;
|
||||
|
||||
return device_is_gamepad && device_is_unassigned && gamestate_is_in_level;
|
||||
}
|
||||
|
||||
static INT32 AssignDeviceToFirstUnassignedPlayer(INT32 device)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < splitscreen + 1; i++)
|
||||
{
|
||||
if (G_GetDeviceForPlayer(i) == -1)
|
||||
{
|
||||
G_SetDeviceForPlayer(i, device);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Remaps the inputs to game controls.
|
||||
//
|
||||
|
|
@ -94,15 +329,15 @@ void G_MapEventsToControls(event_t *ev)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
if (ev->device >= 0 && ev->device < MAXDEVICES)
|
||||
if (ev->device >= 0)
|
||||
{
|
||||
switch (ev->type)
|
||||
{
|
||||
case ev_keydown:
|
||||
//case ev_keyup:
|
||||
//case ev_mouse:
|
||||
//case ev_joystick:
|
||||
deviceResponding[ev->device] = true;
|
||||
//case ev_gamepad_axis:
|
||||
G_SetDeviceResponding(ev->device, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -119,7 +354,16 @@ void G_MapEventsToControls(event_t *ev)
|
|||
case ev_keydown:
|
||||
if (ev->data1 < NUMINPUTS)
|
||||
{
|
||||
gamekeydown[ev->device][ev->data1] = JOYAXISRANGE;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[ev->data1] = JOYAXISRANGE;
|
||||
|
||||
if (AutomaticControllerReassignmentIsAllowed(ev->device))
|
||||
{
|
||||
INT32 assigned = AssignDeviceToFirstUnassignedPlayer(ev->device);
|
||||
if (assigned >= 0)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, "Player %d device was reassigned\n", assigned + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef PARANOIA
|
||||
else
|
||||
|
|
@ -132,7 +376,7 @@ void G_MapEventsToControls(event_t *ev)
|
|||
case ev_keyup:
|
||||
if (ev->data1 < NUMINPUTS)
|
||||
{
|
||||
gamekeydown[ev->device][ev->data1] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[ev->data1] = 0;
|
||||
}
|
||||
#ifdef PARANOIA
|
||||
else
|
||||
|
|
@ -147,32 +391,32 @@ void G_MapEventsToControls(event_t *ev)
|
|||
if (ev->data2 < 0)
|
||||
{
|
||||
// Left
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE + 2] = abs(ev->data2);
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE + 3] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 2] = abs(ev->data2);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Right
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE + 2] = 0;
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE + 3] = abs(ev->data2);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 2] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 3] = abs(ev->data2);
|
||||
}
|
||||
|
||||
// Y axis
|
||||
if (ev->data3 < 0)
|
||||
{
|
||||
// Up
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE] = abs(ev->data3);
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE + 1] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE] = abs(ev->data3);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Down
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE] = 0;
|
||||
gamekeydown[ev->device][KEY_MOUSEMOVE + 1] = abs(ev->data3);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 1] = abs(ev->data3);
|
||||
}
|
||||
break;
|
||||
|
||||
case ev_joystick: // buttons are virtual keys
|
||||
case ev_gamepad_axis: // buttons are virtual keys
|
||||
if (ev->data1 >= JOYAXISSETS)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
|
|
@ -190,12 +434,12 @@ void G_MapEventsToControls(event_t *ev)
|
|||
|
||||
if (ev->data2 != INT32_MAX)
|
||||
{
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2);
|
||||
}
|
||||
|
||||
if (ev->data3 != INT32_MAX)
|
||||
{
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -206,14 +450,14 @@ void G_MapEventsToControls(event_t *ev)
|
|||
if (ev->data2 < 0)
|
||||
{
|
||||
// Left
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4)] = abs(ev->data2);
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 1] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4)] = abs(ev->data2);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Right
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4)] = 0;
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4)] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -222,14 +466,14 @@ void G_MapEventsToControls(event_t *ev)
|
|||
if (ev->data3 < 0)
|
||||
{
|
||||
// Up
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 2] = abs(ev->data3);
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 3] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 2] = abs(ev->data3);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Down
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 2] = 0;
|
||||
gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3);
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 2] = 0;
|
||||
G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,8 +107,8 @@ extern consvar_t cv_controlperkey;
|
|||
// current state of the keys: JOYAXISRANGE or 0 when boolean.
|
||||
// Or anything inbetween for analog values
|
||||
#define MAXDEVICES (MAXGAMEPADS + 1) // Gamepads + keyboard & mouse
|
||||
#define KEYBOARD_MOUSE_DEVICE 0
|
||||
extern INT32 gamekeydown[MAXDEVICES][NUMINPUTS];
|
||||
extern boolean deviceResponding[MAXDEVICES];
|
||||
|
||||
// several key codes (or virtual key) per game control
|
||||
extern INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING];
|
||||
|
|
@ -135,7 +135,31 @@ extern const INT32 gcl_full[num_gcl_full];
|
|||
// peace to my little coder fingers!
|
||||
// check a gamecontrol being active or not
|
||||
|
||||
INT32 G_GetDevicePlayer(INT32 deviceID);
|
||||
/*
|
||||
*/
|
||||
|
||||
/// Register a device index (from ev_gamepad_device_added) as an Available Gamepad
|
||||
void G_RegisterAvailableGamepad(INT32 device_id);
|
||||
/// Unregister a device index (from ev_gamepad_device_removed) as an Available Gamepad
|
||||
void G_UnregisterAvailableGamepad(INT32 device_id);
|
||||
/// Get the number of Available Gamepads registered.
|
||||
INT32 G_GetNumAvailableGamepads(void);
|
||||
/// Get the device ID for a given Available Gamepad Index, or -1. 0 <= available_index < G_GetNumAvailableGamepads()
|
||||
INT32 G_GetAvailableGamepadDevice(INT32 available_index);
|
||||
|
||||
INT32 G_GetPlayerForDevice(INT32 deviceID);
|
||||
/// Get gamepad device for given player, or -1.
|
||||
INT32 G_GetDeviceForPlayer(INT32 player);
|
||||
|
||||
/// Set the given player index's assigned device. If the device is in use by another player, that player is unassigned.
|
||||
void G_SetDeviceForPlayer(INT32 player, INT32 device);
|
||||
|
||||
/// Get the gamekeydown array (NUMINPUTS values) for the given device, or NULL if the device id is invalid.
|
||||
INT32* G_GetDeviceGameKeyDownArray(INT32 device);
|
||||
|
||||
boolean G_IsDeviceResponding(INT32 device);
|
||||
void G_SetDeviceResponding(INT32 device, boolean responding);
|
||||
void G_ResetAllDeviceResponding(void);
|
||||
|
||||
// remaps the input event to a game control.
|
||||
void G_MapEventsToControls(event_t *ev);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ struct JoyType_t
|
|||
|
||||
extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
void I_SetGamepadPlayerIndex(INT32 device_id, INT32 index);
|
||||
void I_SetGamepadIndicatorColor(INT32 device_id, UINT8 red, UINT8 green, UINT8 blue);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -205,9 +205,8 @@ void I_JoyScale4(void);
|
|||
|
||||
// Called by D_SRB2Main.
|
||||
|
||||
/** \brief to startup a joystick
|
||||
*/
|
||||
void I_InitJoystick(UINT8 index);
|
||||
/// Startup input subsystems.
|
||||
void I_StartupInput(void);
|
||||
|
||||
/** \brief to startup the first joystick
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -60,13 +60,6 @@
|
|||
// And just some randomness for the exits.
|
||||
#include "m_random.h"
|
||||
|
||||
#if defined(HAVE_SDL)
|
||||
#include "SDL.h"
|
||||
#if SDL_VERSION_ATLEAST(2,0,0)
|
||||
#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PC_DOS
|
||||
#include <stdio.h> // for snprintf
|
||||
int snprintf(char *str, size_t n, const char *fmt, ...);
|
||||
|
|
@ -3385,11 +3378,18 @@ void M_DrawProfileControls(void)
|
|||
// Get userbound controls...
|
||||
for (k = 0; k < MAXINPUTMAPPING; k++)
|
||||
{
|
||||
int device;
|
||||
keys[k] = optionsmenu.tempcontrols[gc][k];
|
||||
if (keys[k] == KEY_NULL)
|
||||
continue;
|
||||
set++;
|
||||
if (!G_KeyIsAvailable(keys[k], cv_usejoystick[0].value))
|
||||
|
||||
device = G_GetDeviceForPlayer(0);
|
||||
if (device == -1)
|
||||
{
|
||||
device = 0;
|
||||
}
|
||||
if (!G_KeyIsAvailable(keys[k], device))
|
||||
continue;
|
||||
available++;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -222,6 +222,22 @@ boolean M_Responder(event_t *ev)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (gamestate == GS_MENU && ev->type == ev_gamepad_device_removed && G_GetPlayerForDevice(ev->device) != -1)
|
||||
{
|
||||
int i;
|
||||
INT32 player = G_GetPlayerForDevice(ev->device);
|
||||
|
||||
// Unassign all controllers
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
G_SetDeviceForPlayer(i, -1);
|
||||
}
|
||||
|
||||
// Return to the title because a controller was removed at the menu.
|
||||
CONS_Alert(CONS_NOTICE, "Player %d's assigned gamepad was removed. Returning to the title screen.", player);
|
||||
D_StartTitle();
|
||||
}
|
||||
|
||||
if (ev->type == ev_keydown && ev->data1 < NUMKEYS)
|
||||
{
|
||||
// Record keyboard presses
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ static void SetDeviceOnPress(void)
|
|||
{
|
||||
if (deviceResponding[i])
|
||||
{
|
||||
CV_SetValue(&cv_usejoystick[0], i); // Force-set this joystick as the current joystick we're using for P1 (which is the only one controlling menus)
|
||||
G_SetDeviceForPlayer(0, i); // Force-set this joystick as the current joystick we're using for P1 (which is the only one controlling menus)
|
||||
CONS_Printf("SetDeviceOnPress: Device for %d set to %d\n", 0, i);
|
||||
return;
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ void M_MapProfileControl(event_t *ev)
|
|||
UINT8 where = n; // By default, we'll save the bind where we're supposed to map.
|
||||
INT32 i;
|
||||
|
||||
//SetDeviceOnPress(); // Update cv_usejoystick
|
||||
//SetDeviceOnPress(); // Update player gamepad assignments
|
||||
|
||||
// Only consider keydown and joystick events to make sure we ignore ev_mouse and other events
|
||||
// See also G_MapEventsToControls
|
||||
|
|
@ -325,11 +325,11 @@ void M_MapProfileControl(event_t *ev)
|
|||
}
|
||||
#endif
|
||||
break;
|
||||
case ev_joystick:
|
||||
case ev_gamepad_axis:
|
||||
if (ev->data1 >= JOYAXES)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Bad gamepad axis event %d\n", ev->data1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -380,10 +380,10 @@ void M_CharacterSelectInit(void)
|
|||
{
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
// Un-set devices for other players.
|
||||
if (i != 0 || optionsmenu.profile)
|
||||
// Un-set devices for all players if not editing profile
|
||||
if (!optionsmenu.profile)
|
||||
{
|
||||
CV_SetValue(&cv_usejoystick[i], -1);
|
||||
G_SetDeviceForPlayer(i, -1);
|
||||
CONS_Printf("M_CharacterSelectInit: Device for %d set to %d\n", i, -1);
|
||||
}
|
||||
}
|
||||
|
|
@ -526,7 +526,12 @@ static boolean M_DeviceAvailable(INT32 deviceID, UINT8 numPlayers)
|
|||
|
||||
for (i = 0; i < numPlayers; i++)
|
||||
{
|
||||
if (cv_usejoystick[i].value == deviceID)
|
||||
int player_device = G_GetDeviceForPlayer(i);
|
||||
if (player_device == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (player_device == deviceID)
|
||||
{
|
||||
// This one's already being used.
|
||||
return false;
|
||||
|
|
@ -540,6 +545,7 @@ static boolean M_DeviceAvailable(INT32 deviceID, UINT8 numPlayers)
|
|||
static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
|
||||
{
|
||||
INT32 i, j;
|
||||
INT32 num_gamepads_available;
|
||||
|
||||
if (optionsmenu.profile)
|
||||
return false; // Don't allow for the possibility of SOMEHOW another player joining in.
|
||||
|
|
@ -568,24 +574,32 @@ static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
|
||||
// Now detect new devices trying to join.
|
||||
for (i = 0; i < MAXDEVICES; i++)
|
||||
num_gamepads_available = G_GetNumAvailableGamepads();
|
||||
for (i = 0; i < num_gamepads_available + 1; i++)
|
||||
{
|
||||
if (deviceResponding[i] != true)
|
||||
INT32 device = 0;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
device = G_GetAvailableGamepadDevice(i - 1);
|
||||
}
|
||||
|
||||
if (G_IsDeviceResponding(device) != true)
|
||||
{
|
||||
// No buttons are being pushed.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (M_DeviceAvailable(i, setup_numplayers) == true)
|
||||
if (M_DeviceAvailable(device, setup_numplayers) == true)
|
||||
{
|
||||
// Available!! Let's use this one!!
|
||||
|
||||
// if P1 is setting up using keyboard (device 0), save their last used device.
|
||||
// this is to allow them to retain controller usage when they play alone.
|
||||
// Because let's face it, when you test mods, you're often lazy to grab your controller for menuing :)
|
||||
if (!i && !num)
|
||||
if (i == 0 && num == 0)
|
||||
{
|
||||
setup_player[num].ponedevice = cv_usejoystick[num].value;
|
||||
setup_player[num].ponedevice = G_GetDeviceForPlayer(num);
|
||||
}
|
||||
else if (num)
|
||||
{
|
||||
|
|
@ -593,14 +607,13 @@ static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
|
|||
memcpy(&gamecontrol[num], gamecontroldefault, sizeof(gamecontroldefault));
|
||||
}
|
||||
|
||||
|
||||
CV_SetValue(&cv_usejoystick[num], i);
|
||||
CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", num, i);
|
||||
G_SetDeviceForPlayer(num, device);
|
||||
CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", num, device);
|
||||
|
||||
for (j = num + 1; j < MAXSPLITSCREENPLAYERS; j++)
|
||||
{
|
||||
// Un-set devices for other players.
|
||||
CV_SetValue(&cv_usejoystick[j], -1);
|
||||
G_SetDeviceForPlayer(j, -1);
|
||||
CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", j, -1);
|
||||
}
|
||||
|
||||
|
|
@ -616,7 +629,7 @@ static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
|
|||
menucmd[j].buttonsHeld |= MBT_X;
|
||||
}
|
||||
|
||||
memset(deviceResponding, false, sizeof(deviceResponding));
|
||||
G_ResetAllDeviceResponding();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -668,11 +681,8 @@ static boolean M_HandleCSelectProfile(setup_player_t *p, UINT8 num)
|
|||
menucmd[i].buttonsHeld |= MBT_X;
|
||||
}
|
||||
|
||||
if (num > 0)
|
||||
{
|
||||
CV_StealthSetValue(&cv_usejoystick[num], -1);
|
||||
G_SetDeviceForPlayer(num, -1);
|
||||
CONS_Printf("M_HandleCSelectProfile: Device for %d set to %d\n", num, -1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1482,12 +1492,6 @@ void M_CharacterSelectTick(void)
|
|||
|
||||
CV_StealthSetValue(&cv_splitplayers, setup_numplayers);
|
||||
|
||||
// P1 is alone, set their old device just in case.
|
||||
if (setup_numplayers < 2 && setup_player[0].ponedevice)
|
||||
{
|
||||
CV_StealthSetValue(&cv_usejoystick[0], setup_player[0].ponedevice);
|
||||
}
|
||||
|
||||
#if defined (TESTERS)
|
||||
M_MPOptSelectInit(0);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -194,48 +194,6 @@ static char returnWadPath[256];
|
|||
#include "../byteptr.h"
|
||||
#endif
|
||||
|
||||
void I_StoreExJoystick(SDL_GameController *dev)
|
||||
{
|
||||
// ExJoystick is a massive hack to avoid needing to completely
|
||||
// rewrite pretty much all of the controller support from scratch...
|
||||
|
||||
// Used in favor of most instances of SDL_GameControllerClose.
|
||||
// If a joystick would've been discarded, then save it in an array,
|
||||
// because we want it have it for the joystick input screen.
|
||||
|
||||
int index = 0;
|
||||
|
||||
if (dev == NULL)
|
||||
{
|
||||
// No joystick?
|
||||
return;
|
||||
}
|
||||
|
||||
index = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(dev));
|
||||
|
||||
if (index >= MAXGAMEPADS || index < 0)
|
||||
{
|
||||
// Not enough space to save this joystick, completely discard.
|
||||
SDL_GameControllerClose(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ExJoystick[index] == dev)
|
||||
{
|
||||
// No need to do anything else.
|
||||
return;
|
||||
}
|
||||
|
||||
if (ExJoystick[index] != NULL)
|
||||
{
|
||||
// Discard joystick in the old slot.
|
||||
SDL_GameControllerClose(ExJoystick[index]);
|
||||
}
|
||||
|
||||
// Keep for safe-keeping.
|
||||
ExJoystick[index] = dev;
|
||||
}
|
||||
|
||||
/** \brief The JoyReset function
|
||||
|
||||
\param JoySet Joystick info to reset
|
||||
|
|
@ -244,10 +202,6 @@ void I_StoreExJoystick(SDL_GameController *dev)
|
|||
*/
|
||||
static void JoyReset(SDLJoyInfo_t *JoySet)
|
||||
{
|
||||
if (JoySet->dev)
|
||||
{
|
||||
I_StoreExJoystick(JoySet->dev);
|
||||
}
|
||||
JoySet->dev = NULL;
|
||||
JoySet->oldjoy = -1;
|
||||
JoySet->axises = JoySet->buttons = JoySet->hats = JoySet->balls = 0;
|
||||
|
|
@ -261,7 +215,6 @@ static INT32 joystick_started[MAXSPLITSCREENPLAYERS] = {0,0,0,0};
|
|||
/** \brief SDL info about joystick 1
|
||||
*/
|
||||
SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS];
|
||||
SDL_GameController *ExJoystick[MAXGAMEPADS];
|
||||
|
||||
SDL_bool consolevent = SDL_FALSE;
|
||||
SDL_bool framebuffer = SDL_FALSE;
|
||||
|
|
@ -983,316 +936,78 @@ void I_JoyScale4(void)
|
|||
JoyInfo[3].scale = Joystick[3].bGamepadStyle?1:cv_joyscale[1].value;
|
||||
}
|
||||
|
||||
// Cheat to get the device index for a game controller handle
|
||||
INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev)
|
||||
void I_SetGamepadPlayerIndex(INT32 device_id, INT32 player)
|
||||
{
|
||||
SDL_Joystick *joystick = NULL;
|
||||
#if !(SDL_VERSION_ATLEAST(2,0,12))
|
||||
(void)device_id;
|
||||
(void)player;
|
||||
#else
|
||||
I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher
|
||||
I_Assert(player >= 0 && player < MAXSPLITSCREENPLAYERS);
|
||||
|
||||
joystick = SDL_GameControllerGetJoystick(dev);
|
||||
|
||||
if (joystick)
|
||||
SDL_GameController *controller = SDL_GameControllerFromInstanceID(device_id - 1);
|
||||
if (controller == NULL)
|
||||
{
|
||||
return SDL_JoystickInstanceID(joystick);
|
||||
return;
|
||||
}
|
||||
|
||||
return -1;
|
||||
SDL_GameControllerSetPlayerIndex(controller, player);
|
||||
#endif
|
||||
}
|
||||
|
||||
void I_UpdateJoystickDeviceIndex(UINT8 player)
|
||||
void I_SetGamepadIndicatorColor(INT32 device_id, UINT8 red, UINT8 green, UINT8 blue)
|
||||
{
|
||||
///////////////////////////////////////////////
|
||||
// update this joystick's device index (wow) //
|
||||
///////////////////////////////////////////////
|
||||
#if !(SDL_VERSION_ATLEAST(2,0,14))
|
||||
(void)device_id;
|
||||
(void)player;
|
||||
#else
|
||||
I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher
|
||||
|
||||
if (JoyInfo[player].dev)
|
||||
SDL_GameController *controller = SDL_GameControllerFromInstanceID(device_id - 1);
|
||||
if (controller == NULL)
|
||||
{
|
||||
cv_usejoystick[player].value = I_GetJoystickDeviceIndex(JoyInfo[player].dev) + 1;
|
||||
CONS_Printf("I_UpdateJoystickDeviceIndex: Device for %d set to %d\n", player, cv_usejoystick[player].value);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 joystickID, compareJoystick;
|
||||
|
||||
for (joystickID = 0; joystickID < MAXSPLITSCREENPLAYERS; joystickID++)
|
||||
{
|
||||
// is this cv_usejoystick used?
|
||||
const INT32 value = atoi(cv_usejoystick[joystickID].string);
|
||||
|
||||
for (compareJoystick = 0; compareJoystick < MAXSPLITSCREENPLAYERS; compareJoystick++)
|
||||
{
|
||||
if (compareJoystick == player)
|
||||
continue;
|
||||
|
||||
if (value == JoyInfo[compareJoystick].oldjoy || value == cv_usejoystick[compareJoystick].value)
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
if (compareJoystick == MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
// We DID make it through the whole loop, so we can use this one!
|
||||
cv_usejoystick[player].value = value;
|
||||
CONS_Printf("I_UpdateJoystickDeviceIndex: Device for %d set to %d\n", player, cv_usejoystick[player].value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (joystickID == MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
// We DID NOT make it through the whole loop, so we can't assign this joystick to anything.
|
||||
// When you try your best, but you don't succeed...
|
||||
cv_usejoystick[player].value = 0;
|
||||
CONS_Printf("I_UpdateJoystickDeviceIndex: Device for %d set to %d\n", player, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Misleading function: updates device indices for all players BUT the one specified.
|
||||
// Necessary for SDL_JOYDEVICEADDED events
|
||||
void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer)
|
||||
{
|
||||
UINT8 player;
|
||||
|
||||
for (player = 0; player < MAXSPLITSCREENPLAYERS; player++)
|
||||
{
|
||||
if (player == excludePlayer)
|
||||
continue;
|
||||
|
||||
I_UpdateJoystickDeviceIndex(player);
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Shuts down joystick
|
||||
\return void
|
||||
*/
|
||||
void I_ShutdownJoystick(UINT8 index)
|
||||
{
|
||||
INT32 i;
|
||||
event_t event;
|
||||
|
||||
event.device = I_GetJoystickDeviceIndex(JoyInfo[index].dev);
|
||||
event.type = ev_keyup;
|
||||
event.data2 = 0;
|
||||
event.data3 = 0;
|
||||
|
||||
// emulate the up of all joystick buttons
|
||||
for (i = 0; i < JOYBUTTONS; i++)
|
||||
{
|
||||
event.data1 = KEY_JOY1+i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
// reset joystick position
|
||||
event.type = ev_joystick;
|
||||
for (i = 0; i < JOYAXES; i++)
|
||||
{
|
||||
event.data1 = i;
|
||||
D_PostEvent(&event);
|
||||
}
|
||||
|
||||
joystick_started[index] = 0;
|
||||
JoyReset(&JoyInfo[index]);
|
||||
|
||||
// don't shut down the subsystem here, because hotplugging
|
||||
}
|
||||
|
||||
/** \brief Open joystick handle
|
||||
|
||||
\param fname name of joystick
|
||||
|
||||
\return axises
|
||||
|
||||
|
||||
*/
|
||||
static int joy_open(int playerIndex, int joyIndex)
|
||||
{
|
||||
SDL_GameController *newdev = NULL;
|
||||
int num_joy = 0;
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
|
||||
{
|
||||
CONS_Printf(M_GetText("Joystick subsystem not started\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
|
||||
{
|
||||
CONS_Printf(M_GetText("Game Controller subsystem not started\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (joyIndex <= 0)
|
||||
return -1;
|
||||
|
||||
num_joy = SDL_NumJoysticks();
|
||||
|
||||
if (num_joy == 0)
|
||||
{
|
||||
CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
newdev = SDL_GameControllerOpen(joyIndex-1);
|
||||
|
||||
// Handle the edge case where the device <-> joystick index assignment can change due to hotplugging
|
||||
// This indexing is SDL's responsibility and there's not much we can do about it.
|
||||
//
|
||||
// Example:
|
||||
// 1. Plug Controller A -> Index 0 opened
|
||||
// 2. Plug Controller B -> Index 1 opened
|
||||
// 3. Unplug Controller A -> Index 0 closed, Index 1 active
|
||||
// 4. Unplug Controller B -> Index 0 inactive, Index 1 closed
|
||||
// 5. Plug Controller B -> Index 0 opened
|
||||
// 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B
|
||||
if (JoyInfo[playerIndex].dev)
|
||||
{
|
||||
if (JoyInfo[playerIndex].dev == newdev // same device, nothing to do
|
||||
|| (newdev == NULL && SDL_GameControllerGetAttached(JoyInfo[playerIndex].dev))) // we failed, but already have a working device
|
||||
{
|
||||
return SDL_CONTROLLER_AXIS_MAX;
|
||||
}
|
||||
|
||||
// Else, we're changing devices, so send neutral joy events
|
||||
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device is changing; resetting events...\n", playerIndex+1);
|
||||
I_ShutdownJoystick(playerIndex);
|
||||
}
|
||||
|
||||
JoyInfo[playerIndex].dev = newdev;
|
||||
|
||||
if (JoyInfo[playerIndex].dev == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: Couldn't open device - %s\n"), playerIndex+1, SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: %s\n"), playerIndex+1, SDL_GameControllerName(JoyInfo[playerIndex].dev));
|
||||
|
||||
JoyInfo[playerIndex].axises = SDL_CONTROLLER_AXIS_MAX;
|
||||
JoyInfo[playerIndex].buttons = SDL_CONTROLLER_BUTTON_MAX;
|
||||
JoyInfo[playerIndex].hats = 1;
|
||||
JoyInfo[playerIndex].balls = 0;
|
||||
|
||||
//JoyInfo[playerIndex].bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo[playerIndex].dev), "pad");
|
||||
|
||||
return JoyInfo[playerIndex].axises;
|
||||
}
|
||||
SDL_GameControllerSetLED(controller, red, green, blue);
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// I_InitJoystick
|
||||
// I_StartupInput
|
||||
//
|
||||
void I_InitJoystick(UINT8 index)
|
||||
void I_StartupInput(void)
|
||||
{
|
||||
SDL_GameController *newcontroller = NULL;
|
||||
UINT8 i;
|
||||
|
||||
//I_ShutdownJoystick();
|
||||
//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
|
||||
if (M_CheckParm("-nojoy"))
|
||||
return;
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (M_CheckParm("-noxinput"))
|
||||
SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
|
||||
|
||||
if (M_CheckParm("-nohidapi"))
|
||||
SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE);
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
|
||||
{
|
||||
CONS_Printf("I_InitJoystick()...\n");
|
||||
CONS_Printf("I_StartupInput()...\n");
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
|
||||
{
|
||||
CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
|
||||
{
|
||||
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1)
|
||||
{
|
||||
CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError());
|
||||
CONS_Printf(M_GetText("Couldn't initialize game controllers: %s\n"), SDL_GetError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cv_usejoystick[index].value)
|
||||
newcontroller = SDL_GameControllerOpen(cv_usejoystick[index].value-1);
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (i == index)
|
||||
continue;
|
||||
|
||||
if (JoyInfo[i].dev == newcontroller)
|
||||
break;
|
||||
}
|
||||
|
||||
if (newcontroller && i < MAXSPLITSCREENPLAYERS) // don't override an active device
|
||||
{
|
||||
cv_usejoystick[index].value = I_GetJoystickDeviceIndex(JoyInfo[index].dev) + 1;
|
||||
CONS_Printf("I_InitJoystick: Device for %d set to %d\n", index, cv_usejoystick[index].value);
|
||||
}
|
||||
else if (newcontroller && joy_open(index, cv_usejoystick[index].value) != -1)
|
||||
{
|
||||
// SDL's device indexes are unstable, so cv_usejoystick may not match
|
||||
// the actual device index. So let's cheat a bit and find the device's current index.
|
||||
JoyInfo[index].oldjoy = I_GetJoystickDeviceIndex(JoyInfo[index].dev) + 1;
|
||||
joystick_started[index] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (JoyInfo[index].oldjoy)
|
||||
I_ShutdownJoystick(index);
|
||||
cv_usejoystick[index].value = 0;
|
||||
CONS_Printf("I_InitJoystick: Device for %d set to %d\n", index, cv_usejoystick[index].value);
|
||||
joystick_started[index] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (JoyInfo[i].dev == newcontroller)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
// Joystick didn't end up being used
|
||||
I_StoreExJoystick(newcontroller);
|
||||
}
|
||||
}
|
||||
|
||||
void I_InitJoystick1(void)
|
||||
{
|
||||
I_InitJoystick(0);
|
||||
}
|
||||
|
||||
void I_InitJoystick2(void)
|
||||
{
|
||||
I_InitJoystick(1);
|
||||
}
|
||||
|
||||
void I_InitJoystick3(void)
|
||||
{
|
||||
I_InitJoystick(2);
|
||||
}
|
||||
|
||||
void I_InitJoystick4(void)
|
||||
{
|
||||
I_InitJoystick(3);
|
||||
// Upon initialization, the gamecontroller subsystem will automatically dispatch controller device added events
|
||||
// for controllers connected before initialization.
|
||||
}
|
||||
|
||||
static void I_ShutdownInput(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
// Yes, the name is misleading: these send neutral events to
|
||||
// clean up the unplugged joystick's input
|
||||
// Note these methods are internal to this file, not called elsewhere.
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
I_ShutdownJoystick(i);
|
||||
// The game code is now responsible for resetting its internal state based on ev_gamepad_device_removed events.
|
||||
// In practice, Input should never be shutdown and restarted during runtime.
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == SDL_INIT_GAMECONTROLLER)
|
||||
{
|
||||
|
|
@ -1322,14 +1037,28 @@ static char joyname[255]; // joystick name is straight from the driver
|
|||
const char *I_GetJoyName(INT32 joyindex)
|
||||
{
|
||||
const char *tempname = NULL;
|
||||
SDL_Joystick* joystick;
|
||||
joyname[0] = 0;
|
||||
joyindex--; //SDL's Joystick System starts at 0, not 1
|
||||
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
|
||||
{
|
||||
return joyname;
|
||||
}
|
||||
|
||||
// joyindex corresponds to the open joystick *instance* ID, not the joystick number
|
||||
joystick = SDL_JoystickFromInstanceID(joyindex);
|
||||
if (joystick == NULL)
|
||||
{
|
||||
return joyname;
|
||||
}
|
||||
|
||||
tempname = SDL_JoystickNameForIndex(joyindex);
|
||||
if (tempname)
|
||||
{
|
||||
strncpy(joyname, tempname, 255);
|
||||
}
|
||||
|
||||
return joyname;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
SDLforceUngrabMouse();
|
||||
}
|
||||
memset(gamekeydown, 0, sizeof(gamekeydown)); // TODO this is a scary memset
|
||||
memset(deviceResponding, false, sizeof (deviceResponding));
|
||||
G_ResetAllDeviceResponding();
|
||||
|
||||
if (MOUSE_MENU)
|
||||
{
|
||||
|
|
@ -701,7 +701,7 @@ static void Impl_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt)
|
|||
event_t event;
|
||||
INT32 value;
|
||||
|
||||
event.type = ev_joystick;
|
||||
event.type = ev_gamepad_axis;
|
||||
|
||||
event.device = 1 + evt.which;
|
||||
if (event.device == INT32_MAX)
|
||||
|
|
@ -777,6 +777,40 @@ static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint
|
|||
}
|
||||
}
|
||||
|
||||
static void Impl_HandleControllerDeviceAddedEvent(SDL_ControllerDeviceEvent event)
|
||||
{
|
||||
// The game is always interested in controller events, even if they aren't internally assigned to a player.
|
||||
// Thus, we *always* open SDL controllers as they become available, to begin receiving their events.
|
||||
|
||||
SDL_GameController* controller = SDL_GameControllerOpen(event.which);
|
||||
if (controller == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller);
|
||||
SDL_JoystickID joystick_instance_id = SDL_JoystickInstanceID(joystick);
|
||||
|
||||
event_t engine_event {};
|
||||
|
||||
engine_event.type = ev_gamepad_device_added;
|
||||
engine_event.device = 1 + joystick_instance_id;
|
||||
|
||||
D_PostEvent(&engine_event);
|
||||
}
|
||||
|
||||
static void Impl_HandleControllerDeviceRemovedEvent(SDL_ControllerDeviceEvent event)
|
||||
{
|
||||
// SDL only posts Device Removed events for controllers that have actually been opened.
|
||||
// Thus, we don't need to filter out controllers that may not have opened successfully prior to this event.
|
||||
event_t engine_event {};
|
||||
|
||||
engine_event.type = ev_gamepad_device_removed;
|
||||
engine_event.device = 1 + event.which;
|
||||
|
||||
D_PostEvent(&engine_event);
|
||||
}
|
||||
|
||||
static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
|
||||
{
|
||||
switch (keycode)
|
||||
|
|
@ -983,8 +1017,6 @@ void I_GetEvent(void)
|
|||
// otherwise we'll end up catching the warp back to center.
|
||||
//int mouseMotionOnce = 0;
|
||||
|
||||
UINT8 i;
|
||||
|
||||
if (!graphics_started)
|
||||
{
|
||||
return;
|
||||
|
|
@ -1031,147 +1063,14 @@ void I_GetEvent(void)
|
|||
Impl_HandleControllerButtonEvent(evt.cbutton, evt.type);
|
||||
break;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
{
|
||||
// OH BOY are you in for a good time! #abominationstation
|
||||
|
||||
SDL_GameController *newcontroller = SDL_GameControllerOpen(evt.cdevice.which);
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Controller device index %d added\n", evt.cdevice.which + 1);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Because SDL's device index is unstable, we're going to cheat here a bit:
|
||||
// For the first joystick setting that is NOT active:
|
||||
//
|
||||
// 1. Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg)
|
||||
//
|
||||
// 2. Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed
|
||||
// * If device doesn't exist, switch cv_usejoystick back to default value (.string)
|
||||
// * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (newcontroller && (!JoyInfo[i].dev || !SDL_GameControllerGetAttached(JoyInfo[i].dev)))
|
||||
{
|
||||
UINT8 j;
|
||||
|
||||
for (j = 0; j < MAXSPLITSCREENPLAYERS; j++)
|
||||
{
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
if (JoyInfo[j].dev == newcontroller)
|
||||
Impl_HandleControllerDeviceAddedEvent(evt.cdevice);
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
// ensures we aren't overriding a currently active device
|
||||
cv_usejoystick[i].value = evt.cdevice.which + 1;
|
||||
I_UpdateJoystickDeviceIndices(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Was cv_usejoystick disabled in settings?
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (!strcmp(cv_usejoystick[i].string, "0") || !cv_usejoystick[i].value)
|
||||
cv_usejoystick[i].value = 0;
|
||||
else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
|
||||
&& cv_usejoystick[i].value) // update the cvar ONLY if a device exists
|
||||
CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Update all joysticks' init states
|
||||
// This is a little wasteful since cv_usejoystick already calls this, but
|
||||
// we need to do this in case CV_SetValue did nothing because the string was already same.
|
||||
// if the device is already active, this should do nothing, effectively.
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
I_InitJoystick(i);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
|
||||
|
||||
#if 0
|
||||
// update the menu
|
||||
if (currentMenu == &OP_JoystickSetDef)
|
||||
M_SetupJoystickMenu(0);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (JoyInfo[i].dev == newcontroller)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAXSPLITSCREENPLAYERS)
|
||||
I_StoreExJoystick(newcontroller);
|
||||
}
|
||||
break;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (JoyInfo[i].dev && !SDL_GameControllerGetAttached(JoyInfo[i].dev))
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Joystick%d removed, device index: %d\n", i+1, JoyInfo[i].oldjoy);
|
||||
I_ShutdownJoystick(i);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Update the device indexes, because they likely changed
|
||||
// * If device doesn't exist, switch cv_usejoystick back to default value (.string)
|
||||
// * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
I_UpdateJoystickDeviceIndex(i);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Was cv_usejoystick disabled in settings?
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (!strcmp(cv_usejoystick[i].string, "0"))
|
||||
{
|
||||
cv_usejoystick[i].value = 0;
|
||||
}
|
||||
else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
|
||||
&& cv_usejoystick[i].value) // update the cvar ONLY if a device exists
|
||||
{
|
||||
CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
|
||||
|
||||
#if 0
|
||||
// update the menu
|
||||
if (currentMenu == &OP_JoystickSetDef)
|
||||
M_SetupJoystickMenu(0);
|
||||
#endif
|
||||
Impl_HandleControllerDeviceRemovedEvent(evt.cdevice);
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
LUA_HookBool(true, HOOK(GameQuit));
|
||||
I_Quit();
|
||||
|
|
@ -1195,10 +1094,7 @@ void I_GetEvent(void)
|
|||
|
||||
// In order to make wheels act like buttons, we have to set their state to Up.
|
||||
// This is because wheel messages don't have an up/down state.
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
gamekeydown[i][KEY_MOUSEWHEELDOWN] = gamekeydown[i][KEY_MOUSEWHEELUP] = 0;
|
||||
}
|
||||
G_GetDeviceGameKeyDownArray(0)[KEY_MOUSEWHEELDOWN] = G_GetDeviceGameKeyDownArray(0)[KEY_MOUSEWHEELUP] = 0;
|
||||
}
|
||||
|
||||
static void half_warp_mouse(uint16_t x, uint16_t y) {
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ extern "C" {
|
|||
#define SDL2STUB() CONS_Printf("SDL2: stubbed: %s:%d\n", __func__, __LINE__)
|
||||
#endif
|
||||
|
||||
// So m_menu knows whether to store cv_usejoystick value or string
|
||||
#define JOYSTICK_HOTPLUG
|
||||
|
||||
/** \brief The JoyInfo_s struct
|
||||
|
||||
info about joystick
|
||||
|
|
@ -65,9 +62,6 @@ typedef struct SDLJoyInfo_s
|
|||
/** \brief SDL info about controllers
|
||||
*/
|
||||
extern SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS];
|
||||
extern SDL_GameController *ExJoystick[MAXGAMEPADS];
|
||||
|
||||
void I_StoreExJoystick(SDL_GameController *dev);
|
||||
|
||||
/** \brief joystick axis deadzone
|
||||
*/
|
||||
|
|
@ -76,18 +70,6 @@ void I_StoreExJoystick(SDL_GameController *dev);
|
|||
|
||||
void I_GetConsoleEvents(void);
|
||||
|
||||
// So we can call this from i_video event loop
|
||||
void I_ShutdownJoystick(UINT8 index);
|
||||
|
||||
// Cheat to get the device index for a game controller handle
|
||||
INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev);
|
||||
|
||||
// Quick thing to make SDL_JOYDEVICEADDED events less of an abomination
|
||||
void I_UpdateJoystickDeviceIndex(UINT8 player);
|
||||
void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer);
|
||||
|
||||
void I_GetConsoleEvents(void);
|
||||
|
||||
void SDLforceUngrabMouse(void);
|
||||
|
||||
// Needed for some WIN32 functions
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue