mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Merge branch 'analog-options' of https://github.com/ShiftyAxel/ppsspp into ShiftyAxel-analog-options
This commit is contained in:
commit
cbf8aa41a4
@ -573,6 +573,17 @@ static ConfigSetting controlSettings[] = {
|
||||
ConfigSetting("AnalogStickX", &g_Config.fAnalogStickX, -1.0f, true, true),
|
||||
ConfigSetting("AnalogStickY", &g_Config.fAnalogStickY, -1.0f, true, true),
|
||||
ConfigSetting("AnalogStickScale", &g_Config.fAnalogStickScale, defaultControlScale, true, true),
|
||||
#ifdef _WIN32
|
||||
ConfigSetting("DInputAnalogDeadzone", &g_Config.fDInputAnalogDeadzone, 0.1f, true, true),
|
||||
ConfigSetting("DInputAnalogInverseMode", &g_Config.iDInputAnalogInverseMode, 0, true, true),
|
||||
ConfigSetting("DInputAnalogInverseDeadzone", &g_Config.fDInputAnalogInverseDeadzone, 0.0f, true, true),
|
||||
ConfigSetting("DInputAnalogSensitivity", &g_Config.fDInputAnalogSensitivity, 1.0f, true, true),
|
||||
|
||||
ConfigSetting("XInputAnalogDeadzone", &g_Config.fXInputAnalogDeadzone, 0.24f, true, true),
|
||||
ConfigSetting("XInputAnalogInverseMode", &g_Config.iXInputAnalogInverseMode, 0, true, true),
|
||||
ConfigSetting("XInputAnalogInverseDeadzone", &g_Config.fXInputAnalogInverseDeadzone, 0.0f, true, true),
|
||||
ConfigSetting("XInputAnalogSensitivity", &g_Config.fXInputAnalogSensitivity, 1.0f, true, true),
|
||||
#endif
|
||||
ConfigSetting("AnalogLimiterDeadzone", &g_Config.fAnalogLimiterDeadzone, 0.6f, true, true),
|
||||
|
||||
ConfigSetting(false),
|
||||
|
@ -294,6 +294,16 @@ public:
|
||||
|
||||
bool bHapticFeedback;
|
||||
|
||||
float fDInputAnalogDeadzone;
|
||||
int iDInputAnalogInverseMode;
|
||||
float fDInputAnalogInverseDeadzone;
|
||||
float fDInputAnalogSensitivity;
|
||||
|
||||
float fXInputAnalogDeadzone;
|
||||
int iXInputAnalogInverseMode;
|
||||
float fXInputAnalogInverseDeadzone;
|
||||
float fXInputAnalogSensitivity;
|
||||
|
||||
float fAnalogLimiterDeadzone;
|
||||
// GLES backend-specific hacks. Not saved to the ini file, do not add checkboxes. Will be made into
|
||||
// proper options when good enough.
|
||||
|
@ -409,6 +409,20 @@ void GameSettingsScreen::CreateViews() {
|
||||
View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, c->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), c, screenManager()));
|
||||
style->SetEnabledPtr(&g_Config.bShowTouchControls);
|
||||
|
||||
static const char *inverseDeadzoneModes[] = { "Off", "X", "Y", "X + Y" };
|
||||
|
||||
controlsSettings->Add(new ItemHeader(c->T("DInput Analog Settings", "DInput Analog Settings")));
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogDeadzone, 0.0f, 1.0f, c->T("Dead Zone"), screenManager()));
|
||||
controlsSettings->Add(new PopupMultiChoice(&g_Config.iDInputAnalogInverseMode, c->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), c, screenManager()));
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogInverseDeadzone, 0.0f, 1.0f, c->T("Analog Mapper Low End (Inverse Deadzone)"), screenManager()));
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogSensitivity, 0.0f, 10.0f, c->T("Analog Mapper High End (Axis Sensitivity)"), screenManager()));
|
||||
|
||||
controlsSettings->Add(new ItemHeader(c->T("XInput Analog Settings", "XInput Analog Settings")));
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogDeadzone, 0.0f, 1.0f, c->T("Dead Zone"), screenManager()));
|
||||
controlsSettings->Add(new PopupMultiChoice(&g_Config.iXInputAnalogInverseMode, c->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), c, screenManager()));
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogInverseDeadzone, 0.0f, 1.0f, c->T("Analog Mapper Low End (Inverse Deadzone)"), screenManager()));
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, c->T("Analog Mapper High End (Axis Sensitivity)"), screenManager()));
|
||||
|
||||
controlsSettings->Add(new ItemHeader(c->T("Keyboard", "Keyboard Control Settings")));
|
||||
#if defined(USING_WIN_UI)
|
||||
controlsSettings->Add(new CheckBox(&g_Config.bIgnoreWindowsKey, c->T("Ignore Windows Key")));
|
||||
|
@ -177,8 +177,8 @@ DinputDevice::DinputDevice(int devnum) {
|
||||
dipw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipw.diph.dwHow = DIPH_DEVICE;
|
||||
dipw.diph.dwObj = 0;
|
||||
// dwData 1000 is deadzone(0% - 10%)
|
||||
dipw.dwData = 1000;
|
||||
// dwData 10000 is deadzone(0% - 100%), multiply by config scalar
|
||||
dipw.dwData = (int)(g_Config.fDInputAnalogDeadzone * 10000);
|
||||
|
||||
analog |= FAILED(pJoystick->SetProperty(DIPROP_DEADZONE, &dipw.diph)) ? false : true;
|
||||
}
|
||||
@ -208,12 +208,20 @@ void SendNativeAxis(int deviceId, short value, short &lastValue, int axisId) {
|
||||
AxisInput axis;
|
||||
axis.deviceId = deviceId;
|
||||
axis.axisId = axisId;
|
||||
axis.value = NormalizedDeadzoneFilter(value);
|
||||
axis.value = (float)value / 10000.0f; // Convert axis to normalised float
|
||||
NativeAxis(axis);
|
||||
|
||||
lastValue = value;
|
||||
}
|
||||
|
||||
inline float Signs(short val) {
|
||||
return (0 < val) - (val < 0);
|
||||
}
|
||||
|
||||
inline float LinearMaps(short val, short a0, short a1, short b0, short b1) {
|
||||
return b0 + (((val - a0) * (b1 - b0)) / (a1 - a0));
|
||||
}
|
||||
|
||||
int DinputDevice::UpdateState(InputState &input_state) {
|
||||
if (!pJoystick) return -1;
|
||||
|
||||
@ -233,6 +241,54 @@ int DinputDevice::UpdateState(InputState &input_state) {
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_PAD_0 + pDevNum;
|
||||
|
||||
// Circle to Square mapping, cribbed from XInputDevice
|
||||
float sx = js.lX;
|
||||
float sy = js.lY;
|
||||
float scaleFactor = sqrtf((sx * sx + sy * sy) / std::max(sx * sx, sy * sy));
|
||||
js.lX = (short)(sx * scaleFactor);
|
||||
js.lY = (short)(sy * scaleFactor);
|
||||
|
||||
// Linear range mapping (used to invert deadzones)
|
||||
float dz = g_Config.fDInputAnalogDeadzone;
|
||||
int idzm = g_Config.iDInputAnalogInverseMode;
|
||||
float idz = g_Config.fDInputAnalogInverseDeadzone;
|
||||
float md = std::max(dz, idz);
|
||||
float st = g_Config.fDInputAnalogSensitivity;
|
||||
|
||||
float magnitude = sqrtf(js.lX * js.lX + js.lY * js.lY);
|
||||
if (magnitude > dz * 10000.0f) {
|
||||
if (idzm == 1)
|
||||
{
|
||||
short xSign = Signs(js.lX);
|
||||
if (xSign != 0.0f) {
|
||||
js.lX = LinearMaps(js.lX, xSign * (short)(dz * 10000), xSign * 10000, xSign * (short)(md * 10000), xSign * 10000 * st);
|
||||
}
|
||||
}
|
||||
else if (idzm == 2)
|
||||
{
|
||||
short ySign = Signs(js.lY);
|
||||
if (ySign != 0.0f) {
|
||||
js.lY = LinearMaps(js.lY, ySign * (short)(dz * 10000.0f), ySign * 10000, ySign * (short)(md * 10000.0f), ySign * 10000 * st);
|
||||
}
|
||||
}
|
||||
else if (idzm == 3)
|
||||
{
|
||||
float xNorm = (float)js.lX / magnitude;
|
||||
float yNorm = (float)js.lY / magnitude;
|
||||
float mapMag = LinearMaps(magnitude, dz * 10000.0f, 10000.0f, md * 10000.0f, 10000.0f * st);
|
||||
js.lX = (short)(xNorm * mapMag);
|
||||
js.lY = (short)(yNorm * mapMag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
js.lX = 0;
|
||||
js.lY = 0;
|
||||
}
|
||||
|
||||
js.lX = (short)std::min(10000.0f, std::max((float)js.lX, -10000.0f));
|
||||
js.lY = (short)std::min(10000.0f, std::max((float)js.lY, -10000.0f));
|
||||
|
||||
SendNativeAxis(DEVICE_ID_PAD_0 + pDevNum, js.lX, last_lX_, JOYSTICK_AXIS_X);
|
||||
SendNativeAxis(DEVICE_ID_PAD_0 + pDevNum, js.lY, last_lY_, JOYSTICK_AXIS_Y);
|
||||
SendNativeAxis(DEVICE_ID_PAD_0 + pDevNum, js.lZ, last_lZ_, JOYSTICK_AXIS_Z);
|
||||
@ -253,15 +309,6 @@ int DinputDevice::UpdateState(InputState &input_state) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static float NormalizedDeadzoneFilter(short value) {
|
||||
float result = (float)value / 10000.0f;
|
||||
|
||||
// Expand and clamp. Hack to let us reach the corners on most pads.
|
||||
result = std::min(1.0f, std::max(result * 1.2f, -1.0f));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DinputDevice::ApplyButtons(DIJOYSTATE2 &state, InputState &input_state) {
|
||||
BYTE *buttons = state.rgbButtons;
|
||||
u32 downMask = 0x80;
|
||||
|
@ -120,12 +120,20 @@ inline float Clampf(float val, float min, float max) {
|
||||
return val;
|
||||
}
|
||||
|
||||
static Stick NormalizedDeadzoneFilter(short x, short y, short thresh) {
|
||||
static const float DEADZONE = (float)thresh / 32767.0f;
|
||||
inline float Signf(float val) {
|
||||
return (0.0f < val) - (val < 0.0f);
|
||||
}
|
||||
|
||||
inline float LinearMapf(float val, float a0, float a1, float b0, float b1) {
|
||||
return b0 + (((val - a0) * (b1 - b0)) / (a1 - a0));
|
||||
}
|
||||
|
||||
static Stick NormalizedDeadzoneFilter(short x, short y, float dz, int idzm, float idz, float st) {
|
||||
Stick s(x, y, 1.0 / 32767.0f);
|
||||
|
||||
float magnitude = sqrtf(s.x * s.x + s.y * s.y);
|
||||
if (magnitude > DEADZONE) {
|
||||
if (magnitude > dz) {
|
||||
|
||||
// Circle to square mapping (the PSP stick outputs the full -1..1 square of values)
|
||||
#if 1
|
||||
// Looks way better than the old one, below, in the axis tester.
|
||||
@ -140,6 +148,33 @@ static Stick NormalizedDeadzoneFilter(short x, short y, short thresh) {
|
||||
s.y *= 1.41421f;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Linear range mapping (used to invert deadzones)
|
||||
float md = std::max(dz, idz);
|
||||
|
||||
if (idzm == 1)
|
||||
{
|
||||
float xSign = Signf(s.x);
|
||||
if (xSign != 0.0f) {
|
||||
s.x = LinearMapf(s.x, xSign * dz, xSign, xSign * md, xSign * st);
|
||||
}
|
||||
}
|
||||
else if (idzm == 2)
|
||||
{
|
||||
float ySign = Signf(s.y);
|
||||
if (ySign != 0.0f) {
|
||||
s.y = LinearMapf(s.y, ySign * dz, ySign, ySign * md, ySign * st);
|
||||
}
|
||||
}
|
||||
else if (idzm == 3)
|
||||
{
|
||||
float xNorm = s.x / magnitude;
|
||||
float yNorm = s.y / magnitude;
|
||||
float mapMag = LinearMapf(magnitude, dz, 1.0f, md, st);
|
||||
s.x = xNorm * mapMag;
|
||||
s.y = yNorm * mapMag;
|
||||
}
|
||||
|
||||
s.x = Clampf(s.x, -1.0f, 1.0f);
|
||||
s.y = Clampf(s.y, -1.0f, 1.0f);
|
||||
} else {
|
||||
@ -149,14 +184,13 @@ static Stick NormalizedDeadzoneFilter(short x, short y, short thresh) {
|
||||
return s;
|
||||
}
|
||||
|
||||
bool NormalizedDeadzoneDiffers(short x1, short y1, short x2, short y2, const short thresh) {
|
||||
static const float DEADZONE = (float)thresh / 32767.0f;
|
||||
bool NormalizedDeadzoneDiffers(short x1, short y1, short x2, short y2, const float dz) {
|
||||
Stick s1(x1, y1, 1.0 / 32767.0f);
|
||||
Stick s2(x2, y2, 1.0 / 32767.0f);
|
||||
|
||||
float magnitude1 = sqrtf(s1.x * s1.x + s1.y * s1.y);
|
||||
float magnitude2 = sqrtf(s2.x * s2.x + s2.y * s2.y);
|
||||
if (magnitude1 > DEADZONE || magnitude2 > DEADZONE) {
|
||||
if (magnitude1 > dz || magnitude2 > dz) {
|
||||
return x1 != x2 || y1 != y2;
|
||||
}
|
||||
return false;
|
||||
@ -201,8 +235,13 @@ int XinputDevice::UpdateState(InputState &input_state) {
|
||||
}
|
||||
ApplyButtons(state, input_state);
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.sThumbLX, prevState.Gamepad.sThumbLY, state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)) {
|
||||
Stick left = NormalizedDeadzoneFilter(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
|
||||
const float STICK_DEADZONE = g_Config.fXInputAnalogDeadzone;
|
||||
const int STICK_INV_MODE = g_Config.iXInputAnalogInverseMode;
|
||||
const float STICK_INV_DEADZONE = g_Config.fXInputAnalogInverseDeadzone;
|
||||
const float STICK_SENSITIVITY = g_Config.fXInputAnalogSensitivity;
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.sThumbLX, prevState.Gamepad.sThumbLY, state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, STICK_DEADZONE)) {
|
||||
Stick left = NormalizedDeadzoneFilter(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, STICK_DEADZONE, STICK_INV_MODE, STICK_INV_DEADZONE, STICK_SENSITIVITY);
|
||||
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0;
|
||||
@ -218,8 +257,8 @@ int XinputDevice::UpdateState(InputState &input_state) {
|
||||
}
|
||||
}
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.sThumbRX, prevState.Gamepad.sThumbRY, state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)) {
|
||||
Stick right = NormalizedDeadzoneFilter(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.sThumbRX, prevState.Gamepad.sThumbRY, state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, STICK_DEADZONE)) {
|
||||
Stick right = NormalizedDeadzoneFilter(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, STICK_DEADZONE, STICK_INV_MODE, STICK_INV_DEADZONE, STICK_SENSITIVITY);
|
||||
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0;
|
||||
|
Loading…
Reference in New Issue
Block a user