Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

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.

ValueArms whileUsed by
"free" (default)the button is down and no other control that can answer on it declares itthe player scheme
"held"the button is downthe editor scheme, where holding it IS the fly gesture
"off"nevera 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.