fix(gamepad): truncate stick/trigger axes uniformly across clients (G25)

Apple's GamepadCapture rounded axis values (`(v * scale).rounded()`) while
SDL-core and Android truncate, so a half-pressed control emitted 128 on Apple
vs 127 elsewhere. Drop `.rounded()` so `Int32(Float)` truncates toward zero on
Apple too; rails are unchanged (full deflection stays 255 / ±32767).

Also clamp SDL-core's LeftX/RightX to a symmetric -32767 like the Y axes and
the other clients already do, instead of letting the raw i16 reach -32768.

Verified: Apple `swift build` + full PunktfunkKit suite (124 pass); SDL half
on Windows .173 `cargo clippy -p pf-client-core -- -D warnings` (green).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 22:05:13 +02:00
parent 48933dc405
commit 26cac9ce20
2 changed files with 8 additions and 8 deletions
@@ -271,12 +271,12 @@ public final class GamepadCapture {
slot.buttons = newButtons slot.buttons = newButtons
} }
let newAxes: [Int32] = [ let newAxes: [Int32] = [
Int32((g.leftThumbstick.xAxis.value * 32767).rounded()), Int32(g.leftThumbstick.xAxis.value * 32767),
Int32((g.leftThumbstick.yAxis.value * 32767).rounded()), Int32(g.leftThumbstick.yAxis.value * 32767),
Int32((g.rightThumbstick.xAxis.value * 32767).rounded()), Int32(g.rightThumbstick.xAxis.value * 32767),
Int32((g.rightThumbstick.yAxis.value * 32767).rounded()), Int32(g.rightThumbstick.yAxis.value * 32767),
Int32((g.leftTrigger.value * 255).rounded()), Int32(g.leftTrigger.value * 255),
Int32((g.rightTrigger.value * 255).rounded()), Int32(g.rightTrigger.value * 255),
] ]
for (i, v) in newAxes.enumerated() where v != slot.axes[i] { for (i, v) in newAxes.enumerated() where v != slot.axes[i] {
connection.send(.gamepadAxis(UInt32(i), value: v, pad: slot.pad)) connection.send(.gamepadAxis(UInt32(i), value: v, pad: slot.pad))
+2 -2
View File
@@ -558,9 +558,9 @@ fn button_bit(b: sdl3::gamepad::Button) -> Option<u32> {
fn axis_value(axis: sdl3::gamepad::Axis, v: i16) -> (u32, i32) { fn axis_value(axis: sdl3::gamepad::Axis, v: i16) -> (u32, i32) {
use sdl3::gamepad::Axis; use sdl3::gamepad::Axis;
match axis { match axis {
Axis::LeftX => (wire::AXIS_LS_X, v as i32), Axis::LeftX => (wire::AXIS_LS_X, (v as i32).max(-32767)),
Axis::LeftY => (wire::AXIS_LS_Y, -(v as i32).max(-32767)), Axis::LeftY => (wire::AXIS_LS_Y, -(v as i32).max(-32767)),
Axis::RightX => (wire::AXIS_RS_X, v as i32), Axis::RightX => (wire::AXIS_RS_X, (v as i32).max(-32767)),
Axis::RightY => (wire::AXIS_RS_Y, -(v as i32).max(-32767)), Axis::RightY => (wire::AXIS_RS_Y, -(v as i32).max(-32767)),
Axis::TriggerLeft => (wire::AXIS_LT, (v as i32).clamp(0, 32767) >> 7), Axis::TriggerLeft => (wire::AXIS_LT, (v as i32).clamp(0, 32767) >> 7),
Axis::TriggerRight => (wire::AXIS_RT, (v as i32).clamp(0, 32767) >> 7), Axis::TriggerRight => (wire::AXIS_RT, (v as i32).clamp(0, 32767) >> 7),