acron.gamepad

Gamepad mechanisms: dead zone, a standard-pad reader, one adopted seat.

Three pieces every pad-aware game re-derives, extracted once:

  • dead_zone() — nothing inside the zone, the rest rescaled so the stick still reaches 1.

  • GamepadReader — a Acron InputDevice wrapped for polling: named axes, named buttons, triggers normalised across driver conventions, and per-frame button-edge latching. It wraps the device and nothing else, so a suite drives it with a stand-in device and pins the arithmetic with no hardware in the room.

  • PadSeat — the first pad wins the seat, later ones are ignored, and when the seat empties the survivor is adopted instead of leaving the game padless with a working controller attached.

One sign note, because it once cost a bug downstream: Acron reverses a gamepad’s Y axes so up reads positive (ioKitInputDevice.cxx: “we’d like to reverse the Y axis to match the XInput behavior”), where the standard-gamepad convention reads positive DOWN. The reader hands back the driver’s values untouched — which axes to re-flip is the caller’s sign policy, and signs are policy a game must pin.

GamepadReader(device)

One connected pad, read by polling as a standard gamepad.

PadSeat(base, wrap, prefix)

One adopted gamepad: first to arrive wins, the survivor inherits.

Global Functions

dead_zone(v: float, zone: float) → float

Nothing inside the zone, and the rest rescaled to the full range so the stick still reaches 1.