mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-11 22:49:56 +00:00
Pad: Add option to correct diagonal scale on analog sticks.
Adds a new option to scale analog stick diagonal inputs, correcting for the drop off caused by modern controllers having a square pickup zone as opposed to the DS2 which was round and could sustain full input on diagonals. A possibly cleaner alternative to axis scaling, so full input can still be achieved on diagonals without having to crank axis scaling and causing cardinal directions to max out noticeably before hitting the actual edge of the stick housing.
This commit is contained in:
@@ -123,8 +123,10 @@ void Pad::LoadConfig(const SettingsInterface& si)
|
||||
|
||||
const float axis_deadzone = si.GetFloatValue(section.c_str(), "Deadzone", Pad::DEFAULT_STICK_DEADZONE);
|
||||
const float axis_scale = si.GetFloatValue(section.c_str(), "AxisScale", Pad::DEFAULT_STICK_SCALE);
|
||||
const bool use_diagonal_scale_correction = si.GetBoolValue(section.c_str(), "UseDiagonalScaleCorrection", Pad::DEFAULT_USE_DIAGONAL_SCALE_CORRECTION);
|
||||
const float button_deadzone = si.GetFloatValue(section.c_str(), "ButtonDeadzone", Pad::DEFAULT_BUTTON_DEADZONE);
|
||||
pad->SetAxisScale(axis_deadzone, axis_scale);
|
||||
pad->SetDiagonalScaleCorrection(use_diagonal_scale_correction);
|
||||
pad->SetButtonDeadzone(button_deadzone);
|
||||
|
||||
if (ci->vibration_caps != Pad::VibrationCapabilities::NoVibration)
|
||||
|
||||
@@ -43,6 +43,7 @@ public: // Public members
|
||||
virtual void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) = 0;
|
||||
virtual void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) = 0;
|
||||
virtual void SetAxisScale(float deadzone, float scale) = 0;
|
||||
virtual void SetDiagonalScaleCorrection(bool enabled) = 0;
|
||||
virtual float GetVibrationScale(u32 motor) const = 0;
|
||||
virtual void SetVibrationScale(u32 motor, float scale) = 0;
|
||||
virtual float GetPressureModifier() const = 0;
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
#include "IconsPromptFont.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
static const InputBindingInfo s_bindings[] = {
|
||||
// clang-format off
|
||||
{"Up", TRANSLATE_NOOP("Pad", "D-Pad Up"), ICON_PF_DPAD_UP, InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_UP, GenericInputBinding::DPadUp},
|
||||
@@ -62,9 +65,14 @@ static const SettingInfo s_settings[] = {
|
||||
"0.00", "0.00", "1.00", "0.01", TRANSLATE_NOOP("Pad", "%.0f%%"), nullptr, nullptr, 100.0f},
|
||||
{SettingInfo::Type::Float, "AxisScale", TRANSLATE_NOOP("Pad", "Analog Sensitivity"),
|
||||
TRANSLATE_NOOP("Pad",
|
||||
"Sets the analog stick axis scaling factor. A value between 130% and 140% is recommended when using recent "
|
||||
"controllers, e.g. DualShock 4, Xbox One Controller."),
|
||||
"Sets the analog stick axis scaling factor. Modern controllers with square pickup zones, e.g. DualShock 4, Xbox One "
|
||||
"have better diagonal inputs at a range between 130-140%, but this will cause axes to reach max input early."),
|
||||
"1.33", "0.01", "2.00", "0.01", TRANSLATE_NOOP("Pad", "%.0f%%"), nullptr, nullptr, 100.0f},
|
||||
{SettingInfo::Type::Boolean, "UseDiagonalScaleCorrection", TRANSLATE_NOOP("Pad", "Use Diagonal Scale Correction"),
|
||||
TRANSLATE_NOOP("Pad",
|
||||
"Transforms analog stick pickup zone from a square to a circle, allows for full input at diagonals without also scaling the X and Y axes. "
|
||||
"Ideal for modern controllers with square pickup zones, e.g. DualShock 4, Xbox One. Setting Analog Sensitivity to 100% is recommended with this setting."),
|
||||
"false", "", "", "", TRANSLATE_NOOP("Pad", "%.0f%%"), nullptr, nullptr, 0.0f},
|
||||
{SettingInfo::Type::Float, "LargeMotorScale", TRANSLATE_NOOP("Pad", "Large Motor Vibration Scale"),
|
||||
TRANSLATE_NOOP("Pad", "Increases or decreases the intensity of low frequency vibration sent by the game."),
|
||||
"1.00", "0.00", "2.00", "0.01", TRANSLATE_NOOP("Pad", "%.0f%%"), nullptr, nullptr, 100.0f},
|
||||
@@ -576,14 +584,48 @@ void PadDualshock2::Set(u32 index, float value)
|
||||
if (index <= Inputs::PAD_L_LEFT)
|
||||
{
|
||||
// Left Stick
|
||||
this->analogs.lx = this->analogs.lxInvert ? MERGE(Inputs::PAD_L_LEFT, Inputs::PAD_L_RIGHT) : MERGE(Inputs::PAD_L_RIGHT, Inputs::PAD_L_LEFT);
|
||||
this->analogs.ly = this->analogs.lyInvert ? MERGE(Inputs::PAD_L_UP, Inputs::PAD_L_DOWN) : MERGE(Inputs::PAD_L_DOWN, Inputs::PAD_L_UP);
|
||||
const u8 combinedX = this->analogs.lxInvert ? MERGE(Inputs::PAD_L_LEFT, Inputs::PAD_L_RIGHT) : MERGE(Inputs::PAD_L_RIGHT, Inputs::PAD_L_LEFT);
|
||||
const u8 combinedY = this->analogs.lyInvert ? MERGE(Inputs::PAD_L_UP, Inputs::PAD_L_DOWN) : MERGE(Inputs::PAD_L_DOWN, Inputs::PAD_L_UP);
|
||||
|
||||
if (this->useDiagonalScaleCorrection)
|
||||
{
|
||||
const float normalizedX = (combinedX - 127.5) / 127.5f;
|
||||
const float normalizedY = (combinedY - 127.5) / 127.5f;
|
||||
const float magnitude = std::sqrt((normalizedX * normalizedX) + (normalizedY * normalizedY));
|
||||
const float max = std::max(std::abs(normalizedX), std::abs(normalizedY));
|
||||
const float scaledX = (normalizedX / max) * std::min(magnitude, 1.0f);
|
||||
const float scaledY = (normalizedY / max) * std::min(magnitude, 1.0f);
|
||||
this->analogs.lx = (scaledX * 127.5) + 127.5;
|
||||
this->analogs.ly = (scaledY * 127.5) + 127.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->analogs.lx = combinedX;
|
||||
this->analogs.ly = combinedY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Right Stick
|
||||
this->analogs.rx = this->analogs.rxInvert ? MERGE(Inputs::PAD_R_LEFT, Inputs::PAD_R_RIGHT) : MERGE(Inputs::PAD_R_RIGHT, Inputs::PAD_R_LEFT);
|
||||
this->analogs.ry = this->analogs.ryInvert ? MERGE(Inputs::PAD_R_UP, Inputs::PAD_R_DOWN) : MERGE(Inputs::PAD_R_DOWN, Inputs::PAD_R_UP);
|
||||
const u8 combinedX = this->analogs.rxInvert ? MERGE(Inputs::PAD_R_LEFT, Inputs::PAD_R_RIGHT) : MERGE(Inputs::PAD_R_RIGHT, Inputs::PAD_R_LEFT);
|
||||
const u8 combinedY = this->analogs.ryInvert ? MERGE(Inputs::PAD_R_UP, Inputs::PAD_R_DOWN) : MERGE(Inputs::PAD_R_DOWN, Inputs::PAD_R_UP);
|
||||
|
||||
if (this->useDiagonalScaleCorrection)
|
||||
{
|
||||
const float normalizedX = (combinedX - 127.5) / 127.5f;
|
||||
const float normalizedY = (combinedY - 127.5) / 127.5f;
|
||||
const float magnitude = std::sqrt((normalizedX * normalizedX) + (normalizedY * normalizedY));
|
||||
const float max = std::max(std::abs(normalizedX), std::abs(normalizedY));
|
||||
const float scaledX = (normalizedX / max) * std::min(magnitude, 1.0f);
|
||||
const float scaledY = (normalizedY / max) * std::min(magnitude, 1.0f);
|
||||
this->analogs.rx = (scaledX * 127.5) + 127.5;
|
||||
this->analogs.ry = (scaledY * 127.5) + 127.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->analogs.rx = combinedX;
|
||||
this->analogs.ry = combinedY;
|
||||
}
|
||||
}
|
||||
#undef MERGE
|
||||
|
||||
@@ -739,6 +781,11 @@ void PadDualshock2::SetAxisScale(float deadzone, float scale)
|
||||
this->axisScale = scale;
|
||||
}
|
||||
|
||||
void PadDualshock2::SetDiagonalScaleCorrection(bool enabled)
|
||||
{
|
||||
this->useDiagonalScaleCorrection = enabled;
|
||||
}
|
||||
|
||||
float PadDualshock2::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return this->vibrationScale[motor];
|
||||
|
||||
@@ -72,6 +72,8 @@ private:
|
||||
std::array<u8, VIBRATION_MOTORS> vibrationMotors = {};
|
||||
float axisScale = 1.0f;
|
||||
float axisDeadzone = 0.0f;
|
||||
// Determines if inputs from the host should be corrected from square pickup zone to circular
|
||||
bool useDiagonalScaleCorrection = false;
|
||||
std::array<float, 2> vibrationScale = {1.0f, 1.0f};
|
||||
// When the pressure modifier binding is activated, this is multiplied against
|
||||
// all values in pressures, to artificially reduce pressures and give players
|
||||
@@ -140,6 +142,7 @@ public:
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
void SetDiagonalScaleCorrection(bool enabled) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
|
||||
@@ -338,6 +338,10 @@ void PadGuitar::SetAxisScale(float deadzone, float scale)
|
||||
this->whammyAxisScale = scale;
|
||||
}
|
||||
|
||||
void PadGuitar::SetDiagonalScaleCorrection(bool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
float PadGuitar::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
void SetDiagonalScaleCorrection(bool enabled) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
|
||||
@@ -376,6 +376,10 @@ void PadJogcon::SetAxisScale(float deadzone, float scale)
|
||||
this->dialScale = scale;
|
||||
}
|
||||
|
||||
void PadJogcon::SetDiagonalScaleCorrection(bool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
float PadJogcon::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return this->vibrationScale[motor];
|
||||
|
||||
@@ -99,6 +99,7 @@ public:
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
void SetDiagonalScaleCorrection(bool enabled) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
|
||||
@@ -375,6 +375,10 @@ void PadNegcon::SetAxisScale(float deadzone, float scale)
|
||||
this->twistScale = scale;
|
||||
}
|
||||
|
||||
void PadNegcon::SetDiagonalScaleCorrection(bool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
float PadNegcon::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return this->vibrationScale[motor];
|
||||
|
||||
@@ -111,6 +111,7 @@ public:
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
void SetDiagonalScaleCorrection(bool enabled) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
|
||||
@@ -46,6 +46,11 @@ void PadNotConnected::SetAxisScale(float deadzone, float scale)
|
||||
|
||||
}
|
||||
|
||||
void PadNotConnected::SetDiagonalScaleCorrection(bool enabled)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float PadNotConnected::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
void SetDiagonalScaleCorrection(bool enabled) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
|
||||
@@ -410,6 +410,10 @@ void PadPopn::SetAxisScale(float deadzone, float scale)
|
||||
{
|
||||
}
|
||||
|
||||
void PadPopn::SetDiagonalScaleCorrection(bool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
float PadPopn::GetVibrationScale(u32 motor) const
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -96,6 +96,7 @@ public:
|
||||
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
|
||||
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
|
||||
void SetAxisScale(float deadzone, float scale) override;
|
||||
void SetDiagonalScaleCorrection(bool enabled) override;
|
||||
float GetVibrationScale(u32 motor) const override;
|
||||
void SetVibrationScale(u32 motor, float scale) override;
|
||||
float GetPressureModifier() const override;
|
||||
|
||||
@@ -101,6 +101,7 @@ namespace Pad
|
||||
// Default stick deadzone/sensitivity.
|
||||
static constexpr float DEFAULT_STICK_DEADZONE = 0.0f;
|
||||
static constexpr float DEFAULT_STICK_SCALE = 1.33f;
|
||||
static constexpr float DEFAULT_USE_DIAGONAL_SCALE_CORRECTION = false;
|
||||
static constexpr float DEFAULT_MOTOR_SCALE = 1.0f;
|
||||
static constexpr float DEFAULT_PRESSURE_MODIFIER = 0.5f;
|
||||
static constexpr float DEFAULT_BUTTON_DEADZONE = 0.0f;
|
||||
|
||||
Reference in New Issue
Block a user