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 */