feat(apple): multi-controller support
Roll the pf-client-core slot pattern to the Apple client (Swift): - GamepadManager tracks all connected GCControllers, assigning each a stable lowest-free wire pad index + concrete type, emitting GamepadArrival on connect and GamepadRemove on disconnect (index freed for reuse on re-plug). - GamepadCapture binds every controller with per-controller Slot state (buttons/axes/fingers/motion), threading the pad index into flags on every event; GamepadWire/InputEvents carry the pad + the two new events. - GamepadFeedback + RumbleRenderer go per-pad (rumbleByPad, slots[pad]), routing rumble/HID back to the correct controller by wire index. - ContentView/Settings surface every forwarded controller. pad 0 => flags 0, so single-controller wire is byte-identical. Cannot build on the Linux dev box (no Swift toolchain / Apple frameworks); wire bytes hand-checked against input.rs and GamepadWireTests extended for multi-pad. CI apple.yml (swift build/test on macOS) is the compile gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -419,9 +419,10 @@ final class SessionModel: ObservableObject {
|
||||
micChannel: defaults.integer(forKey: DefaultsKey.micChannel),
|
||||
micEnabled: defaults.object(forKey: DefaultsKey.micEnabled) as? Bool ?? true)
|
||||
self.audio = audio
|
||||
// Gamepads: forward GamepadManager's active controller as pad 0 and render the
|
||||
// host's feedback (rumble always; lightbar/player-LEDs/adaptive-triggers when the
|
||||
// session's virtual pad is a DualSense). Same trust gate as audio — nothing is
|
||||
// Gamepads: forward every controller GamepadManager selected — each on its own wire pad
|
||||
// index (a pin forwards only one, Automatic forwards all) — and render the host's feedback
|
||||
// back to the pad it's addressed to (rumble always; lightbar/player-LEDs/adaptive-triggers
|
||||
// when a pad's virtual device is a DualSense). Same trust gate as audio — nothing is
|
||||
// forwarded during the trust prompt.
|
||||
let capture = GamepadCapture(connection: conn, manager: .shared)
|
||||
// The cross-client escape chord (hold L1+R1+Start+Select 1.5 s) — on tvOS the only
|
||||
|
||||
Reference in New Issue
Block a user