diff --git a/Core/ControlMapper.cpp b/Core/ControlMapper.cpp index a8746afc08..57e5066a12 100644 --- a/Core/ControlMapper.cpp +++ b/Core/ControlMapper.cpp @@ -18,7 +18,28 @@ using KeyMap::MultiInputMapping; const float AXIS_BIND_THRESHOLD = 0.75f; const float AXIS_BIND_THRESHOLD_MOUSE = 0.01f; -float GetDeviceAxisThreshold(int device, const InputMapping &mapping) { + +// We reduce the threshold of some axes when another axis on the same stick is active. +// This makes it easier to hit diagonals if you bind an analog stick to four face buttons or D-Pad. +static InputAxis GetCoAxis(InputAxis axis) { + switch (axis) { + case JOYSTICK_AXIS_X: return JOYSTICK_AXIS_Y; + case JOYSTICK_AXIS_Y: return JOYSTICK_AXIS_X; + + // This looks weird, but it's simply how XInput axes are mapped. + case JOYSTICK_AXIS_Z: return JOYSTICK_AXIS_RZ; + case JOYSTICK_AXIS_RZ: return JOYSTICK_AXIS_Z; + + // Not sure if these two are used. + case JOYSTICK_AXIS_RX: return JOYSTICK_AXIS_RY; + case JOYSTICK_AXIS_RY: return JOYSTICK_AXIS_RX; + + default: + return JOYSTICK_AXIS_MAX; // invalid + } +} + +float ControlMapper::GetDeviceAxisThreshold(int device, const InputMapping &mapping) { if (device == DEVICE_ID_MOUSE) { return AXIS_BIND_THRESHOLD_MOUSE; } @@ -26,12 +47,27 @@ float GetDeviceAxisThreshold(int device, const InputMapping &mapping) { switch (KeyMap::GetAxisType((InputAxis)mapping.Axis(nullptr))) { case KeyMap::AxisType::TRIGGER: return g_Config.fAnalogTriggerThreshold; + case KeyMap::AxisType::STICK: + { + // Co-axis processing, see GetCoAxes comment. + InputAxis axis = (InputAxis)mapping.Axis(nullptr); + InputAxis coAxis = GetCoAxis(axis); + if (coAxis != JOYSTICK_AXIS_MAX) { + float absCoValue = fabsf(rawAxisValue_[(int)coAxis]); + if (absCoValue > 0.0f) { + // Bias down the threshold if the other axis is active. + float biasedThreshold = AXIS_BIND_THRESHOLD * (1.0f - absCoValue * 0.2f); + // INFO_LOG(SYSTEM, "coValue: %f threshold: %f", absCoValue, biasedThreshold); + return biasedThreshold; + } + } + break; + } default: - return AXIS_BIND_THRESHOLD; + break; } - } else { - return AXIS_BIND_THRESHOLD; } + return AXIS_BIND_THRESHOLD; } static int GetOppositeVKey(int vkey) { @@ -325,7 +361,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no } else { curTime = iter->second.timestamp; } - bool down = iter->second.value > GetDeviceAxisThreshold(iter->first.deviceId, mapping); + bool down = iter->second.value > 0.0f && iter->second.value > GetDeviceAxisThreshold(iter->first.deviceId, mapping); if (!down) all = false; } @@ -541,10 +577,16 @@ void ControlMapper::Axis(const AxisInput *axes, size_t count) { KeyMap::LockMappings(); for (size_t i = 0; i < count; i++) { const AxisInput &axis = axes[i]; + + if (axis.deviceId == DEVICE_ID_MOUSE && !g_Config.bMouseControl) { + continue; + } + size_t deviceIndex = (size_t)axis.deviceId; // this wraps -1 up high, so will get rejected on the next line. if (deviceIndex < (size_t)DEVICE_ID_COUNT) { deviceTimestamps_[deviceIndex] = now; } + rawAxisValue_[axis.axisId] = axis.value; // these are only used for co-axis mapping if (axis.value >= 0.0f) { InputMapping mapping(axis.deviceId, axis.axisId, 1); InputMapping opposite(axis.deviceId, axis.axisId, -1); diff --git a/Core/ControlMapper.h b/Core/ControlMapper.h index 1df1f39244..d7f2414e42 100644 --- a/Core/ControlMapper.h +++ b/Core/ControlMapper.h @@ -59,11 +59,16 @@ private: void onVKeyAnalog(int deviceId, int vkey, float value); void UpdateCurInputAxis(const InputMapping &mapping, float value, double timestamp); + float GetDeviceAxisThreshold(int device, const InputMapping &mapping); // To track mappable virtual keys. We can have as many as we want. float virtKeys_[VIRTKEY_COUNT]{}; bool virtKeyOn_[VIRTKEY_COUNT]{}; // Track boolean output separaately since thresholds may differ. + // This is only used for co-axis (analog stick to buttons), so not bothering to track separately + // per device. + float rawAxisValue_[JOYSTICK_AXIS_MAX]{}; + double deviceTimestamps_[(size_t)DEVICE_ID_COUNT]{}; int lastNonDeadzoneDeviceID_[2]{};