Builtin Library
README.md
arming
The predicate a look-style control hands to its gate, in the one place it
is written. Backs Zin.arming.
A mouse always has a delta, so an ungated mouse-look turns the camera
whenever the cursor crosses the window. The gate answers "is the player
steering?" — and every scheme answers it with the same list of gestures in a
different combination. Zin.arming.gate(opts) takes the combination and
returns the predicate.
local Arming = require("@builtin::modules.zinput.arming")
return {
label = "Look",
kind = "axis2",
gate = Arming.gate({ dragZone = "right", stick = "right" }),
kbm = B.mouseDelta(),
gamepad = B.padStick("right", { as = "delta", unitsPerSecond = 1200 }),
touch = B.touchDrag({ zone = "right" }),
}
A locked pointer always arms: a cursor the scheme took is one the player
gave to the camera. The rest is named in opts — dragZone for a finger
inside a touch zone, stick for a deflected pad stick, padButtons for a
trigger, virtualButtons for an on-screen button by its id.
The right mouse button
rightButton is the field the schemes disagree about, because the button
means two different things.
| Value | Arms while | Used by |
|---|---|---|
"free" (default) | the button is down and no other control that can answer on it declares it | the player scheme |
"held" | the button is down | the editor scheme, where holding it IS the fly gesture |
"off" | never | a control that reads the button through nothing but pointer lock |
"free" is what lets a world bind the right button to a game action. The
engine's default scheme arms mouse-look on that button, and a world that
also binds it would otherwise get the camera turn and its own action from
one gesture, with no way to decline the camera half short of standing down
its whole control group. Under "free" the world's binding is the claim:
declare the button in a live .inputMap control, or in the Zin.actions /
Zin.axes registry, and the arming stands down for as long as that control
can answer on it. A control whose map is standing down for a suppressor, or
whose context is not the one on top, is one the player cannot reach — the
same two terms the tick's own dispatch reads before it evaluates a control —
so the button is free of it while that holds and the camera keeps the drag.
Zin.arming.rightButtonClaimants() names who is holding it, which is the
answer to "why did my right-drag stop turning the camera":
Zin.arming.rightButtonClaimants() --> { "map:torch.torchToggle" }
The engine's own arming gesture — the lookDrag control on the standard
scheme, and the look_drag action beside it in the registry — is what
"free" arms FROM, so those two names are passed over by the search.
A claim is decided on the frame the button goes down and holds until it comes up. A map activating mid-drag therefore cannot take a gesture away from the camera halfway through it, and the search runs once per press rather than once per gated control per frame.