Builtin Library
README.md
gamepad
The pad-facing surface: which controllers are connected, what family they
belong to, and what a legend should call a canonical button on them. Backs
Zin.gamepad.
Bindings never come through here. A scheme binds B.padButton("south") and
evaluates against whichever pad is connected; this module answers the
questions a UI asks — how many players have controllers, and which letter to
draw on a prompt.
Position, not letter
The canonical layout names a button by POSITION, because position is what
every pad shares — south is the lower face button on all of them. The
letter printed on it is not shared: south is A on an Xbox pad, Cross
on a PlayStation one, and B on a Nintendo one. label() resolves that
from the device name the platform reported, so a binding stays
device-independent and only the drawn glyph changes.
Anything unrecognised reads as xbox, because the standard mapping every
backend normalises to is the Xbox layout.
Exports
M.list() -> { Pad }— every connected pad, in slot order.M.count() -> number— how many pads are connected.M.get(slot) -> Pad?— the pad in one slot.M.family(slot?) -> string—"xbox"|"playstation"|"nintendo".M.label(button, slot?) -> string— the legend for a canonical button.M.available() -> boolean— whether the session has ever seen a pad. Latched by the first connection, so unplugging one does not flip a scheme's prompts back to keyboard glyphs on a cable knock.
Types:
Pad = { slot, name, buttons, buttons_pressed, buttons_released, axes, simulated }— the button fields are arrays of canonical names,axesa map of canonical axis name to number, andsimulatedmarks a pad that came from theinputSimtoolbox rather than a device.
Usage
local Zin = require("@builtin::modules.zinput")
if Zin.gamepad.count() >= 2 then
startLocalCoop()
end
ui.text("Press " .. Zin.gamepad.label("south") .. " to jump")