From 92e66479fcb0849e6459311eda509341ee2d3d53 Mon Sep 17 00:00:00 2001 From: Marcus Minhorst Date: Mon, 7 Jul 2025 17:46:19 -0400 Subject: [PATCH] Added stubs and helper functions --- src/common/engine/m_joy.cpp | 68 ++++++++++-- src/common/engine/m_joy.h | 31 ++++++ .../platform/posix/cocoa/i_joystick.cpp | 44 ++++++++ src/common/platform/posix/sdl/i_joystick.cpp | 29 +++++ src/common/platform/win32/i_dijoy.cpp | 97 ++++++++++++++++- src/common/platform/win32/i_rawps2.cpp | 101 ++++++++++++++++-- src/common/platform/win32/i_xinput.cpp | 93 ++++++++++++++++ 7 files changed, 443 insertions(+), 20 deletions(-) diff --git a/src/common/engine/m_joy.cpp b/src/common/engine/m_joy.cpp index fe9e9e589..0fce7d994 100644 --- a/src/common/engine/m_joy.cpp +++ b/src/common/engine/m_joy.cpp @@ -278,6 +278,48 @@ double Joy_RemoveDeadZone(double axisval, double deadzone, uint8_t *buttons) return axisval; } +//=========================================================================== +// +// Joy_ApplyResponseCurveBezier +// +// Applies cubic bezier easing function +// Curve is defined by control points [(0,0) (x1,y1) (x2,y2) (1,1)] +// https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function/cubic-bezier +// +//=========================================================================== + +double Joy_ApplyResponseCurveBezier(const CubicBezier &curve, double input) +{ + // clamp + trivial cases + if (input == 0) return 0; + double sign = (input >= 0)? 1.0: -1.0; + input = abs(input); + input = (input > 1.0)? 1.0: input; + if (input == 1.0) return sign*input; + + double t = input, T; + float x1 = curve.x1, y1 = curve.y1, x2 = curve.x2, y2 = curve.y2; + + const int max_iter = 4; + for (auto i = 0; i < max_iter; i++) + { + T = 1-t; + + double x = 3*T*T*t*x1 + 3*T*t*t*x2 + t*t*t; + double dx = 3*T*T*x1 + 6*T*t*(x2-x1) + 3*t*t*(1-x2); + + // no div by 0 + if (abs(dx) < 0.00001) break; + + t = clamp(t - (x-input)/dx, 0.0, 1.0); + } + + T = 1-t; + t = 3*T*T*t*y1 + 3*T*t*t*y2 + t*t*t; + + return sign*t; +} + //=========================================================================== // // Joy_XYAxesToButtons @@ -315,6 +357,22 @@ int Joy_XYAxesToButtons(double x, double y) return JoyAngleButtons[int(rad) & 7]; } +//=========================================================================== +// +// Joy_GenerateButtonEvent +// +// Send either a button up or button down event for supplied key code +// +//=========================================================================== + +void Joy_GenerateButtonEvent(bool down, EKeyCodes which) +{ + event_t event = { 0,0,0,0,0,0,0 }; + event.type = down ? EV_KeyDown : EV_KeyUp; + event.data1 = which; + D_PostEvent(&event); +} + //=========================================================================== // // Joy_GenerateButtonEvents @@ -330,15 +388,12 @@ void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, in int changed = oldbuttons ^ newbuttons; if (changed != 0) { - event_t ev = { 0, 0, 0, 0, 0, 0, 0 }; int mask = 1; for (int j = 0; j < numbuttons; mask <<= 1, ++j) { if (changed & mask) { - ev.data1 = base + j; - ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp; - D_PostEvent(&ev); + Joy_GenerateButtonEvent(newbuttons & mask, static_cast(base + j)); } } } @@ -349,15 +404,12 @@ void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, co int changed = oldbuttons ^ newbuttons; if (changed != 0) { - event_t ev = { 0, 0, 0, 0, 0, 0, 0 }; int mask = 1; for (int j = 0; j < numbuttons; mask <<= 1, ++j) { if (changed & mask) { - ev.data1 = keys[j]; - ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp; - D_PostEvent(&ev); + Joy_GenerateButtonEvent(newbuttons & mask, static_cast(keys[j])); } } } diff --git a/src/common/engine/m_joy.h b/src/common/engine/m_joy.h index e8d9d3b13..60321785a 100644 --- a/src/common/engine/m_joy.h +++ b/src/common/engine/m_joy.h @@ -2,9 +2,30 @@ #define M_JOY_H #include "basics.h" +#include "keydef.h" #include "tarray.h" #include "c_cvars.h" +union CubicBezier { + struct { + float x1; + float y1; + float x2; + float y2; + }; + float pts[4]; +}; + +enum EJoyCurve { + JOYCURVE_CUSTOM = -1, + JOYCURVE_DEFAULT, + JOYCURVE_LINEAR, + JOYCURVE_QUADRATIC, + JOYCURVE_CUBIC, + + NUM_JOYCURVE +}; + enum EJoyAxis { JOYAXIS_None = -1, @@ -31,10 +52,16 @@ struct IJoystickConfig virtual EJoyAxis GetAxisMap(int axis) = 0; virtual const char *GetAxisName(int axis) = 0; virtual float GetAxisScale(int axis) = 0; + virtual float GetAxisDigitalThreshold(int axis) = 0; + virtual EJoyCurve GetAxisResponseCurve(int axis) = 0; + virtual float GetAxisResponseCurvePoint(int axis, int point) = 0; virtual void SetAxisDeadZone(int axis, float zone) = 0; virtual void SetAxisMap(int axis, EJoyAxis gameaxis) = 0; virtual void SetAxisScale(int axis, float scale) = 0; + virtual void SetAxisDigitalThreshold(int axis, float threshold) = 0; + virtual void SetAxisResponseCurve(int axis, EJoyCurve preset) = 0; + virtual void SetAxisResponseCurvePoint(int axis, int point, float value) = 0; virtual bool GetEnabled() = 0; virtual void SetEnabled(bool enabled) = 0; @@ -48,6 +75,8 @@ struct IJoystickConfig virtual bool IsAxisDeadZoneDefault(int axis) = 0; virtual bool IsAxisMapDefault(int axis) = 0; virtual bool IsAxisScaleDefault(int axis) = 0; + virtual bool IsAxisDigitalThresholdDefault(int axis) = 0; + virtual bool IsAxisResponseCurveDefault(int axis) = 0; virtual void SetDefaultConfig() = 0; virtual FString GetIdentifier() = 0; @@ -58,10 +87,12 @@ EXTERN_CVAR(Bool, use_joystick); bool M_LoadJoystickConfig(IJoystickConfig *joy); void M_SaveJoystickConfig(IJoystickConfig *joy); +void Joy_GenerateButtonEvent(bool down, EKeyCodes which); void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base); void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys); int Joy_XYAxesToButtons(double x, double y); double Joy_RemoveDeadZone(double axisval, double deadzone, uint8_t *buttons); +double Joy_ApplyResponseCurveBezier(const CubicBezier &curve, double input); // These ought to be provided by a system-specific i_input.cpp. void I_GetAxes(float axes[NUM_JOYAXIS]); diff --git a/src/common/platform/posix/cocoa/i_joystick.cpp b/src/common/platform/posix/cocoa/i_joystick.cpp index 44d1fb961..e338ad8dd 100644 --- a/src/common/platform/posix/cocoa/i_joystick.cpp +++ b/src/common/platform/posix/cocoa/i_joystick.cpp @@ -94,15 +94,23 @@ public: virtual EJoyAxis GetAxisMap(int axis); virtual const char* GetAxisName(int axis); virtual float GetAxisScale(int axis); + float GetAxisDigitalThreshold(int axis); + EJoyCurve GetAxisResponseCurve(int axis); + float GetAxisResponseCurvePoint(int axis, int point); virtual void SetAxisDeadZone(int axis, float deadZone); virtual void SetAxisMap(int axis, EJoyAxis gameAxis); virtual void SetAxisScale(int axis, float scale); + void SetAxisDigitalThreshold(int axis, float threshold); + void SetAxisResponseCurve(int axis, EJoyCurve preset); + void SetAxisResponseCurvePoint(int axis, int point, float value); virtual bool IsSensitivityDefault(); virtual bool IsAxisDeadZoneDefault(int axis); virtual bool IsAxisMapDefault(int axis); virtual bool IsAxisScaleDefault(int axis); + bool IsAxisDigitalThresholdDefault(int axis); + bool IsAxisResponseCurveDefault(int axis); virtual bool GetEnabled(); virtual void SetEnabled(bool enabled); @@ -386,6 +394,21 @@ float IOKitJoystick::GetAxisScale(int axis) return IS_AXIS_VALID ? m_axes[axis].sensitivity : 0.0f; } +float IOKitJoystick::GetAxisDigitalThreshold(int axis) +{ + return 0; +} + +EJoyCurve IOKitJoystick::GetAxisResponseCurve(int axis) +{ + return JOYCURVE_DEFAULT; +} + +float IOKitJoystick::GetAxisResponseCurvePoint(int axis, int point) +{ + return 0; +} + void IOKitJoystick::SetAxisDeadZone(int axis, float deadZone) { if (IS_AXIS_VALID) @@ -412,6 +435,17 @@ void IOKitJoystick::SetAxisScale(int axis, float scale) } } +void IOKitJoystick::SetAxisDigitalThreshold(int axis, float threshold) +{ +} + +void IOKitJoystick::SetAxisResponseCurve(int axis, EJoyCurve preset) +{ +} + +void IOKitJoystick::SetAxisResponseCurvePoint(int axis, int point, float value) +{ +} bool IOKitJoystick::IsSensitivityDefault() { @@ -425,6 +459,16 @@ bool IOKitJoystick::IsAxisDeadZoneDefault(int axis) : true; } +bool IOKitJoystick::IsAxisDigitalThresholdDefault(int axis) +{ + return true; +} + +bool IOKitJoystick::IsAxisResponseCurveDefault(int axis) +{ + return true; +} + bool IOKitJoystick::IsAxisMapDefault(int axis) { return IS_AXIS_VALID diff --git a/src/common/platform/posix/sdl/i_joystick.cpp b/src/common/platform/posix/sdl/i_joystick.cpp index b276f0fb4..6654bcae3 100644 --- a/src/common/platform/posix/sdl/i_joystick.cpp +++ b/src/common/platform/posix/sdl/i_joystick.cpp @@ -128,6 +128,18 @@ public: { return Axes[axis].Multiplier; } + float GetAxisDigitalThreshold(int axis) + { + return 0; + } + EJoyCurve GetAxisResponseCurve(int axis) + { + return JOYCURVE_DEFAULT; + } + float GetAxisResponseCurvePoint(int axis, int point) + { + return 0; + }; void SetAxisDeadZone(int axis, float zone) { @@ -141,6 +153,15 @@ public: { Axes[axis].Multiplier = scale; } + void SetAxisDigitalThreshold(int axis, float threshold) + { + } + void SetAxisResponseCurve(int axis, EJoyCurve preset) + { + } + void SetAxisResponseCurvePoint(int axis, int point, float value) + { + } // Used by the saver to not save properties that are at their defaults. bool IsSensitivityDefault() @@ -161,6 +182,14 @@ public: { return Axes[axis].Multiplier == 1.0f; } + bool IsAxisDigitalThresholdDefault(int axis) + { + return true; + } + bool IsAxisResponseCurveDefault(int axis) + { + return true; + } void SetDefaultConfig() { diff --git a/src/common/platform/win32/i_dijoy.cpp b/src/common/platform/win32/i_dijoy.cpp index 33c4574c9..d3ada1e22 100644 --- a/src/common/platform/win32/i_dijoy.cpp +++ b/src/common/platform/win32/i_dijoy.cpp @@ -170,15 +170,23 @@ public: EJoyAxis GetAxisMap(int axis); const char *GetAxisName(int axis); float GetAxisScale(int axis); + float GetAxisDigitalThreshold(int axis); + EJoyCurve GetAxisResponseCurve(int axis); + float GetAxisResponseCurvePoint(int axis, int point); void SetAxisDeadZone(int axis, float deadzone); void SetAxisMap(int axis, EJoyAxis gameaxis); void SetAxisScale(int axis, float scale); + void SetAxisDigitalThreshold(int axis, float threshold); + void SetAxisResponseCurve(int axis, EJoyCurve preset); + void SetAxisResponseCurvePoint(int axis, int point, float value); bool IsSensitivityDefault(); bool IsAxisDeadZoneDefault(int axis); bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); + bool IsAxisDigitalThresholdDefault(int axis); + bool IsAxisResponseCurveDefault(int axis); bool GetEnabled(); void SetEnabled(bool enabled); @@ -923,6 +931,39 @@ float FDInputJoystick::GetAxisScale(int axis) return Axes[axis].Multiplier; } +//=========================================================================== +// +// FDInputJoystick :: GetAxisDigitalThreshold +// +//=========================================================================== + +float FDInputJoystick::GetAxisDigitalThreshold(int axis) +{ + return 0; +} + +//=========================================================================== +// +// FDInputJoystick :: GetAxisResponseCurve +// +//=========================================================================== + +EJoyCurve FDInputJoystick::GetAxisResponseCurve(int axis) +{ + return JOYCURVE_DEFAULT; +} + +//=========================================================================== +// +// FDInputJoystick :: GetAxisResponseCurvePoint +// +//=========================================================================== + +float FDInputJoystick::GetAxisResponseCurvePoint(int axis, int point) +{ + return 0; +} + //=========================================================================== // // FDInputJoystick :: SetAxisDeadZone @@ -965,6 +1006,36 @@ void FDInputJoystick::SetAxisScale(int axis, float scale) } } +//=========================================================================== +// +// FDInputJoystick :: SetAxisDigitalThreshold +// +//=========================================================================== + +void FDInputJoystick::SetAxisDigitalThreshold(int axis, float threshold) +{ +} + +//=========================================================================== +// +// FDInputJoystick :: SetAxisResponseCurve +// +//=========================================================================== + +void FDInputJoystick::SetAxisResponseCurve(int axis, EJoyCurve preset) +{ +} + +//=========================================================================== +// +// FDInputJoystick :: SetAxisResponseCurvePoint +// +//=========================================================================== + +void FDInputJoystick::SetAxisResponseCurvePoint(int axis, int point, float value) +{ +} + //=========================================================================== // // FDInputJoystick :: IsAxisDeadZoneDefault @@ -988,10 +1059,28 @@ bool FDInputJoystick::IsAxisDeadZoneDefault(int axis) bool FDInputJoystick::IsAxisScaleDefault(int axis) { - if (unsigned(axis) < Axes.Size()) - { - return Axes[axis].Multiplier == Axes[axis].DefaultMultiplier; - } + return true; +} + +//=========================================================================== +// +// FDInputJoystick :: IsAxisDigitalThresholdDefault +// +//=========================================================================== + +bool FDInputJoystick::IsAxisDigitalThresholdDefault(int axis) +{ + return true; +} + +//=========================================================================== +// +// FDInputJoystick :: IsAxisResponseCurveDefault +// +//=========================================================================== + +bool FDInputJoystick::IsAxisResponseCurveDefault(int axis) +{ return true; } diff --git a/src/common/platform/win32/i_rawps2.cpp b/src/common/platform/win32/i_rawps2.cpp index 2f89739bd..69eea017a 100644 --- a/src/common/platform/win32/i_rawps2.cpp +++ b/src/common/platform/win32/i_rawps2.cpp @@ -104,10 +104,18 @@ public: EJoyAxis GetAxisMap(int axis); const char *GetAxisName(int axis); float GetAxisScale(int axis); + float GetAxisDigitalThreshold(int axis); + EJoyCurve GetAxisResponseCurve(int axis); + float GetAxisResponseCurvePoint(int axis, int point); void SetAxisDeadZone(int axis, float deadzone); void SetAxisMap(int axis, EJoyAxis gameaxis); void SetAxisScale(int axis, float scale); + void SetAxisDigitalThreshold(int axis, float threshold); + void SetAxisResponseCurve(int axis, EJoyCurve preset); + void SetAxisResponseCurvePoint(int axis, int point, float value); + bool IsAxisDigitalThresholdDefault(int axis); + bool IsAxisResponseCurveDefault(int axis); bool IsSensitivityDefault(); bool IsAxisDeadZoneDefault(int axis); @@ -786,6 +794,39 @@ float FRawPS2Controller::GetAxisScale(int axis) return 0; } +//========================================================================== +// +// FRawPS2Controller :: GetAxisDigitalThreshold +// +//========================================================================== + +float FRawPS2Controller::GetAxisDigitalThreshold(int axis) +{ + return 0; +} + +//========================================================================== +// +// FRawPS2Controller :: GetAxisResponseCurve +// +//========================================================================== + +EJoyCurve FRawPS2Controller::GetAxisResponseCurve(int axis) +{ + return JOYCURVE_DEFAULT; +} + +//========================================================================== +// +// FRawPS2Controller :: GetAxisResponseCurvePoint +// +//========================================================================== + +float FRawPS2Controller::GetAxisResponseCurvePoint(int axis, int point) +{ + return 0; +} + //========================================================================== // // FRawPS2Controller :: SetAxisDeadZone @@ -828,6 +869,36 @@ void FRawPS2Controller::SetAxisScale(int axis, float scale) } } +//========================================================================== +// +// FRawPS2Controller :: SetAxisDigitalThreshold +// +//========================================================================== + +void FRawPS2Controller::SetAxisDigitalThreshold(int axis, float threshold) +{ +} + +//========================================================================== +// +// FRawPS2Controller :: SetAxisResponseCurve +// +//========================================================================== + +void FRawPS2Controller::SetAxisResponseCurve(int axis, EJoyCurve preset) +{ +} + +//========================================================================== +// +// FRawPS2Controller :: SetAxisResponseCurvePoint +// +//========================================================================== + +void FRawPS2Controller::SetAxisResponseCurvePoint(int axis, int point, float value) +{ +} + //=========================================================================== // // FRawPS2Controller :: IsAxisDeadZoneDefault @@ -836,10 +907,6 @@ void FRawPS2Controller::SetAxisScale(int axis, float scale) bool FRawPS2Controller::IsAxisDeadZoneDefault(int axis) { - if (unsigned(axis) < NUM_AXES) - { - return Axes[axis].DeadZone == DEFAULT_DEADZONE; - } return true; } @@ -851,10 +918,28 @@ bool FRawPS2Controller::IsAxisDeadZoneDefault(int axis) bool FRawPS2Controller::IsAxisScaleDefault(int axis) { - if (unsigned(axis) < NUM_AXES) - { - return Axes[axis].Multiplier == DefaultAxes[axis].Multiplier; - } + return true; +} + +//=========================================================================== +// +// FRawPS2Controller :: IsAxisDigitalThresholdDefault +// +//=========================================================================== + +bool FRawPS2Controller::IsAxisDigitalThresholdDefault(int axis) +{ + return true; +} + +//=========================================================================== +// +// FRawPS2Controller :: IsAxisResponseCurveDefault +// +//=========================================================================== + +bool FRawPS2Controller::IsAxisResponseCurveDefault(int axis) +{ return true; } diff --git a/src/common/platform/win32/i_xinput.cpp b/src/common/platform/win32/i_xinput.cpp index 0f3c19237..f9cdbe2e5 100644 --- a/src/common/platform/win32/i_xinput.cpp +++ b/src/common/platform/win32/i_xinput.cpp @@ -94,15 +94,23 @@ public: EJoyAxis GetAxisMap(int axis); const char *GetAxisName(int axis); float GetAxisScale(int axis); + float GetAxisDigitalThreshold(int axis); + EJoyCurve GetAxisResponseCurve(int axis); + float GetAxisResponseCurvePoint(int axis, int point); void SetAxisDeadZone(int axis, float deadzone); void SetAxisMap(int axis, EJoyAxis gameaxis); void SetAxisScale(int axis, float scale); + void SetAxisDigitalThreshold(int axis, float threshold); + void SetAxisResponseCurve(int axis, EJoyCurve preset); + void SetAxisResponseCurvePoint(int axis, int point, float value); bool IsSensitivityDefault(); bool IsAxisDeadZoneDefault(int axis); bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); + bool IsAxisDigitalThresholdDefault(int axis); + bool IsAxisResponseCurveDefault(int axis); bool GetEnabled(); void SetEnabled(bool enabled); @@ -568,6 +576,39 @@ float FXInputController::GetAxisScale(int axis) return 0; } +//========================================================================== +// +// FXInputController :: GetAxisDigitalThreshold +// +//========================================================================== + +float FXInputController::GetAxisDigitalThreshold(int axis) +{ + return 0; +} + +//========================================================================== +// +// FXInputController :: GetAxisResponseCurve +// +//========================================================================== + +EJoyCurve FXInputController::GetAxisResponseCurve(int axis) +{ + return JOYCURVE_DEFAULT; +} + +//========================================================================== +// +// FXInputController :: GetAxisResponseCurvePoint +// +//========================================================================== + +float FXInputController::GetAxisResponseCurvePoint(int axis, int point) +{ + return 0; +} + //========================================================================== // // FXInputController :: SetAxisDeadZone @@ -610,6 +651,36 @@ void FXInputController::SetAxisScale(int axis, float scale) } } +//========================================================================== +// +// FXInputController :: SetAxisDigitalThreshold +// +//========================================================================== + +void FXInputController::SetAxisDigitalThreshold(int axis, float threshold) +{ +} + +//========================================================================== +// +// FXInputController :: SetAxisResponseCurve +// +//========================================================================== + +void FXInputController::SetAxisResponseCurve(int axis, EJoyCurve preset) +{ +} + +//========================================================================== +// +// FXInputController :: SetAxisResponseCurvePoint +// +//========================================================================== + +void FXInputController::SetAxisResponseCurvePoint(int axis, int point, float value) +{ +} + //=========================================================================== // // FXInputController :: IsAxisDeadZoneDefault @@ -640,6 +711,28 @@ bool FXInputController::IsAxisScaleDefault(int axis) return true; } +//=========================================================================== +// +// FXInputController :: IsAxisDigitalThresholdDefault +// +//=========================================================================== + +bool FXInputController::IsAxisDigitalThresholdDefault(int axis) +{ + return true; +} + +//=========================================================================== +// +// FXInputController :: IsAxisResponseCurveDefault +// +//=========================================================================== + +bool FXInputController::IsAxisResponseCurveDefault(int axis) +{ + return true; +} + //=========================================================================== // // FXInputController :: GetEnabled