fix(gamepad): resolve the menu diagonal tie-break horizontally on all clients (G25)

The gamepad-UI navigation resolvers disagreed on which way a perfect 45-degree
stick push (|x| == |y|) resolves: the SDL core picked horizontal (`ax >= ay`)
while Apple (`abs(x) > abs(y)`) and Android (`abs(Y) >= abs(X)`) picked vertical.
Align Apple (`>` -> `>=`) and Android (`>=` -> `>`) to the SDL core so an exact
diagonal moves focus the same way on every client (horizontal wins). This is
client-local menu navigation only and never reaches the wire. Completes the last
deferred G25 sub-part.

Verified: Apple `swift build` + full suite (124 pass); Android `:app:compileDebugKotlin`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 22:24:03 +02:00
parent 1af11cc64d
commit 764b5d938b
2 changed files with 7 additions and 2 deletions
@@ -241,7 +241,10 @@ private fun resolveDir(s: NavInputState): NavDir? {
if (s.hatY >= 0.5f) return NavDir.DOWN if (s.hatY >= 0.5f) return NavDir.DOWN
if (s.hatX <= -0.5f) return NavDir.LEFT if (s.hatX <= -0.5f) return NavDir.LEFT
if (s.hatX >= 0.5f) return NavDir.RIGHT if (s.hatX >= 0.5f) return NavDir.RIGHT
return if (abs(s.stickY) >= abs(s.stickX)) { // Horizontal wins an exact |x| == |y| diagonal tie (Y must be strictly greater to take the
// vertical branch), matching the SDL core and Apple nav so a perfect 45° push resolves the
// same on every client.
return if (abs(s.stickY) > abs(s.stickX)) {
when { when {
s.stickY <= -STICK_HIGH -> NavDir.UP s.stickY <= -STICK_HIGH -> NavDir.UP
s.stickY >= STICK_HIGH -> NavDir.DOWN s.stickY >= STICK_HIGH -> NavDir.DOWN
@@ -140,7 +140,9 @@ public final class GamepadMenuInput {
let stick = gamepad.leftThumbstick let stick = gamepad.leftThumbstick
let x = stick.xAxis.value let x = stick.xAxis.value
let y = stick.yAxis.value let y = stick.yAxis.value
if abs(x) > abs(y), abs(x) > deadzone { // Horizontal wins an exact |x| == |y| diagonal tie (>=), matching the SDL core and Android
// nav so a perfect 45° push resolves to the same direction on every client.
if abs(x) >= abs(y), abs(x) > deadzone {
return x > 0 ? .right : .left return x > 0 ? .right : .left
} else if abs(y) > deadzone { } else if abs(y) > deadzone {
return y > 0 ? .up : .down return y > 0 ? .up : .down