Builtin Library
README.md
virtual
Per-tick virtual-control values. On-screen controls (and tests) write stick
vectors, button states, and drag deltas here; the touchStick / touchButton
/ touchDrag / touchPinch binding kinds in Zin.bindings read them. Backs
Zin.virtual.
Three families, each keyed by the control's binding identity:
- Sticks — zone string (
"left","right", ...). A vector clamped to[-1, 1]per component, persisting until set again or reset. - Buttons — id string: a
touchButton'sid(stamped with the control's name when its map activates), else itslabel, else itszone. A held boolean;buttonPressed/buttonReleasedderive edges from the previous frame boundary. - Drags — zone string. A delta vector that accumulates within a tick
(
addDragsums repeated calls) and clears at the next frame boundary — the same per-frame-delta semantics asZin.state.mouseDelta().
Edge-at-frame-boundary semantics
_beginFrame() shifts _buttons into _buttonsPrev and clears drag deltas.
It runs once per engine frame from the Zin.tick coordinator's gated begin
block, before any binding evals happen. On-screen overlay code (script phase)
calls setButton earlier in the same frame it wants the press recognized;
buttonPressed reads true starting the frame _beginFrame next observes the
transition — matching how a real key's press edge surfaces on the frame
after the OS event, not the same frame the write happened.
Exports
M.setStick(zone: string, x: number, y: number)— set a stick's vector (clamped).M.stick(zone: string) -> (number, number)— read a stick's(x, y);(0, 0)when unset.M.setButton(id: string, held: boolean)— set a button's held state.M.button(id: string) -> boolean— held state.M.buttonPressed(id: string) -> boolean— press edge this frame.M.buttonReleased(id: string) -> boolean— release edge this frame.M.addDrag(zone: string, dx: number, dy: number)— accumulate a drag delta.M.drag(zone: string) -> (number, number)— read a zone's accumulated(dx, dy)this frame.M._beginFrame()— internal: frame-boundary edge shift + drag clear, called byZin.tick.M._reset()— test-only: clear all virtual state.
Usage
local Virtual = require("@builtin::modules.zinput.virtual")
Virtual.setStick("left", 0.4, -0.9)
local x, y = Virtual.stick("left")
Virtual.setButton("Jump", true)
if Virtual.buttonPressed("Jump") then
-- fires once, on the frame after the set
end