Tilt: Add back inverse deadzone (low end radius). Allow choosing circular or per-axis.

This commit is contained in:
Henrik Rydgård 2023-05-22 10:13:57 +02:00
parent d5dfef8a8a
commit 2ceb9942f3
4 changed files with 29 additions and 1 deletions

View File

@ -681,6 +681,7 @@ static const ConfigSetting controlSettings[] = {
ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 60, CfgFlag::PER_GAME),
ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 60, CfgFlag::PER_GAME),
ConfigSetting("TiltAnalogDeadzoneRadius", &g_Config.fTiltAnalogDeadzoneRadius, 0.0f, CfgFlag::PER_GAME),
ConfigSetting("TiltInverseDeadzone", &g_Config.fTiltInverseDeadzone, 0.0f, CfgFlag::PER_GAME),
ConfigSetting("TiltInputType", &g_Config.iTiltInputType, 0, CfgFlag::PER_GAME),
#endif

View File

@ -279,6 +279,8 @@ public:
int iTiltSensitivityY;
// The deadzone radius of the tilt. Only used in the analog mapping.
float fTiltAnalogDeadzoneRadius;
float fTiltInverseDeadzone; // An inverse deadzone for the output, counteracting excessive deadzones applied by games. See #17483.
bool bTiltCircularInverseDeadzone;
// Type of tilt input currently selected: Defined in TiltEventProcessor.h
// 0 - no tilt, 1 - analog stick, 2 - D-Pad, 3 - Action Buttons (Tri, Cross, Square, Circle)
int iTiltInputType;

View File

@ -40,6 +40,24 @@ inline float ApplyDeadzone(float x, float deadzone) {
}
}
// Also clamps to -1.0..1.0.
// This applies a (circular if desired) inverse deadzone.
inline void ApplyInverseDeadzone(float x, float y, float *outX, float *outY, float inverseDeadzone, bool circular) {
if (inverseDeadzone == 0.0f) {
*outX = Clamp(x, -1.0f, 1.0f);
*outY = Clamp(y, -1.0f, 1.0f);
}
if (circular) {
float magnitude = sqrtf(x * x + y * y);
magnitude = (magnitude + inverseDeadzone) / magnitude;
*outX = Clamp(x * magnitude, -1.0f, 1.0f);
*outY = Clamp(y * magnitude, -1.0f, 1.0f);
} else {
*outX = Clamp(x + copysignf(inverseDeadzone, x), -1.0f, 1.0f);
*outY = Clamp(y + copysignf(inverseDeadzone, y), -1.0f, 1.0f);
}
}
void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity) {
if (g_Config.iTiltInputType == TILT_NULL) {
// Turned off - nothing to do.
@ -79,9 +97,14 @@ void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float
if (g_Config.iTiltInputType == TILT_ANALOG) {
// Only analog mappings use the deadzone.
float adjustedTiltX = ApplyDeadzone(tiltX, g_Config.fTiltAnalogDeadzoneRadius);
float adjustedTiltY = ApplyDeadzone(tiltY, g_Config.fTiltAnalogDeadzoneRadius);
// Unlike regular deadzone, where per-axis is okay, inverse deadzone (to compensate for game deadzones) really needs to be
// applied on the two axes together.
// TODO: Share this code with the joystick code. For now though, we keep it separate.
ApplyInverseDeadzone(adjustedTiltX, adjustedTiltY, &adjustedTiltX, &adjustedTiltY, g_Config.fTiltInverseDeadzone, g_Config.bTiltCircularInverseDeadzone);
rawTiltAnalogX = adjustedTiltX;
rawTiltAnalogY = adjustedTiltY;
GenerateAnalogStickEvent(adjustedTiltX, adjustedTiltY);

View File

@ -123,6 +123,8 @@ void TiltAnalogSettingsScreen::CreateViews() {
settings->Add(new ItemHeader(co->T("Sensitivity")));
if (g_Config.iTiltInputType == 1) {
settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltAnalogDeadzoneRadius, 0.0f, 0.8f, 0.0f, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc);
settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltInverseDeadzone, 0.0f, 0.8f, 0.0f, co->T("Low end radius"), 0.0f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc);
settings->Add(new CheckBox(&g_Config.bTiltCircularInverseDeadzone, co->T("Circular low end radius")))->SetEnabledFunc(enabledFunc);
}
settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, 60, co->T("Tilt Sensitivity along X axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc);
settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, 60, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc);