From 0a98ca63ab3b683ada113454e7742c1c3af67aea Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 6 Dec 2021 17:43:52 -0500 Subject: [PATCH] First pass on character select device select Ultra mega hacked in, by saving all "discarded" joysticks to an array so they don't get totally closed & we can still poll them. Events now properly send the device number instead of the player number, which means we can store all controllers pressing buttons, and thus, can detect when ANY controller is pressing anything, and THUS we can make the character select work like we wanted to :V Did not bother fixing any of the bugs, however. First of all, the opening menus do not properly fallback to default controls. Yet again, we may need a more robust system -- storing all keys from gamekeydown separately? Additionally it seems like when I input gamepad it makes me use keyboard anyway, so I think something fishy is up. (G: finally, a commit that mostly survived... deviceResponding is useless for us right now but might as well keep it. maybe easier assignment on the multiplayer setup menu in the future?) --- src/d_clisrv.c | 2 ++ src/d_main.cpp | 2 ++ src/d_netcmd.c | 10 ++++---- src/doomdef.h | 1 + src/g_game.c | 1 + src/g_input.c | 60 +++++++++++++++++++++++++++++++++----------- src/g_input.h | 3 +++ src/sdl/i_system.cpp | 47 ++++++++++++++++++++++++++++++++-- src/sdl/i_video.cpp | 56 ++++++++--------------------------------- src/sdl/sdlmain.h | 3 +++ 10 files changed, 118 insertions(+), 67 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d67c833ba..722270930 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1941,6 +1941,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic renderdeltatics = FRACUNIT; rendertimefrac = FRACUNIT; + memset(deviceResponding, false, sizeof (deviceResponding)); + if (cl_mode == CL_CONFIRMCONNECT) { D_ProcessEvents(); //needed for menu system to receive inputs diff --git a/src/d_main.cpp b/src/d_main.cpp index d3a3a3662..100c30100 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -187,6 +187,7 @@ void D_ProcessEvents(void) boolean eaten; + memset(deviceResponding, false, sizeof (deviceResponding)); for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { ev = &events[eventtail]; @@ -1047,6 +1048,7 @@ void D_StartTitle(void) // clear cmd building stuff memset(gamekeydown, 0, sizeof(gamekeydown)); + memset(deviceResponding, false, sizeof (deviceResponding)); F_StartTitleScreen(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 95b408565..dea647a00 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -244,7 +244,7 @@ static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"}, {4, "/dev/js3"}, {0, NULL}}; #else // accept whatever value - it is in fact the joystick device number -#define usejoystick_cons_t NULL +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}}; @@ -329,10 +329,10 @@ consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "Off", CV_SAVE|CV_CALL,usemouse_ consvar_t cv_laglesscam = CVAR_INIT ("laglesscamera", "Off", CV_SAVE,CV_OnOff, NULL); consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS] = { - CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick1), - CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2), - CVAR_INIT ("use_joystick3", "3", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick3), - CVAR_INIT ("use_joystick4", "4", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick4) + 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)) diff --git a/src/doomdef.h b/src/doomdef.h index 5088491d4..34d131872 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -202,6 +202,7 @@ extern char logfilename[1024]; #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 #define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer +#define MAXGAMEPADS (MAXSPLITSCREENPLAYERS * 2) // Number of gamepads we'll be allowing #define MAXSKINS UINT8_MAX #define MAXFOLLOWERS UINT16_MAX diff --git a/src/g_game.c b/src/g_game.c index 233957cd3..53cc4c967 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1369,6 +1369,7 @@ void G_DoLoadLevel(boolean resetplayer) // clear cmd building stuff memset(gamekeydown, 0, sizeof (gamekeydown)); + memset(deviceResponding, false, sizeof (deviceResponding)); // clear hud messages remains (usually from game startup) CON_ClearHUD(); diff --git a/src/g_input.c b/src/g_input.c index d87e0450f..24c9c8b39 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -37,6 +37,7 @@ consvar_t cv_turnsmooth = CVAR_INIT ("turnsmoothing", "Slow", CV_SAVE, turnsmoot // current state of the keys // JOYAXISRANGE for fully pressed, 0 for not pressed INT32 gamekeydown[MAXSPLITSCREENPLAYERS][NUMINPUTS]; +boolean deviceResponding[MAXDEVICES]; // two key codes (or virtual key) per game control INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING]; @@ -75,13 +76,44 @@ const INT32 gcl_full[num_gcl_full] = { void G_MapEventsToControls(event_t *ev) { INT32 i; + INT32 devicePlayer = INT32_MAX; + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (ev->device == cv_usejoystick[i].value) + { + devicePlayer = i; + break; + } + } + + if (ev->device >= 0 && ev->device <= MAXGAMEPADS) + { + switch (ev->type) + { + case ev_keydown: + //case ev_keyup: + //case ev_mouse: + //case ev_joystick: + deviceResponding[ev->device] = true; + break; + + default: + break; + } + } + + if (devicePlayer == INT32_MAX) + { + return; + } switch (ev->type) { case ev_keydown: if (ev->data1 < NUMINPUTS) { - gamekeydown[ev->device][ev->data1] = JOYAXISRANGE; + gamekeydown[devicePlayer][ev->data1] = JOYAXISRANGE; } #ifdef PARANOIA else @@ -94,7 +126,7 @@ void G_MapEventsToControls(event_t *ev) case ev_keyup: if (ev->data1 < NUMINPUTS) { - gamekeydown[ev->device][ev->data1] = 0; + gamekeydown[devicePlayer][ev->data1] = 0; } #ifdef PARANOIA else @@ -114,28 +146,28 @@ 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; + gamekeydown[devicePlayer][KEY_MOUSEMOVE + 2] = abs(ev->data2); + gamekeydown[devicePlayer][KEY_MOUSEMOVE + 3] = 0; } else { // Right - gamekeydown[ev->device][KEY_MOUSEMOVE + 2] = 0; - gamekeydown[ev->device][KEY_MOUSEMOVE + 3] = abs(ev->data2); + gamekeydown[devicePlayer][KEY_MOUSEMOVE + 2] = 0; + gamekeydown[devicePlayer][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; + gamekeydown[devicePlayer][KEY_MOUSEMOVE] = abs(ev->data3); + gamekeydown[devicePlayer][KEY_MOUSEMOVE + 1] = 0; } else { // Down - gamekeydown[ev->device][KEY_MOUSEMOVE] = 0; - gamekeydown[ev->device][KEY_MOUSEMOVE + 1] = abs(ev->data3); + gamekeydown[devicePlayer][KEY_MOUSEMOVE] = 0; + gamekeydown[devicePlayer][KEY_MOUSEMOVE + 1] = abs(ev->data3); } break; @@ -164,14 +196,14 @@ void G_MapEventsToControls(event_t *ev) if (ev->data2 < 0) { // Left - gamekeydown[ev->device][KEY_AXIS1 + i] = abs(ev->data2); - gamekeydown[ev->device][KEY_AXIS1 + i + 1] = 0; + gamekeydown[devicePlayer][KEY_AXIS1 + i] = abs(ev->data2); + gamekeydown[devicePlayer][KEY_AXIS1 + i + 1] = 0; } else { // Right - gamekeydown[ev->device][KEY_AXIS1 + i] = 0; - gamekeydown[ev->device][KEY_AXIS1 + i + 1] = abs(ev->data2); + gamekeydown[devicePlayer][KEY_AXIS1 + i] = 0; + gamekeydown[devicePlayer][KEY_AXIS1 + i + 1] = abs(ev->data2); } break; diff --git a/src/g_input.h b/src/g_input.h index 4b3c4dc25..500b27268 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -92,6 +92,9 @@ extern consvar_t cv_controlperkey, cv_turnsmooth; // Or anything inbetween for analog values extern INT32 gamekeydown[MAXSPLITSCREENPLAYERS][NUMINPUTS]; +#define MAXDEVICES (MAXGAMEPADS + 1) // Gamepads + keyboard & mouse +extern boolean deviceResponding[MAXDEVICES]; + // several key codes (or virtual key) per game control extern INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING]; extern INT32 gamecontroldefault[num_gamecontrols][MAXINPUTMAPPING]; // default control storage diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index fa7a750a7..f93a02300 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -203,6 +203,48 @@ static char returnWadPath[256]; static std::thread::id g_main_thread_id; +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 @@ -213,7 +255,7 @@ static void JoyReset(SDLJoyInfo_t *JoySet) { if (JoySet->dev) { - SDL_GameControllerClose(JoySet->dev); + I_StoreExJoystick(JoySet->dev); } JoySet->dev = NULL; JoySet->oldjoy = -1; @@ -228,6 +270,7 @@ 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; @@ -1479,7 +1522,7 @@ void I_InitJoystick(UINT8 index) if (i == MAXSPLITSCREENPLAYERS) { // Joystick didn't end up being used - SDL_GameControllerClose(newcontroller); + I_StoreExJoystick(newcontroller); } } diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index 8d44070d6..c0a2fdeeb 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -642,6 +642,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)); if (MOUSE_MENU) { @@ -655,7 +656,7 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type) { event_t event; - event.device = 0; // TODO: properly set a device + event.device = 0; if (type == SDL_KEYUP) { @@ -738,7 +739,7 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type) /// \todo inputEvent.button.which if (USE_MOUSEINPUT) { - event.device = 0; // TODO: properly set a device + event.device = 0; if (type == SDL_MOUSEBUTTONUP) { @@ -772,7 +773,7 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt) SDL_memset(&event, 0, sizeof(event_t)); - event.device = 0; // TODO: properly set a device + event.device = 0; if (evt.y > 0) { @@ -798,23 +799,12 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt) static void Impl_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt) { event_t event; - SDL_JoystickID joyid[MAXSPLITSCREENPLAYERS]; - UINT8 i; - event.device = INT32_MAX; - event.data1 = event.data2 = event.data3 = INT32_MAX; event.type = ev_joystick; - // Determine the Joystick IDs for each current open joystick - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - joyid[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo[i].dev)); + event.data1 = event.data2 = event.data3 = INT32_MAX; - if (evt.which == joyid[i]) - { - event.device = i; - } - } + event.device = 1 + evt.which; if (event.device == INT32_MAX) { @@ -857,20 +847,8 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt) { event_t event; SDL_JoystickID joyid[MAXSPLITSCREENPLAYERS]; - UINT8 i; - event.device = INT32_MAX; - - // Determine the Joystick IDs for each current open joystick - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - joyid[i] = SDL_JoystickInstanceID(JoyInfo[i].dev); - - if (evt.which == joyid[i]) - { - event.device = i; - } - } + event.device = 1 + evt.which; if (event.device == INT32_MAX) { @@ -891,23 +869,11 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt) static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type) { event_t event; - SDL_JoystickID joyid[MAXSPLITSCREENPLAYERS]; - UINT8 i; - event.device = INT32_MAX; + event.device = 1 + evt.which; + event.data1 = event.data2 = event.data3 = INT32_MAX; - // Determine the Joystick IDs for each current open joystick - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - joyid[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo[i].dev)); - - if (evt.which == joyid[i]) - { - event.device = i; - } - } - if (evt.button == SDL_CONTROLLER_BUTTON_DPAD_UP || evt.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN || evt.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT @@ -952,8 +918,6 @@ static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint } } - - void I_GetEvent(void) { SDL_Event evt; @@ -1093,7 +1057,7 @@ void I_GetEvent(void) } if (i == MAXSPLITSCREENPLAYERS) - SDL_GameControllerClose(newcontroller); + I_StoreExJoystick(newcontroller); } break; diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 8502eb788..8fd360248 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -65,6 +65,9 @@ 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 */