diff --git a/Source/controls/controller_motion.cpp b/Source/controls/controller_motion.cpp index 692c25057..51039198c 100644 --- a/Source/controls/controller_motion.cpp +++ b/Source/controls/controller_motion.cpp @@ -207,17 +207,48 @@ void ProcessControllerMotion(const SDL_Event &event) } } -AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper) +AxisDirection GetAnalogStickDirection(float stickX, float stickY) { - const float stickX = leftStickX; - const float stickY = leftStickY; - + // avoid sqrt() by comparing squared magnitudes + const float magnitudeSquared = stickX * stickX + stickY * stickY; + const float thresholdSquared = StickDirectionThreshold * StickDirectionThreshold; + if (magnitudeSquared < thresholdSquared) + return { AxisDirectionX_NONE, AxisDirectionY_NONE }; + + const float absX = std::fabs(stickX); + const float absY = std::fabs(stickY); AxisDirection result { AxisDirectionX_NONE, AxisDirectionY_NONE }; - bool isUpPressed = stickY >= 0.5; - bool isDownPressed = stickY <= -0.5; - bool isLeftPressed = stickX <= -0.5; - bool isRightPressed = stickX >= 0.5; + // 8-way sectoring with 22.5° cutoffs + constexpr float DiagonalCutoff = 0.41421356F; // tan(22.5°) + if (absX == 0.0F) { + result.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN; + return result; + } + + const float ratio = absY / absX; + if (ratio <= DiagonalCutoff) { + result.x = stickX > 0 ? AxisDirectionX_RIGHT : AxisDirectionX_LEFT; + return result; + } + if (ratio >= 1.0F / DiagonalCutoff) { + result.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN; + return result; + } + + result.x = stickX > 0 ? AxisDirectionX_RIGHT : AxisDirectionX_LEFT; + result.y = stickY > 0 ? AxisDirectionY_UP : AxisDirectionY_DOWN; + return result; +} + +AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper) +{ + AxisDirection result = GetAnalogStickDirection(leftStickX, leftStickY); + + bool isUpPressed = false; + bool isDownPressed = false; + bool isLeftPressed = false; + bool isRightPressed = false; if (usePadmapper) { isUpPressed |= PadmapperIsActionActive("MoveUp"); diff --git a/Source/controls/controller_motion.h b/Source/controls/controller_motion.h index 317f22795..fe507c09a 100644 --- a/Source/controls/controller_motion.h +++ b/Source/controls/controller_motion.h @@ -25,6 +25,9 @@ extern float leftStickX, leftStickY, rightStickX, rightStickY; // Whether stick positions have been updated and need rescaling. extern bool leftStickNeedsScaling, rightStickNeedsScaling; +// Minimum scaled stick magnitude to register a direction. +constexpr float StickDirectionThreshold = 0.4F; + // Updates motion state for mouse and joystick sticks. void ProcessControllerMotion(const SDL_Event &event); diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 7a54aba31..c4ec5092f 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1594,8 +1594,11 @@ struct RightStickAccumulator { bool IsStickMovementSignificant() { - return leftStickX >= 0.5 || leftStickX <= -0.5 - || leftStickY >= 0.5 || leftStickY <= -0.5 + // avoid sqrt() by comparing squared magnitudes + const float leftStickMagnitudeSquared = leftStickX * leftStickX + leftStickY * leftStickY; + const float thresholdSquared = StickDirectionThreshold * StickDirectionThreshold; + + return leftStickMagnitudeSquared >= thresholdSquared || rightStickX != 0 || rightStickY != 0; }