diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8abfb870..16c08309 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -46,6 +46,13 @@ #include "m_cond.h" #include "m_anigif.h" +#if defined(HAVE_SDL) +#include "SDL.h" +#if SDL_VERSION_ATLEAST(2,0,0) +#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG +#endif +#endif + #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR #else @@ -243,10 +250,19 @@ consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_S consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL}; #if defined (DC) || defined (_XBOX) || defined (WMINPUT) || defined (_WII) || defined(HAVE_SDL) || defined(_WINDOWS) //joystick 1 and 2 -consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; +// JOYSTICK_HOTPLUG is set by sdlmain.h (SDL2) +// because SDL joystick indexes are unstable, and hotplugging can change a device's index. +// So let's not save any index changes to the config +consvar_t cv_usejoystick = {"use_joystick", "1", CV_CALL +#ifndef JOYSTICK_HOTPLUG + |CV_SAVE +#endif + , usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_CALL +#ifndef JOYSTICK_HOTPLUG + |CV_SAVE +#endif + , usejoystick_cons_t, I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; #elif defined (PSP) || defined (GP2X) || defined (_NDS) //only one joystick consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/m_menu.c b/src/m_menu.c index a4c62c0f..7bac5fa2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -62,6 +62,13 @@ // 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 // for snprintf int snprintf(char *str, size_t n, const char *fmt, ...); @@ -6770,12 +6777,34 @@ void M_SetupJoystickMenu(INT32 choice) strcpy(joystickInfo[i], "None"); +#ifdef JOYSTICK_HOTPLUG + if (0 == cv_usejoystick.value) + CV_SetValue(&cv_usejoystick, 0); + if (0 == cv_usejoystick2.value) + CV_SetValue(&cv_usejoystick2, 0); +#endif + for (i = 1; i < 8; i++) { if (i <= n && (I_GetJoyName(i)) != NULL) strncpy(joystickInfo[i], I_GetJoyName(i), 28); else strcpy(joystickInfo[i], joyNA); + +#ifdef JOYSTICK_HOTPLUG + // We use cv_usejoystick.string as the USER-SET var + // and cv_usejoystick.value as the INTERNAL var + // + // In practice, if cv_usejoystick.string == 0, this overrides + // cv_usejoystick.value and always disables + // + // Update cv_usejoystick.string here so that the user can + // properly change this value. + if (i == cv_usejoystick.value) + CV_SetValue(&cv_usejoystick, i); + if (i == cv_usejoystick2.value) + CV_SetValue(&cv_usejoystick2, i); +#endif } M_SetupNextMenu(&OP_JoystickSetDef); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 7cbaf6d3..e6c1b0b5 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1413,11 +1413,20 @@ void I_InitJoystick(void) // the actual device index. So let's cheat a bit and find the device's current index. JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; joystick_started = 1; + + // If another joystick occupied this device, deactivate that joystick + if (JoyInfo2.dev == JoyInfo.dev) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick2 was set to the same device; disabling...\n"); + cv_usejoystick2.value = 0; + I_InitJoystick2(); + } } else { if (JoyInfo.oldjoy) I_ShutdownJoystick(); + cv_usejoystick.value = 0; joystick_started = 0; } } @@ -1445,11 +1454,20 @@ void I_InitJoystick2(void) // the actual device index. So let's cheat a bit and find the device's current index. JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; joystick2_started = 1; + + // If another joystick occupied this device, deactivate that joystick + if (JoyInfo.dev == JoyInfo2.dev) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick1 was set to the same device; disabling...\n"); + cv_usejoystick.value = 0; + I_InitJoystick(); + } } else { if (JoyInfo2.oldjoy) I_ShutdownJoystick2(); + cv_usejoystick2.value = 0; joystick2_started = 0; } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index f6f19303..24228aa8 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -887,19 +887,21 @@ void I_GetEvent(void) // Because SDL's device index is unstable, we're going to cheat here a bit: // For the first joystick setting that is NOT active: - // Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg) - // 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! + // 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! if (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) { cv_usejoystick.value = evt.jdevice.which + 1; if (JoyInfo2.dev) cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy) + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick.value) cv_usejoystick2.value = atoi(cv_usejoystick2.string); - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy) + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) cv_usejoystick2.value = atoi(cv_usejoystick.string); else // we tried... cv_usejoystick2.value = 0; @@ -910,16 +912,31 @@ void I_GetEvent(void) if (JoyInfo.dev) cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; - else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy) + else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick2.value) cv_usejoystick.value = atoi(cv_usejoystick.string); - else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy) + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) cv_usejoystick.value = atoi(cv_usejoystick2.string); else // we tried... cv_usejoystick.value = 0; } - // If an active joystick's index has changed, these will just - // change the corresponding JoyInfo.oldjoy + // Was cv_usejoystick disabled in settings? + if (!strcmp(cv_usejoystick.string, "0") || !cv_usejoystick.value) + cv_usejoystick.value = 0; + else if (cv_usejoystick.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); + + if (!strcmp(cv_usejoystick2.string, "0") || !cv_usejoystick2.value) + cv_usejoystick2.value = 0; + else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.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. I_InitJoystick(); I_InitJoystick2(); @@ -944,8 +961,8 @@ void I_GetEvent(void) } // 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! + // * 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! if (JoyInfo.dev) cv_usejoystick.value = JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy) @@ -964,6 +981,17 @@ void I_GetEvent(void) else // we tried... cv_usejoystick2.value = 0; + // Was cv_usejoystick disabled in settings? + if (!strcmp(cv_usejoystick.string, "0")) + cv_usejoystick.value = 0; + else if (cv_usejoystick.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); + + if (!strcmp(cv_usejoystick2.string, "0")) + cv_usejoystick2.value = 0; + else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index b858e1f6..810c7dce 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -31,6 +31,9 @@ extern SDL_bool framebuffer; #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