Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

bindings

Binding primitives and evaluators. A binding names which physical input satisfies a control on one device class — the value a .inputBinding record's kbm / gamepad / touch field holds. A binding is a plain descriptor table (e.g. { kind = "key", code = "KeyW" }); the evaluators (evalHeld, evalPressed, evalReleased, evalAxis, evalVector) dispatch on kind and read Zin.state / Zin.virtual to produce the live signal. Zin.scheme runs them once per tick for every live binding, and they are public so chords, axes and library authors can evaluate a binding without reimplementing the dispatch.

-- boost.inputBinding/init.luau
local B = require("@builtin::modules.zinput.bindings")

return {
    label = "Boost",
    kind = "button",

    kbm     = { B.key("ShiftLeft") },
    gamepad = { B.padButton("left_shoulder") },
    touch   = { B.touchButton({ zone = "right-lower" }) },
}

Two frames, and which binding speaks which

  • Stick bindings (vector, touchStick, padStick) report the direction the player means — forward is +y. A move control carrying a keyboard class and a stick class drives both devices the same way.
  • Delta bindings (mouseDelta, touchDrag, scroll) report movement that happened — down is +y, because that is what the pointer did.

They also differ in magnitude: a stick is a position bounded at 1.0, a delta is however far the device moved this frame. A control carrying both — look, zoom — declares as = "delta" on its held class with the unitsPerSecond a full deflection is worth, and scale on a delta class that counts in its own units (a pinch in pixels beside a wheel in notches). Zin.scheme applies both, so one sensitivity covers every device.

Exports

Keyboard and mouse constructors:

  • M.key(code: string) -> Binding
  • M.mouse(button: string) -> Binding — "left" / "right" / "middle".
  • M.modKey(spec: string) -> Binding — "Ctrl+S", "Shift+Alt+P", "Escape".
  • M.axis(plus: Binding, minus: Binding, opts: StickOpts?) -> Binding
  • M.vector(right, left, up, down: Binding) -> Binding
  • M.wasd() -> Binding
  • M.arrowKeys() -> Binding
  • M.mouseDelta(axis: string?) -> Binding — this frame's mouse delta.
  • M.scroll(axis: string?) -> Binding — scrollwheel delta.
  • M.pointerLocked() -> Binding — boolean, true while locked.

Touch constructors (fed by Zin.virtual, which the on-screen controls write):

  • M.touchStick(opts: { zone, axis? }) -> Binding — vector.
  • M.touchButton(opts: { zone?, label?, icon?, priority?, size?, group? }) -> Binding — boolean.
  • M.touchDrag(opts: { zone, axis? }) -> Binding — per-frame delta vector.
  • M.touchPinch(opts: StickOpts?) -> Binding — scalar pinch delta.

Gamepad constructors (addressed by canonical position, or by the device's own 0-based element index for a wheel, pedals, a flight stick or any element past the canonical layout; slot names one pad by number or a device by a piece of its name, omitting it means any connected pad; rest / full calibrate an axis so rest reads 0 and full reads 1):

  • M.padButton(button: string | number, slot: (number | string)?) -> Binding
  • M.padAxis(axis: string | number, opts: PadAxisOpts?) -> Binding
  • M.padStick(stick: string, opts: StickOpts?) -> Binding
  • M.padTrigger(trigger: string, slot: number?) -> Binding

Predicates:

  • M.isBoolean(b) -> boolean
  • M.isAxis(b) -> boolean
  • M.isVector(b) -> boolean

Evaluators:

  • M.evalHeld(b) -> boolean
  • M.evalPressed(b) -> boolean
  • M.evalReleased(b) -> boolean
  • M.evalAxis(b) -> number
  • M.evalVector(b) -> Vec2

Pretty-printers:

  • M.format(b: any) -> string — single binding ("Space", "Ctrl+S", "WASD").
  • M.formatAll(bindings: any?, sep: string?) -> string — joined summary; non-table arg returns "<no bindings>".

Types:

  • Binding = { [string]: any } — descriptor table with kind plus type-specific fields.
  • Vec2 = { x: number, y: number }
  • StickOpts = { slot: number?, as: string?, unitsPerSecond: number?, scale: number? }

Notes

  • Bindings are pure data tables — they serialize cleanly, compare with Json.encode, and have no metatables.
  • modKey normalises modifier order in format() so a key written as Shift+Ctrl+KeyS displays the same as Ctrl+Shift+KeyS. The internal mods = { ctrl, shift, alt } flags are the canonical representation.
  • Mouse-delta, scroll, drag and pinch values are raw physical deltas, not clamped to [-1, 1]. as = "delta" + unitsPerSecond on the stick class beside them is what puts every class in one unit.
  • as = "delta" needs unitsPerSecond and has no default: the number that makes a pad feel right is the point of declaring the conversion, and a default would be right for one control and quietly wrong for the next.
  • Reading a member this module does not have raises immediately, naming the nearest members and the full list — a wrong guess at a constructor surfaces at the call rather than as attempt to call a nil value later.
  • format() always returns a string, never throws — returns "<invalid>" for malformed input.