diff --git a/src/common/platform/posix/sdl/i_input.cpp b/src/common/platform/posix/sdl/i_input.cpp index d9c05a666..da7ac59c2 100644 --- a/src/common/platform/posix/sdl/i_input.cpp +++ b/src/common/platform/posix/sdl/i_input.cpp @@ -32,13 +32,13 @@ */ #include #include +#include "i_input.h" #include "c_cvars.h" #include "dobject.h" #include "m_argv.h" #include "m_joy.h" #include "v_video.h" -#include "d_eventbase.h" #include "d_gui.h" #include "c_buttons.h" #include "c_console.h" @@ -50,10 +50,6 @@ #include "engineerrors.h" #include "i_interface.h" - -static void I_CheckGUICapture (); -static void I_CheckNativeMouse (); - bool GUICapture; static bool NativeMouse = true; @@ -529,12 +525,12 @@ void MessagePump (const SDL_Event &sev) case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: - if (SDL_IsGameController(sev.jdevice.which)) + if (SDL_GameControllerFromInstanceID(sev.jdevice.which)) break; // let SDL_CONTROLLERBUTTON* handle this event.type = sev.type == SDL_JOYBUTTONDOWN ? EV_KeyDown : EV_KeyUp; event.data1 = KEY_FIRSTJOYBUTTON + sev.jbutton.button; if(event.data1 != 0) - D_PostEvent(&event); + I_JoyConsumeEvent(sev.jdevice.which, &event); break; case SDL_CONTROLLERBUTTONDOWN: @@ -566,14 +562,22 @@ void MessagePump (const SDL_Event &sev) default: event.data1 = 0; } if(event.data1 != 0) - D_PostEvent(&event); + I_JoyConsumeEvent(sev.cbutton.which, &event); break; case SDL_JOYDEVICEADDED: - case SDL_JOYDEVICEREMOVED: case SDL_CONTROLLERDEVICEADDED: + if (sev.type == SDL_JOYDEVICEADDED && SDL_IsGameController(sev.jdevice.which)) // DeviceIndex Here + break; // skip double event + I_UpdateDeviceList(); + event.type = EV_DeviceChange; + D_PostEvent (&event); + break; + + case SDL_JOYDEVICEREMOVED: case SDL_CONTROLLERDEVICEREMOVED: - if ((sev.type == SDL_JOYDEVICEADDED || sev.type == SDL_JOYDEVICEREMOVED) && SDL_IsGameController(sev.jdevice.which)) + case SDL_CONTROLLERDEVICEREMAPPED: + if (sev.type == SDL_JOYDEVICEREMOVED && SDL_GameControllerFromInstanceID(sev.jdevice.which)) break; // skip double event I_UpdateDeviceList(); event.type = EV_DeviceChange; diff --git a/src/common/platform/posix/sdl/i_input.h b/src/common/platform/posix/sdl/i_input.h new file mode 100644 index 000000000..6ca2e05aa --- /dev/null +++ b/src/common/platform/posix/sdl/i_input.h @@ -0,0 +1,13 @@ +#ifndef I_INPUT_H +#define I_INPUT_H + +#include "d_eventbase.h" + +extern int WaitingForKey; + +static void I_CheckGUICapture (); +static void I_CheckNativeMouse (); + +void I_JoyConsumeEvent(int instanceID, event_t * event); + +#endif diff --git a/src/common/platform/posix/sdl/i_joystick.cpp b/src/common/platform/posix/sdl/i_joystick.cpp index 000562e30..d37b4f3a6 100644 --- a/src/common/platform/posix/sdl/i_joystick.cpp +++ b/src/common/platform/posix/sdl/i_joystick.cpp @@ -32,28 +32,32 @@ */ #include #include +#include #include "basics.h" #include "cmdlib.h" #include "d_eventbase.h" +#include "i_input.h" #include "m_joy.h" -#include "keydef.h" class SDLInputJoystick: public IJoystickConfig { public: SDLInputJoystick(int DeviceIndex) : DeviceIndex(DeviceIndex), - Multiplier(JOYSENSITIVITY_DEFAULT) , - Enabled(true) + InstanceID(SDL_JoystickGetDeviceInstanceID(DeviceIndex)), + Multiplier(JOYSENSITIVITY_DEFAULT), + Enabled(true), + SettingsChanged(false) { if (SDL_IsGameController(DeviceIndex)) { Mapping = SDL_GameControllerOpen(DeviceIndex); + Device = NULL; DefaultAxes = DefaultControllerAxes; - DefaultAxesCount = sizeof(DefaultControllerAxes) / sizeof(EJoyAxis); + DefaultAxesCount = sizeof(DefaultControllerAxes) / sizeof(DefaultAxisConfig); if(Mapping != NULL) { @@ -66,8 +70,10 @@ public: else { Device = SDL_JoystickOpen(DeviceIndex); + Mapping = NULL; + DefaultAxes = DefaultJoystickAxes; - DefaultAxesCount = sizeof(DefaultJoystickAxes) / sizeof(EJoyAxis); + DefaultAxesCount = sizeof(DefaultJoystickAxes) / sizeof(DefaultAxisConfig); if(Device != NULL) { @@ -77,13 +83,16 @@ public: SetDefaultConfig(); } } + M_LoadJoystickConfig(this); } ~SDLInputJoystick() { - if(Device != NULL || Mapping != NULL) + if(IsValid() && SettingsChanged) M_SaveJoystickConfig(this); - SDL_GameControllerClose(Mapping); - SDL_JoystickClose(Device); + if (Mapping) + SDL_GameControllerClose(Mapping); + if (Device) + SDL_JoystickClose(Device); } bool IsValid() const @@ -103,6 +112,7 @@ public: } void SetSensitivity(float scale) { + SettingsChanged = true; Multiplier = scale; } @@ -128,37 +138,55 @@ public: } float GetAxisDigitalThreshold(int axis) { - return 0; + return Axes[axis].DigitalThreshold; } EJoyCurve GetAxisResponseCurve(int axis) { - return JOYCURVE_DEFAULT; + return Axes[axis].ResponseCurvePreset; } float GetAxisResponseCurvePoint(int axis, int point) { - return 0; + return unsigned(point) < 4 + ? Axes[axis].ResponseCurve.pts[point] + : 0; }; void SetAxisDeadZone(int axis, float zone) { + SettingsChanged = true; Axes[axis].DeadZone = clamp(zone, 0.f, 1.f); } void SetAxisMap(int axis, EJoyAxis gameaxis) { + SettingsChanged = true; Axes[axis].GameAxis = gameaxis; } void SetAxisScale(int axis, float scale) { + SettingsChanged = true; Axes[axis].Multiplier = scale; } void SetAxisDigitalThreshold(int axis, float threshold) { + SettingsChanged = true; + Axes[axis].DigitalThreshold = threshold; } void SetAxisResponseCurve(int axis, EJoyCurve preset) { + if (preset >= NUM_JOYCURVE || preset < JOYCURVE_CUSTOM) return; + SettingsChanged = true; + Axes[axis].ResponseCurvePreset = preset; + if (preset == JOYCURVE_CUSTOM) return; + Axes[axis].ResponseCurve = JOYCURVE[preset]; } void SetAxisResponseCurvePoint(int axis, int point, float value) { + if (unsigned(point) < 4) + { + SettingsChanged = true; + Axes[axis].ResponseCurvePreset = JOYCURVE_CUSTOM; + Axes[axis].ResponseCurve.pts[point] = value; + } } // Used by the saver to not save properties that are at their defaults. @@ -168,58 +196,85 @@ public: } bool IsAxisDeadZoneDefault(int axis) { - return Axes[axis].DeadZone <= JOYDEADZONE_DEFAULT; + if(axis >= DefaultAxesCount) + return Axes[axis].DeadZone == JOYDEADZONE_DEFAULT; + return Axes[axis].DeadZone == DefaultAxes[axis].DeadZone; } bool IsAxisMapDefault(int axis) { if(axis >= DefaultAxesCount) return Axes[axis].GameAxis == JOYAXIS_None; - return Axes[axis].GameAxis == DefaultAxes[axis]; + return Axes[axis].GameAxis == DefaultAxes[axis].GameAxis; } bool IsAxisScaleDefault(int axis) { - return Axes[axis].Multiplier == JOYSENSITIVITY_DEFAULT; + if(axis >= DefaultAxesCount) + return Axes[axis].Multiplier == JOYSENSITIVITY_DEFAULT; + return Axes[axis].Multiplier == DefaultAxes[axis].Multiplier; } bool IsAxisDigitalThresholdDefault(int axis) { - return true; + if(axis >= DefaultAxesCount) + return Axes[axis].DigitalThreshold == JOYTHRESH_DEFAULT; + return Axes[axis].DigitalThreshold == DefaultAxes[axis].DigitalThreshold; } bool IsAxisResponseCurveDefault(int axis) { - return true; - } + if(axis >= DefaultAxesCount) + return Axes[axis].ResponseCurvePreset == JOYCURVE_DEFAULT; + return Axes[axis].ResponseCurvePreset == DefaultAxes[axis].ResponseCurvePreset; + } void SetDefaultConfig() { + if (Axes.size() == 0) + { + for(int i = 0;i < GetNumAxes();i++) + { + Axes.Push({}); + } + } + for(int i = 0;i < GetNumAxes();i++) { - AxisInfo info; - if (Mapping) { switch(i) { - case SDL_CONTROLLER_AXIS_LEFTX: info.Name = "Left Stick X"; break; - case SDL_CONTROLLER_AXIS_LEFTY: info.Name = "Left Stick Y"; break; - case SDL_CONTROLLER_AXIS_RIGHTX: info.Name = "Right Stick X"; break; - case SDL_CONTROLLER_AXIS_RIGHTY: info.Name = "Right Stick Y"; break; - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: info.Name = "Left Trigger"; break; - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: info.Name = "Right Trigger"; break; - default: info.Name.Format("Axis %d", i+1); break; + case SDL_CONTROLLER_AXIS_LEFTX: Axes[i].Name = "Left Stick X"; break; + case SDL_CONTROLLER_AXIS_LEFTY: Axes[i].Name = "Left Stick Y"; break; + case SDL_CONTROLLER_AXIS_RIGHTX: Axes[i].Name = "Right Stick X"; break; + case SDL_CONTROLLER_AXIS_RIGHTY: Axes[i].Name = "Right Stick Y"; break; + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: Axes[i].Name = "Left Trigger"; break; + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: Axes[i].Name = "Right Trigger"; break; + default: Axes[i].Name.Format("Axis %d", i+1); break; } } else { if(i < NumAxes) - info.Name.Format("Axis %d", i+1); + Axes[i].Name.Format("Axis %d", i+1); else - info.Name.Format("Hat %d (%c)", (i-NumAxes)/2 + 1, (i-NumAxes)%2 == 0 ? 'x' : 'y'); + Axes[i].Name.Format("Hat %d (%c)", (i-NumAxes)/2 + 1, (i-NumAxes)%2 == 0 ? 'x' : 'y'); } - info.DeadZone = JOYDEADZONE_DEFAULT; - info.Multiplier = JOYSENSITIVITY_DEFAULT; - info.Value = 0.0; - info.ButtonValue = 0; + Axes[i].Value = 0.0; + Axes[i].ButtonValue = 0; - info.GameAxis = (i < DefaultAxesCount)? DefaultAxes[i]: JOYAXIS_None; - - Axes.Push(info); + if (i < DefaultAxesCount) + { + Axes[i].GameAxis = DefaultAxes[i].GameAxis; + Axes[i].DeadZone = DefaultAxes[i].DeadZone; + Axes[i].Multiplier = DefaultAxes[i].Multiplier; + Axes[i].DigitalThreshold = DefaultAxes[i].DigitalThreshold; + Axes[i].ResponseCurvePreset = DefaultAxes[i].ResponseCurvePreset; + Axes[i].ResponseCurve = JOYCURVE[DefaultAxes[i].ResponseCurvePreset]; + } + else + { + Axes[i].GameAxis = JOYAXIS_None; + Axes[i].DeadZone = JOYDEADZONE_DEFAULT; + Axes[i].Multiplier = JOYSENSITIVITY_DEFAULT; + Axes[i].DigitalThreshold = JOYTHRESH_DEFAULT; + Axes[i].ResponseCurvePreset = JOYCURVE_DEFAULT; + Axes[i].ResponseCurve = JOYCURVE[JOYCURVE_DEFAULT]; + } } } @@ -230,6 +285,7 @@ public: void SetEnabled(bool enabled) { + SettingsChanged = true; Enabled = enabled; } @@ -254,7 +310,104 @@ public: } } - void ProcessInput(); + void ProcessInput() { + uint8_t buttonstate; + + if (Mapping) + { + // GameController API available + + auto lastTriggerL = Axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT].Value > Axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT].DigitalThreshold; + auto lastTriggerR = Axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].Value > Axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].DigitalThreshold; + + for (auto i = 0; i < SDL_CONTROLLER_AXIS_MAX && i < NumAxes; ++i) + { + buttonstate = 0; + + Axes[i].Value = SDL_GameControllerGetAxis(Mapping, static_cast(i))/32767.0; + Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); + Axes[i].Value = Joy_ApplyResponseCurveBezier(Axes[i].ResponseCurve, Axes[i].Value); + } + + auto currTriggerL = Axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT].Value > Axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT].DigitalThreshold; + auto currTriggerR = Axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].Value > Axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].DigitalThreshold; + + if (lastTriggerL != currTriggerL) Joy_GenerateButtonEvent(currTriggerL, KEY_PAD_LTRIGGER); + if (lastTriggerR != currTriggerR) Joy_GenerateButtonEvent(currTriggerR, KEY_PAD_RTRIGGER); + + // todo: right stick + buttonstate = Joy_XYAxesToButtons( + abs(Axes[0].Value) < Axes[0].DigitalThreshold ? 0 : Axes[0].Value, + abs(Axes[1].Value) < Axes[1].DigitalThreshold ? 0 : Axes[1].Value + ); + Joy_GenerateButtonEvents(Axes[0].ButtonValue, buttonstate, 4, KEY_JOYAXIS1PLUS); + Axes[0].ButtonValue = buttonstate; + } + else + { + // Joystick API fallback + + for (int i = 0; i < NumAxes; ++i) + { + buttonstate = 0; + + Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32767.0; + Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); + Axes[i].Value = Joy_ApplyResponseCurveBezier(Axes[i].ResponseCurve, Axes[i].Value); + + // Map button to axis + // X and Y are handled differently so if we have 2 or more axes then we'll use that code instead. + if (NumAxes == 1 || (i >= 2 && i < NUM_JOYAXISBUTTONS)) + { + Joy_GenerateButtonEvents(Axes[i].ButtonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); + Axes[i].ButtonValue = buttonstate; + } + } + + if(NumAxes > 1) + { + buttonstate = Joy_XYAxesToButtons( + abs(Axes[0].Value) < Axes[0].DigitalThreshold ? 0 : Axes[0].Value, + abs(Axes[1].Value) < Axes[1].DigitalThreshold ? 0 : Axes[1].Value + ); + Joy_GenerateButtonEvents(Axes[0].ButtonValue, buttonstate, 4, KEY_JOYAXIS1PLUS); + Axes[0].ButtonValue = buttonstate; + } + + // Map POV hats to buttons and axes. Why axes? Well apparently I have + // a gamepad where the left control stick is a POV hat (instead of the + // d-pad like you would expect, no that's pressure sensitive). Also + // KDE's joystick dialog maps them to axes as well. + for (int i = 0; i < NumHats; ++i) + { + AxisInfo &x = Axes[NumAxes + i*2]; + AxisInfo &y = Axes[NumAxes + i*2 + 1]; + + buttonstate = SDL_JoystickGetHat(Device, i); + + // If we're going to assume that we can pass SDL's value into + // Joy_GenerateButtonEvents then we might as well assume the format here. + if(buttonstate & 0x1) // Up + y.Value = -1.0; + else if(buttonstate & 0x4) // Down + y.Value = 1.0; + else + y.Value = 0.0; + if(buttonstate & 0x2) // Left + x.Value = 1.0; + else if(buttonstate & 0x8) // Right + x.Value = -1.0; + else + x.Value = 0.0; + + if(i < 4) + { + Joy_GenerateButtonEvents(x.ButtonValue, buttonstate, 4, KEY_JOYPOV1_UP + i*4); + x.ButtonValue = buttonstate; + } + } + } + } protected: struct AxisInfo @@ -262,16 +415,28 @@ protected: FString Name; float DeadZone; float Multiplier; + float DigitalThreshold; + EJoyCurve ResponseCurvePreset; + CubicBezier ResponseCurve; EJoyAxis GameAxis; double Value; uint8_t ButtonValue; }; - static const EJoyAxis DefaultJoystickAxes[5]; - static const EJoyAxis DefaultControllerAxes[6]; - const EJoyAxis * DefaultAxes; + struct DefaultAxisConfig + { + float DeadZone; + EJoyAxis GameAxis; + float Multiplier; + float DigitalThreshold; + EJoyCurve ResponseCurvePreset; + }; + static const DefaultAxisConfig DefaultJoystickAxes[5]; + static const DefaultAxisConfig DefaultControllerAxes[6]; + const DefaultAxisConfig * DefaultAxes; int DefaultAxesCount; int DeviceIndex; + int InstanceID; SDL_Joystick *Device; SDL_GameController *Mapping; @@ -280,24 +445,36 @@ protected: TArray Axes; int NumAxes; int NumHats; + bool SettingsChanged; friend class SDLInputJoystickManager; }; // [Nash 4 Feb 2024] seems like on Linux, the third axis is actually the Left Trigger, resulting in the player uncontrollably looking upwards. -const EJoyAxis SDLInputJoystick::DefaultJoystickAxes[5] = {JOYAXIS_Side, JOYAXIS_Forward, JOYAXIS_None, JOYAXIS_Yaw, JOYAXIS_Pitch}; - -// Defaults if we have access to the Gamepad API for this device -const EJoyAxis SDLInputJoystick::DefaultControllerAxes[6] = {JOYAXIS_Side, JOYAXIS_Forward, JOYAXIS_Yaw, JOYAXIS_Pitch, JOYAXIS_None, JOYAXIS_None}; - +const SDLInputJoystick::DefaultAxisConfig SDLInputJoystick::DefaultJoystickAxes[5] = { + {JOYDEADZONE_DEFAULT, JOYAXIS_Side, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_X, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_Forward, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_Y, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_None, JOYSENSITIVITY_DEFAULT, JOYTHRESH_DEFAULT, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_Yaw, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_X, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_Pitch, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_Y, JOYCURVE_DEFAULT} +}; +// Defaults if we have access to the GameController API for this device +const SDLInputJoystick::DefaultAxisConfig SDLInputJoystick::DefaultControllerAxes[6] = { + {JOYDEADZONE_DEFAULT, JOYAXIS_Side, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_X, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_Forward, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_Y, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_Yaw, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_X, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_Pitch, JOYSENSITIVITY_DEFAULT, JOYTHRESH_STICK_Y, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_None, JOYSENSITIVITY_DEFAULT, JOYTHRESH_TRIGGER, JOYCURVE_DEFAULT}, + {JOYDEADZONE_DEFAULT, JOYAXIS_None, JOYSENSITIVITY_DEFAULT, JOYTHRESH_TRIGGER, JOYCURVE_DEFAULT}, +}; class SDLInputJoystickManager { public: SDLInputJoystickManager() { - this->UpdateDeviceList(); + UpdateDeviceList(); } void UpdateDeviceList() @@ -334,6 +511,19 @@ public: if(Joysticks[i]->Enabled) Joysticks[i]->ProcessInput(); } + bool IsJoystickEnabled(int instanceID) + { + for(unsigned int i = 0; i < Joysticks.Size(); i++) + { + if (Joysticks[i]->InstanceID != instanceID) + { + continue; + } + return Joysticks[i]->Enabled; + } + return false; + } + protected: TDeletingArray Joysticks; }; @@ -381,103 +571,14 @@ void I_ProcessJoysticks() JoystickManager->ProcessInput(); } -void PostKeyEvent(bool down, EKeyCodes which) +void I_JoyConsumeEvent(int instanceID, event_t * event) { - event_t event = { 0,0,0,0,0,0,0 }; - event.type = down ? EV_KeyDown : EV_KeyUp; - event.data1 = which; - D_PostEvent(&event); -} - -void SDLInputJoystick::ProcessInput() { - uint8_t buttonstate; - - if (Mapping) + if (event->type == EV_KeyDown) { - // GameController API available - - auto lastTriggerL = Axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT].Value > JOYTHRESH_DEFAULT; - auto lastTriggerR = Axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].Value > JOYTHRESH_DEFAULT; - - for (auto i = 0; i < SDL_CONTROLLER_AXIS_MAX && i < NumAxes; ++i) - { - buttonstate = 0; - - Axes[i].Value = SDL_GameControllerGetAxis(Mapping, static_cast(i))/32767.0; - Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); - } - - auto currTriggerL = Axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT].Value > JOYTHRESH_DEFAULT; - auto currTriggerR = Axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT].Value > JOYTHRESH_DEFAULT; - - if (lastTriggerL != currTriggerL) PostKeyEvent(currTriggerL, KEY_PAD_LTRIGGER); - if (lastTriggerR != currTriggerR) PostKeyEvent(currTriggerR, KEY_PAD_RTRIGGER); - - buttonstate = Joy_XYAxesToButtons(Axes[0].Value, Axes[1].Value); - Joy_GenerateButtonEvents(Axes[0].ButtonValue, buttonstate, 4, KEY_JOYAXIS1PLUS); - Axes[0].ButtonValue = buttonstate; - - } - else - { - // Joystick API fallback - - for (int i = 0; i < NumAxes; ++i) - { - buttonstate = 0; - - Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32767.0; - Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); - - // Map button to axis - // X and Y are handled differently so if we have 2 or more axes then we'll use that code instead. - if (NumAxes == 1 || (i >= 2 && i < NUM_JOYAXISBUTTONS)) - { - Joy_GenerateButtonEvents(Axes[i].ButtonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); - Axes[i].ButtonValue = buttonstate; - } - } - - if(NumAxes > 1) - { - buttonstate = Joy_XYAxesToButtons(Axes[0].Value, Axes[1].Value); - Joy_GenerateButtonEvents(Axes[0].ButtonValue, buttonstate, 4, KEY_JOYAXIS1PLUS); - Axes[0].ButtonValue = buttonstate; - } - - // Map POV hats to buttons and axes. Why axes? Well apparently I have - // a gamepad where the left control stick is a POV hat (instead of the - // d-pad like you would expect, no that's pressure sensitive). Also - // KDE's joystick dialog maps them to axes as well. - for (int i = 0; i < NumHats; ++i) - { - AxisInfo &x = Axes[NumAxes + i*2]; - AxisInfo &y = Axes[NumAxes + i*2 + 1]; - - buttonstate = SDL_JoystickGetHat(Device, i); - - // If we're going to assume that we can pass SDL's value into - // Joy_GenerateButtonEvents then we might as well assume the format here. - if(buttonstate & 0x1) // Up - y.Value = -1.0; - else if(buttonstate & 0x4) // Down - y.Value = 1.0; - else - y.Value = 0.0; - if(buttonstate & 0x2) // Left - x.Value = 1.0; - else if(buttonstate & 0x8) // Right - x.Value = -1.0; - else - x.Value = 0.0; - - if(i < 4) - { - Joy_GenerateButtonEvents(x.ButtonValue, buttonstate, 4, KEY_JOYPOV1_UP + i*4); - x.ButtonValue = buttonstate; - } - } + bool okay = use_joystick && JoystickManager && JoystickManager->IsJoystickEnabled(instanceID); + if (!okay) return; } + D_PostEvent(event); } IJoystickConfig *I_UpdateDeviceList()