utils
Pure helpers for the `Zin` input library. Mouse-button name↔index conversion, key-code normalization, held-modifier matching against a frame snapshot, and the shaping a reading passes through on its way to a consumer. No FFI; safe to call from any context. Stateless.
utils
Pure helpers for the Zin input library. Mouse-button name↔index
conversion, key-code normalization, held-modifier matching against a frame
snapshot, and the shaping a reading passes through on its way to a
consumer. No FFI; safe to call from any context. Stateless.
Exports
M.buttonName(idx: number) -> string?— convert a 0-based mouse button index to its name.M.buttonIndex(name: string) -> number?— convert a mouse button name to its 0-based index.M.normalizeKey(code: string) -> string— canonicalize a key code: a single ASCII letter becomes itsKey<L>code, a single digit itsDigit<N>code; multi-character codes pass through.M.matchModifiers(snapshot: Snapshot, mods: Modifiers) -> boolean— test whether the snapshot's held keys match the requested modifier set.M.applyCurve(curve, x: number) -> number— apply a response curve to a reading.M.applyDeadzoneScalar(x: number, deadzone: number?) -> number— 0 below the threshold, the reading at or above it.M.applyDeadzoneVector(v: Vector2, deadzone: number?) -> Vector2— the same, measured radially on the magnitude of the pair.M.shapeScalar(x: number, deadzone: number?, curve, invert: boolean?) -> number— deadzone, then curve, then inversion.M.shapeVector(v: Vector2, deadzone: number?, curve, invert: boolean?) -> Vector2— the same for a pair.M.smoothToward(current: number, target: number, dt: number, tau: number) -> number— one step of an exponential approach with time constanttau.
A curve is "linear", "quadratic", "cubic", a function of the
reading, or nil for linear.
Types:
Snapshot = { [string]: any }— the raw frame-snapshot table returned byZin.state.get().Modifiers = { ctrl: boolean?, shift: boolean?, alt: boolean? }— modifier subset to require inmatchModifiers.Vector2 = { x: number, y: number }— a two-component reading.
Shaping
The order is deadzone, curve, invert, then the approach toward the shaped target. A scalar takes its deadzone per value; a pair takes it radially, so a diagonal is not clipped into a cross by two independent thresholds.
"quadratic" squares while keeping the sign, so a half-pushed stick reads
a quarter in the direction it was pushed. A curve function that raises, or
answers with anything other than a number, leaves the reading as it was.
This is the one implementation of that shaping: Zin.axes reads it for a
registered axis and Zin.scheme for an axis1 / axis2 control, so an
axis and a control declaring the same numbers read the same.
Usage
local Utils = require("@builtin::modules.zinput.utils")
local name = Utils.buttonName(0) -- "left"
local idx = Utils.buttonIndex("right") -- 1
local key = Utils.normalizeKey("w") -- "KeyW"
local hit = Utils.matchModifiers(snap, { ctrl = true, shift = false })
Notes
- Pure functions — no state, no side effects.
- Mouse-button indexing is 0-based and matches
Zin.state.mouseButtonDown(idx)(0=left, 1=right, 2=middle). matchModifiersignores fields set tonilinmods— onlytrue/falseare constraints.normalizeKeyrejects any other single character: no bound key code is one character long, so"?"raises rather than resolving to a phantom key nothing consumes.
Scoped to this part · feeds back into the world's score.