Added haptics settings

This commit is contained in:
Marcus Minhorst 2025-08-23 10:44:43 -04:00 committed by Rachael Alexanderson
commit a7a1d8447d
12 changed files with 363 additions and 61 deletions

View file

@ -62,6 +62,13 @@ struct {
bool dirty = false; // do we need to do something next tick ?
bool enabled = true; // do we need to do anything ever ?
bool active = true; // is the game currently not paused ?
struct {
double base = 1.0; // [0,1] -> number <1 turns down rumble strength
double high_frequency = 1.0; // [0,inf)
double low_frequency = 1.0; // [0,inf)
double left_trigger = 1.0; // [0,inf)
double right_trigger = 1.0; // [0,inf)
} strength;
struct Haptics current = {0,0,0,0,0}; // current state of the controller
TMap<FName, struct Haptics> channels; // active rumbles (that will be mixed)
} Haptics;
@ -79,6 +86,48 @@ const FName HapticIntense = "INTENSE",
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// for fine-control, if user wants/needs
// added because trigger haptics are much stronger on xbone controller than expected
CUSTOM_CVARD(Float, haptics_strength_lf, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "low frequency motor fine-control")
{
if (self < 0) self = 0;
Haptics.strength.low_frequency = self * Haptics.strength.base;
};
CUSTOM_CVARD(Float, haptics_strength_hf, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "high frequency motor fine-control")
{
if (self < 0) self = 0;
Haptics.strength.high_frequency = self * Haptics.strength.base;
};
CUSTOM_CVARD(Float, haptics_strength_lt, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "left trigger motor fine-control")
{
if (self < 0) self = 0;
Haptics.strength.left_trigger = self * Haptics.strength.base;
};
CUSTOM_CVARD(Float, haptics_strength_rt, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "right trigger motor fine-control")
{
if (self < 0) self = 0;
Haptics.strength.right_trigger = self * Haptics.strength.base;
};
CUSTOM_CVARD(Int, haptics_strength, 10, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "Translate linear haptics to audio taper")
{
double l1 = self / 10.0;
double l2 = l1 * l1;
double l3 = l2 * l1;
double m3 = 2; // cubed portion
double m2 = -2; // squared portion
double m1 = 1 - m2 - m3; // linear portion
Haptics.enabled = self > 0;
Haptics.strength.base = l1*m1 + l2*m2 + l3*m3;
Haptics.strength.high_frequency = haptics_strength_hf * Haptics.strength.base;
Haptics.strength.low_frequency = haptics_strength_lf * Haptics.strength.base;
Haptics.strength.left_trigger = haptics_strength_lt * Haptics.strength.base;
Haptics.strength.right_trigger = haptics_strength_rt * Haptics.strength.base;
if (!Haptics.enabled) I_Rumble(0, 0, 0, 0);
}
CVARD(Bool, haptics_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "print diagnostics for haptic feedback");
// CODE --------------------------------------------------------------------
@ -349,10 +398,10 @@ void Joy_Rumble(const FName source, const struct Haptics data, double attenuatio
// this will overwrite stuff from same source mapping (weapons/pistol not W_BULLET)
Haptics.channels.Insert(source, {
Haptics.tic + data.ticks + 1,
data.high_frequency * strength,
data.low_frequency * strength,
data.left_trigger * strength,
data.right_trigger * strength,
data.high_frequency * Haptics.strength.high_frequency * strength,
data.low_frequency * Haptics.strength.low_frequency * strength,
data.left_trigger * Haptics.strength.left_trigger * strength,
data.right_trigger * Haptics.strength.right_trigger * strength,
});
Haptics.dirty = true;

View file

@ -4,6 +4,7 @@
** Cross-platform joystick/gamepad management
**
**---------------------------------------------------------------------------
**
** Copyright 2005-2016 Randy Heit
** Copyright 2017-2025 GZDoom Maintainers and Contributors
** All rights reserved.
@ -30,6 +31,7 @@
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**---------------------------------------------------------------------------
**
*/
@ -172,6 +174,12 @@ bool M_LoadJoystickConfig(IJoystickConfig *joy)
joy->SetSensitivity((float)atof(value));
}
value = GameConfig->GetValueForKey("Haptics");
if (value)
{
joy->SetHapticsStrength((float)atof(value));
}
numaxes = joy->GetNumAxes();
for (int i = 0; i < numaxes; ++i)
{
@ -262,12 +270,19 @@ void M_SaveJoystickConfig(IJoystickConfig *joy)
{
GameConfig->SetValueForKey("EnabledInBackground", "1");
}
if (!joy->IsSensitivityDefault())
{
mysnprintf(value, countof(value), "%g", joy->GetSensitivity());
GameConfig->SetValueForKey("Sensitivity", value);
}
if (!joy->IsHapticsStrengthDefault())
{
mysnprintf(value, countof(value), "%g", joy->GetHapticsStrength());
GameConfig->SetValueForKey("Haptics", value);
}
numaxes = joy->GetNumAxes();
for (int i = 0; i < numaxes; ++i)
{

View file

@ -48,6 +48,10 @@ struct IJoystickConfig
virtual float GetSensitivity() = 0;
virtual void SetSensitivity(float scale) = 0;
virtual bool HasHaptics() = 0;
virtual float GetHapticsStrength() = 0;
virtual void SetHapticsStrength(float strength) = 0;
virtual int GetNumAxes() = 0;
virtual float GetAxisDeadZone(int axis) = 0;
virtual const char *GetAxisName(int axis) = 0;
@ -71,6 +75,7 @@ struct IJoystickConfig
// Used by the saver to not save properties that are at their defaults.
virtual bool IsSensitivityDefault() = 0;
virtual bool IsHapticsStrengthDefault() = 0;
virtual bool IsAxisDeadZoneDefault(int axis) = 0;
virtual bool IsAxisScaleDefault(int axis) = 0;
virtual bool IsAxisDigitalThresholdDefault(int axis) = 0;

View file

@ -4,6 +4,7 @@
** The joystick configuration menus
**
**---------------------------------------------------------------------------
**
** Copyright 2010 Christoph Oelckers
** Copyright 2017-2025 GZDoom Maintainers and Contributors
** All rights reserved.
@ -30,6 +31,7 @@
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**---------------------------------------------------------------------------
**
*/
@ -54,6 +56,26 @@ DEFINE_ACTION_FUNCTION(IJoystickConfig, SetSensitivity)
return 0;
}
DEFINE_ACTION_FUNCTION(IJoystickConfig, HasHaptics)
{
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
ACTION_RETURN_BOOL(self->HasHaptics());
}
DEFINE_ACTION_FUNCTION(IJoystickConfig, GetHapticsStrength)
{
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
ACTION_RETURN_FLOAT(self->GetHapticsStrength());
}
DEFINE_ACTION_FUNCTION(IJoystickConfig, SetHapticsStrength)
{
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);
PARAM_FLOAT(strength);
self->SetHapticsStrength((float)strength);
return 0;
}
DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisScale)
{
PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig);

View file

@ -2,6 +2,7 @@
** i_joystick.cpp
**
**---------------------------------------------------------------------------
**
** Copyright 2012-2015 Alexey Lysiuk
** Copyright 2017-2025 GZDoom Maintainers and Contributors
** All rights reserved.
@ -28,6 +29,7 @@
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**---------------------------------------------------------------------------
**
*/
@ -45,11 +47,9 @@
#include "printf.h"
#include "keydef.h"
EXTERN_CVAR(Bool, joy_axespolling)
EXTERN_CVAR(Bool, use_joystick)
namespace
{
@ -77,10 +77,8 @@ FString ToFString(const CFStringRef string)
return FString(buffer);
}
// ---------------------------------------------------------------------------
class IOKitJoystick : public IJoystickConfig
{
public:
@ -91,6 +89,10 @@ public:
virtual float GetSensitivity();
virtual void SetSensitivity(float scale);
virtual bool HasHaptics();
virtual float GetHapticsStrength();
virtual void SetHapticsStrength(float strength);
virtual int GetNumAxes();
virtual float GetAxisDeadZone(int axis);
virtual const char* GetAxisName(int axis);
@ -106,6 +108,7 @@ public:
void SetAxisResponseCurvePoint(int axis, int point, float value);
virtual bool IsSensitivityDefault();
virtual bool IsHapticsStrengthDefault();
virtual bool IsAxisDeadZoneDefault(int axis);
virtual bool IsAxisScaleDefault(int axis);
bool IsAxisDigitalThresholdDefault(int axis);
@ -206,7 +209,6 @@ private:
void RemoveFromQueue(IOHIDElementCookie cookie);
};
IOHIDDeviceInterface** CreateDeviceInterface(const io_object_t device)
{
IOCFPlugInInterface** plugInInterface = NULL;
@ -285,7 +287,6 @@ IOHIDQueueInterface** CreateDeviceQueue(IOHIDDeviceInterface** const interface)
return queue;
}
IOKitJoystick::IOKitJoystick(const io_object_t device)
: m_interface(CreateDeviceInterface(device))
, m_queue(CreateDeviceQueue(m_interface))
@ -344,13 +345,11 @@ IOKitJoystick::~IOKitJoystick()
}
}
FString IOKitJoystick::GetName()
{
return m_name;
}
float IOKitJoystick::GetSensitivity()
{
return m_sensitivity;
@ -361,6 +360,20 @@ void IOKitJoystick::SetSensitivity(float scale)
m_sensitivity = scale;
}
bool IOKitJoystick::HasHaptics()
{
return false;
}
float IOKitJoystick::GetHapticsStrength()
{
return JOYHAPSTRENGTH_DEFAULT;
}
void IOKitJoystick::SetHapticsStrength(float strength)
{
// nope
}
int IOKitJoystick::GetNumAxes()
{
@ -448,6 +461,11 @@ bool IOKitJoystick::IsSensitivityDefault()
return JOYSENSITIVITY_DEFAULT == m_sensitivity;
}
bool IOKitJoystick::IsHapticsStrengthDefault()
{
return true;
}
bool IOKitJoystick::IsAxisDeadZoneDefault(int axis)
{
return IS_AXIS_VALID
@ -548,13 +566,11 @@ void IOKitJoystick::SetDefaultConfig()
}
}
FString IOKitJoystick::GetIdentifier()
{
return m_identifier;
}
void IOKitJoystick::AddAxes(float axes[NUM_AXIS_CODES]) const
{
for (size_t i = 0, count = m_axes.Size(); i < count; ++i)
@ -582,7 +598,6 @@ void IOKitJoystick::AddAxes(float axes[NUM_AXIS_CODES]) const
}
}
void IOKitJoystick::UseAxesPolling(const bool axesPolling)
{
m_useAxesPolling = axesPolling;
@ -602,7 +617,6 @@ void IOKitJoystick::UseAxesPolling(const bool axesPolling)
}
}
void IOKitJoystick::Update()
{
if (NULL == m_queue)
@ -630,7 +644,6 @@ void IOKitJoystick::Update()
if(m_enabled) ProcessAxes();
}
void IOKitJoystick::ProcessAxes()
{
if (NULL == m_interface || !m_useAxesPolling)
@ -717,7 +730,6 @@ void IOKitJoystick::ProcessAxes()
}
}
bool IOKitJoystick::ProcessAxis(const IOHIDEventStruct& event)
{
if (m_useAxesPolling)
@ -809,7 +821,6 @@ bool IOKitJoystick::ProcessPOV(const IOHIDEventStruct& event)
return false;
}
void IOKitJoystick::GatherDeviceInfo(const io_object_t device, const CFDictionaryRef properties)
{
assert(NULL != properties);
@ -914,7 +925,6 @@ void IOKitJoystick::GatherDeviceInfo(const io_object_t device, const CFDictionar
}
}
long GetElementValue(const CFDictionaryRef element, const CFStringRef key)
{
const CFNumberRef number =
@ -991,7 +1001,6 @@ void IOKitJoystick::GatherCollectionElements(const CFDictionaryRef properties)
CFArrayApplyFunction(topElement, range, GatherElementsHandler, this);
}
IOHIDElementCookie GetElementCookie(const CFDictionaryRef element)
{
// Use C-style cast to avoid 32/64-bit IOHIDElementCookie type issue
@ -1039,7 +1048,6 @@ void IOKitJoystick::AddPOV(CFDictionaryRef element)
AddToQueue(pov.cookie);
}
void IOKitJoystick::AddToQueue(const IOHIDElementCookie cookie)
{
if (NULL == m_queue)
@ -1066,16 +1074,13 @@ void IOKitJoystick::RemoveFromQueue(const IOHIDElementCookie cookie)
}
}
io_object_t* IOKitJoystick::GetNotificationPtr()
{
return &m_notification;
}
// ---------------------------------------------------------------------------
class IOKitJoystickManager
{
public:
@ -1109,10 +1114,8 @@ private:
natural_t messageType, void* messageArgument);
};
IOKitJoystickManager* s_joystickManager;
IOKitJoystickManager::IOKitJoystickManager()
{
memset(m_notifications, 0, sizeof m_notifications);
@ -1160,7 +1163,6 @@ IOKitJoystickManager::~IOKitJoystickManager()
}
}
void IOKitJoystickManager::GetJoysticks(TArray<IJoystickConfig*>& joysticks) const
{
const size_t joystickCount = m_joysticks.Size();
@ -1183,7 +1185,6 @@ void IOKitJoystickManager::AddAxes(float axes[NUM_AXIS_CODES]) const
}
}
void IOKitJoystickManager::Update()
{
for (size_t i = 0, count = m_joysticks.Size(); i < count; ++i)
@ -1192,7 +1193,6 @@ void IOKitJoystickManager::Update()
}
}
void IOKitJoystickManager::UseAxesPolling(const bool axesPolling)
{
for (size_t i = 0, count = m_joysticks.Size(); i < count; ++i)
@ -1201,14 +1201,12 @@ void IOKitJoystickManager::UseAxesPolling(const bool axesPolling)
}
}
void PostDeviceChangeEvent()
{
event_t event = { EV_DeviceChange };
D_PostEvent(&event);
}
void IOKitJoystickManager::Rescan(const int usagePage, const int usage, const size_t notificationPortIndex)
{
CFMutableDictionaryRef deviceMatching = IOServiceMatching(kIOHIDDeviceKey);
@ -1270,7 +1268,6 @@ void IOKitJoystickManager::AddDevices(const IONotificationPortRef notificationPo
}
}
void IOKitJoystickManager::OnDeviceAttached(void* const refcon, const io_iterator_t iterator)
{
assert(NULL != refcon);
@ -1309,10 +1306,8 @@ void IOKitJoystickManager::OnDeviceRemoved(void* const refcon, io_service_t, con
} // unnamed namespace
// ---------------------------------------------------------------------------
void I_ShutdownInput()
{
delete s_joystickManager;
@ -1358,10 +1353,8 @@ IJoystickConfig* I_UpdateDeviceList()
return NULL;
}
// ---------------------------------------------------------------------------
void I_ProcessJoysticks()
{
if (NULL != s_joystickManager)
@ -1370,10 +1363,8 @@ void I_ProcessJoysticks()
}
}
// ---------------------------------------------------------------------------
CUSTOM_CVAR(Bool, joy_axespolling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (NULL != s_joystickManager)
@ -1388,3 +1379,4 @@ void I_Rumble(double high_freq, double low_freq, double left_trig, double right_
// stub
}

View file

@ -4,6 +4,7 @@
** Handles sdl joysticks and gamepads
**
**---------------------------------------------------------------------------
**
** Copyright 2005-2016 Randy Heit
** Copyright 2017-2025 GZDoom Maintainers and Contributors
** All rights reserved.
@ -30,6 +31,7 @@
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**---------------------------------------------------------------------------
**
*/
@ -138,6 +140,25 @@ public:
Multiplier = scale;
}
bool HasHaptics()
{
return Haptics != 0;
}
float GetHapticsStrength()
{
return HasHaptics()
? HapticsStrength
: 0;
}
void SetHapticsStrength(float strength)
{
if (!HasHaptics()) return;
SettingsChanged = true;
HapticsStrength = clamp(strength, 0.f, 2.f);
}
int GetNumAxes()
{
return NumAxes + NumHats*2;
@ -207,6 +228,10 @@ public:
{
return Multiplier == JOYSENSITIVITY_DEFAULT;
}
bool IsHapticsStrengthDefault()
{
return HapticsStrength == JOYHAPSTRENGTH_DEFAULT;
}
bool IsAxisDeadZoneDefault(int axis)
{
if(axis >= DefaultAxesCount)

View file

@ -4,6 +4,7 @@
** Handles direct input joysticks
**
**---------------------------------------------------------------------------
**
** Copyright 2005-2016 Randy Heit
** Copyright 2017-2025 GZDoom Maintainers and Contributors
** All rights reserved.
@ -30,12 +31,14 @@
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include "m_joy.h"
#define WIN32_LEAN_AND_MEAN
#define DIRECTINPUT_VERSION 0x800
#include <windows.h>
@ -166,6 +169,10 @@ public:
float GetSensitivity();
virtual void SetSensitivity(float scale);
bool HasHaptics();
float GetHapticsStrength();
void SetHapticsStrength(float strength);
int GetNumAxes();
float GetAxisDeadZone(int axis);
const char *GetAxisName(int axis);
@ -181,6 +188,7 @@ public:
void SetAxisResponseCurvePoint(int axis, int point, float value);
bool IsSensitivityDefault();
bool IsHapticsStrengthDefault();
bool IsAxisDeadZoneDefault(int axis);
bool IsAxisScaleDefault(int axis);
bool IsAxisDigitalThresholdDefault(int axis);
@ -913,6 +921,50 @@ bool FDInputJoystick::IsSensitivityDefault()
return Multiplier == JOYSENSITIVITY_DEFAULT;
}
//===========================================================================
//
// FDInputJoystick :: HasHaptics
//
//===========================================================================
bool FDInputJoystick::HasHaptics()
{
return false;
}
//===========================================================================
//
// FDInputJoystick :: GetHapticsStrength
//
//===========================================================================
float FDInputJoystick::GetHapticsStrength()
{
return JOYHAPSTRENGTH_DEFAULT;
}
//===========================================================================
//
// FDInputJoystick :: SetHapticsStrength
//
//===========================================================================
void FDInputJoystick::SetHapticsStrength(float strength)
{
// nope
}
//===========================================================================
//
// FDInputJoystick :: IsHapticsStrengthDefault
//
//===========================================================================
bool FDInputJoystick::IsHapticsStrengthDefault()
{
return true;
}
//===========================================================================
//
// FDInputJoystick :: GetNumAxes

View file

@ -2,6 +2,7 @@
**
**
**---------------------------------------------------------------------------
**
** Copyright 2005-2016 Randy Heit
** All rights reserved.
**
@ -27,6 +28,7 @@
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**---------------------------------------------------------------------------
**
*/
@ -98,6 +100,10 @@ public:
float GetSensitivity();
virtual void SetSensitivity(float scale);
bool HasHaptics();
float GetHapticsStrength();
void SetHapticsStrength(float strength);
int GetNumAxes();
float GetAxisDeadZone(int axis);
const char *GetAxisName(int axis);
@ -113,6 +119,7 @@ public:
void SetAxisResponseCurvePoint(int axis, int point, float value);
bool IsSensitivityDefault();
bool IsHapticsStrengthDefault();
bool IsAxisDeadZoneDefault(int axis);
bool IsAxisScaleDefault(int axis);
bool IsAxisDigitalThresholdDefault(int axis);
@ -750,6 +757,50 @@ bool FRawPS2Controller::IsSensitivityDefault()
return Multiplier == JOYSENSITIVITY_DEFAULT;
}
//===========================================================================
//
// FRawPS2Controller :: HasHaptics
//
//===========================================================================
bool FRawPS2Controller::HasHaptics()
{
return false;
}
//===========================================================================
//
// FRawPS2Controller :: GetHapticsStrength
//
//===========================================================================
float FRawPS2Controller::GetHapticsStrength()
{
return JOYHAPSTRENGTH_DEFAULT;
}
//===========================================================================
//
// FRawPS2Controller :: SetHapticsStrength
//
//===========================================================================
void FRawPS2Controller::SetHapticsStrength(float strength)
{
// nope
}
//===========================================================================
//
// FRawPS2Controller :: IsHapticsStrengthDefault
//
//===========================================================================
bool FRawPS2Controller::IsHapticsStrengthDefault()
{
return true;
}
//==========================================================================
//
// FRawPS2Controller :: GetNumAxes

View file

@ -4,6 +4,7 @@
** Handles direct input gamepads
**
**---------------------------------------------------------------------------
**
** Copyright 2005-2016 Randy Heit
** Copyright 2017-2025 GZDoom Maintainers and Contributors
** All rights reserved.
@ -30,6 +31,7 @@
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**---------------------------------------------------------------------------
**
*/
@ -95,6 +97,10 @@ public:
float GetSensitivity();
virtual void SetSensitivity(float scale);
bool HasHaptics();
float GetHapticsStrength();
void SetHapticsStrength(float strength);
int GetNumAxes();
float GetAxisDeadZone(int axis);
const char *GetAxisName(int axis);
@ -110,6 +116,7 @@ public:
void SetAxisResponseCurvePoint(int axis, int point, float value);
bool IsSensitivityDefault();
bool IsHapticsStrengthDefault();
bool IsAxisDeadZoneDefault(int axis);
bool IsAxisScaleDefault(int axis);
bool IsAxisDigitalThresholdDefault(int axis);
@ -575,6 +582,50 @@ bool FXInputController::IsSensitivityDefault()
return Multiplier == JOYSENSITIVITY_DEFAULT;
}
//==========================================================================
//
// FXInputController :: HasHaptics
//
//==========================================================================
bool FXInputController::HasHaptics()
{
return Haptics;
}
//==========================================================================
//
// FXInputController :: GetHapticsStrength
//
//==========================================================================
float FXInputController::GetHapticsStrength()
{
return HapticStrength;
}
//==========================================================================
//
// FXInputController :: SetHapticsStrength
//
//==========================================================================
void FXInputController::SetHapticsStrength(float strength)
{
if (Haptics) HapticStrength = clamp(strength, 0.f, 2.f);
}
//==========================================================================
//
// FXInputController :: IsHapticsStrengthDefault
//
//==========================================================================
bool FXInputController::IsHapticsStrengthDefault()
{
return true;
}
//==========================================================================
//
// FXInputController :: GetNumAxes