Added stubs and helper functions

This commit is contained in:
Marcus Minhorst 2025-07-07 17:46:19 -04:00 committed by Ricardo Luís Vaz Silva
commit 92e66479fc
7 changed files with 443 additions and 20 deletions

View file

@ -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<EKeyCodes>(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<EKeyCodes>(keys[j]));
}
}
}

View file

@ -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]);

View file

@ -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

View file

@ -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()
{

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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