Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

axes

A name-registered axis registry over Zin.bindings. Any axis or vector binding becomes a Zin.axes entry with optional deadzone, exponential smoothing, curve shaping, invert, context gating, and a per-frame gate function. Stateful — Zin.tick calls advance(dt) each frame to evolve the smoothed reading.

A control asset replaced this. An axis1 / axis2 <name>.inputBinding/ inside an .inputMap/ carries a binding for keyboard-and-mouse, gamepad and touch, so one control reads a stick and a dragging thumb as well as a key, and the binding's own as / unitsPerSecond / scale bring every class into one unit. It declares the same deadzone, smoothing, curve and invert, applied by Zin.scheme through the same Zin.utils maths this reads:

public = {
    inputMap = Field.assetRef("inputMap", "@builtin::inputMaps.default", NoSync, "The controls this component reads."),
    speed = Field.number(5, NoSync, "World units per second at full deflection."),
    jumps = Field.number(0, NoSync, "How many times the jump control was pressed."),
}

local controls

function awake()
    controls = public.inputMap:activate()

    controls.move:onInput(function(v, dt, active)
        if not active then return end
        local p = public.entity.position
        local step = public.speed * dt
        public.entity.position = { p.x + v.x * step, p.y, p.z - v.y * step }
    end)

    controls.jump:onPressed(function() public.jumps += 1 end)
end

function onDestroy()
    public.inputMap:deactivate(controls)
end

Zin.map.bake(name) writes the currently active map out as an .inputMap asset. man topics/input covers the control model.

Exports

Lifecycle:

  • M.define(spec: AxisSpec) — define / replace axes.
  • M.remove(name: string) / M.clear() — drop one / all axes.
  • M.has(name) -> boolean / M.names() -> { string } / M.get(name) -> AxisDef?

Reads:

  • M.value(name: string) -> any — smoothed value (number for scalar, { x, y } for vector).
  • M.raw(name: string) -> any — raw unsmoothed binding value.

Tick hook:

  • M.advance(dt: number) — internal; called by Zin.tick.
  • M._setEnsureBindingsFn(fn) / M._setEnsureLiveFn(fn) — internal cold-read hooks.
  • M._resetGateWarnings() — test helper.

Types:

  • Curve = string | (number) -> number — "linear" / "quadratic" / "cubic" / custom.
  • AxisDef = { binding, deadzone, smoothing, curve, invert, context, gate, kind }
  • AxisSpec = { [string]: any } — define-spec.

Notes

  • smoothing is the exponential time constant in seconds. 0 means "snap to target instantly". Higher = laggier.
  • deadzone is radial for vector bindings — magnitude under the threshold zeros both axes — and scalar for scalar bindings.
  • Context gating is strict: the axis's declared context must equal Zin.context.current(). Mismatch snaps target to 0, and advance smooths current down toward 0.
  • A throwing gate falls through to "ungated" for that frame and logs one warning per axis per session (state cleared via _resetGateWarnings()).
  • Without a tick host (or Zin.autoTick.start()), value() returns the last computed snapshot; raw() always reads live.