diff --git a/Core/ControlMapper.cpp b/Core/ControlMapper.cpp index 5877a2ba63..cd144c5178 100644 --- a/Core/ControlMapper.cpp +++ b/Core/ControlMapper.cpp @@ -155,6 +155,15 @@ static int RotatePSPKeyCode(int x) { } } +// Used to decay analog values when clashing with digital ones. +static float ReduceMagnitude(float value) { + value *= 0.75f; + if ((value > 0.0f && value < 0.05f) || (value < 0.0f && value > -0.05f)) { + value = 0.0f; + } + return value; +} + // Can only be called from Key or Axis. bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) { // Instead of taking an input key and finding what it outputs, we loop through the OUTPUTS and @@ -262,6 +271,20 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) { continue; } + // Small values from analog inputs like gamepad sticks can linger around, which is bad here because we sum + // up before applying deadzone etc. This means that it can be impossible to reach the min/max values with digital input! + // So if non-analog events clash with analog ones mapped to the same input, decay the analog input, + // which will quickly get things back to normal, while if it's intentional to use both at the same time for some reason, + // that still works, though a bit weaker. We could also zero here, but you never know who relies on such strange tricks.. + // Note: This is an old problem, it didn't appear with the refactoring. + if (!changedMapping.IsAxis()) { + for (auto &mapping : inputMappings) { + if (mapping.IsAxis()) { + curInput_[mapping] = ReduceMagnitude(curInput_[mapping]); + } + } + } + value = clamp_value(value, 0.0f, 1.0f); // Derive bools from the floats using the device's threshold. @@ -440,7 +463,7 @@ void ControlMapper::GetDebugString(char *buffer, size_t bufSize) const { } for (int i = 0; i < ARRAY_SIZE(virtKeys_); i++) { int vkId = VIRTKEY_FIRST + i; - if ((vkId >= VIRTKEY_AXIS_X_MIN && vkId <= VIRTKEY_AXIS_Y_MAX) || vkId == VIRTKEY_ANALOG_LIGHTLY) { + if ((vkId >= VIRTKEY_AXIS_X_MIN && vkId <= VIRTKEY_AXIS_Y_MAX) || vkId == VIRTKEY_ANALOG_LIGHTLY || vkId == VIRTKEY_SPEED_ANALOG) { str << KeyMap::GetPspButtonName(vkId) << ": " << virtKeys_[i] << std::endl; } } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 8707215c47..96590a75e5 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -771,7 +771,9 @@ void EmuScreen::onVKeyAnalog(int virtualKeyCode, float value) { // We only handle VIRTKEY_SPEED_ANALOG here. - static constexpr float DEADZONE_THRESHOLD = 0.15f; + // Xbox controllers need a pretty big deadzone here to not leave behind small values + // on occasion when releasing the trigger. Still feels right. + static constexpr float DEADZONE_THRESHOLD = 0.20f; static constexpr float DEADZONE_SCALE = 1.0f / (1.0f - DEADZONE_THRESHOLD); FPSLimit &limitMode = PSP_CoreParameter().fpsLimit;