Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

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 its Key<L> code, a single digit its Digit<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 constant tau.

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 by Zin.state.get().
  • Modifiers = { ctrl: boolean?, shift: boolean?, alt: boolean? } — modifier subset to require in matchModifiers.
  • 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).
  • matchModifiers ignores fields set to nil in mods — only true/false are constraints.
  • normalizeKey rejects any other single character: no bound key code is one character long, so "?" raises rather than resolving to a phantom key nothing consumes.