controls
The kit's public API: the one module a game requires. `Controls.use(scheme)` switches on a complete keyboard + mouse, gamepad and touch scheme. `value` / `held` / `pressed` / `released` / `charge` / `on` / `onGesture` read the shared action names. `setStick` / `setButtons` / `set…
controlsKit.controls
The kit's public API: the one module a game requires. Controls.use(scheme) switches on a complete keyboard + mouse, gamepad and touch scheme. value / held / pressed / released / charge / on / onGesture read the shared action names. setStick / setButtons / setSkin / setPromptStyle change styles live. rebind / conflicts / resetBindings / exportBindings handle bindings. styles() / schemes() / describe() / capabilities() answer what the kit has, and player(n, filter) adds extra local players.
local Controls = require("controlsKit.controls")
Controls.use("twinStick")
local move = Controls.value("move")
Controls.on("fire", function() shoot() end)
The kit ticks itself once a frame after the first call; Controls.stop() shuts it down. See the package README for the full list.
Interface
What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.
conforms to
zero/source-extract/v2controlsKit.controls — the kit's public face. local Controls = require("controlsKit.controls") Controls.use("twinStick") -- keyboard + mouse, pad, touch local mv = Controls.value("move") -- { x, y }, y up, length <= 1 if Controls.pressed("fire") then ... end Controls.on("jump", function() ... end) Controls.use("platformer") -- live switch, same actions Every scheme speaks the same action names (see `~.schemes`), so the game's code never changes when the controls do. Reading kinds: button : value 0/1, held/pressed/released, charge (0..1 while held) vec2 : value { x, y }, x right / y up, length <= 1 axis1 : value -1..1 (or 0..1 for throttle-like actions) delta2 : value { x, y } this frame, in screen points, x right / y down `Controls.*` is player 1 (keyboard + mouse, the first pad, touch). `Controls.player(2, { keyboard = false, pad = 2, touch = false })` gives a second local player its own controller with the same API. In a networked world each peer runs its own copy of the kit, so player 1 is always the local player: gate movement on `entity:isLocal()`.
len(x: number, y: number) → number
| arg | type | description |
|---|---|---|
| x | number | |
| y | number |
clamp(v: number, a: number, b: number) → number
| arg | type | description |
|---|---|---|
| v | number | |
| a | number | |
| b | number |
padDead(x: number, y: number) → void
| arg | type | description |
|---|---|---|
| x | number | |
| y | number |
padDead1(v: number) → number
| arg | type | description |
|---|---|---|
| v | number |
mouseIndex(code: string) → number
| arg | type | description |
|---|---|---|
| code | string |
newController(n: number, filter: any?) → any
| arg | type | description |
|---|---|---|
| n | number | |
| filter | any? |
padSlot( ) → number
usesPad( ) → boolean
labels( ) → void
applyOverlay( ) → void
releaseEverything( ) → void
Fire `released` for everything held, so nothing sticks across a switch.
use(name: string, opts: any?) → any
| arg | type | description |
|---|---|---|
| name | string | |
| opts | any? |
schemeInfo( ) → any
ensure( ) → void
keyHeld(self: any, code: string) → boolean
| arg | type | description |
|---|---|---|
| self | any | |
| code | string |
anyKey(self: any, list: any) → boolean
| arg | type | description |
|---|---|---|
| self | any | |
| list | any |
anyPad(list: any, slot: number?) → boolean
| arg | type | description |
|---|---|---|
| list | any | |
| slot | number? |
mouseLogical( ) → void
readKeys(a: string, kind: string, k: any, dt: number) → any
One action's value from keyboard + mouse.
| arg | type | description |
|---|---|---|
| a | string | |
| kind | string | |
| k | any | |
| dt | number |
readPad(kind: string, p: any, dt: number) → any
One action's value from the pad.
| arg | type | description |
|---|---|---|
| kind | string | |
| p | any | |
| dt | number |
noteDevice( ) → void
emit(action: string, edge: string, value: any) → void
| arg | type | description |
|---|---|---|
| action | string | |
| edge | string | |
| value | any |
emitGesture(kind: string, ev: any) → void
| arg | type | description |
|---|---|---|
| kind | string | |
| ev | any |
handleGestures( ) → void
tick(dt: number) → void
| arg | type | description |
|---|---|---|
| dt | number |
pollCapture( ) → void
onRawKey(ev: any, gpe: boolean) → void
| arg | type | description |
|---|---|---|
| ev | any | |
| gpe | boolean |
removeHooks( ) → void
installHooks( ) → void
q(kind: string) → void
| arg | type | description |
|---|---|---|
| kind | string |
framePresses( ) → void
Key and mouse-button presses are read straight off the frame's event list rather than subscribed to: a subscription is bound to the context that made it and quietly stops answering when that context ends, a frame read has no owner to lose.
ensureKitMap(on: boolean) → void
| arg | type | description |
|---|---|---|
| on | boolean |
step(dt: number) → void
| arg | type | description |
|---|---|---|
| dt | number |
startSystem( ) → void
controller(n: number, filter: any?) → any
| arg | type | description |
|---|---|---|
| n | number | |
| filter | any? |
actionSpec(self: any, action: string) → any
| arg | type | description |
|---|---|---|
| self | any | |
| action | string |
value(action: string) → any
An action's current value: 0/1 for buttons, -1..1 for axes, {x,y} for sticks and deltas.
| arg | type | description |
|---|---|---|
| action | string |
held(action: string) → boolean
| arg | type | description |
|---|---|---|
| action | string |
pressed(action: string) → boolean
| arg | type | description |
|---|---|---|
| action | string |
released(action: string) → boolean
| arg | type | description |
|---|---|---|
| action | string |
charge(action: string) → number
| arg | type | description |
|---|---|---|
| action | string |
lastCharge(action: string) → number
| arg | type | description |
|---|---|---|
| action | string |
point(action: string) → any
| arg | type | description |
|---|---|---|
| action | string |
on(action: string, fn: (any, string) → void
| arg | type | description |
|---|---|---|
| action | string | |
| fn | (any, string |
off(handle: number) → boolean
| arg | type | description |
|---|---|---|
| handle | number |
onGesture(kind: string, fn: (any) → void
| arg | type | description |
|---|---|---|
| kind | string | |
| fn | (any |
drive(action: string, value: any) → void
| arg | type | description |
|---|---|---|
| action | string | |
| value | any |
setStick(variant: string, side: string?) → boolean
| arg | type | description |
|---|---|---|
| variant | string | |
| side | string? |
setButtons(layout: string) → boolean
| arg | type | description |
|---|---|---|
| layout | string |
setSkin(name: string) → void
| arg | type | description |
|---|---|---|
| name | string |
setVisibility(mode: string) → void
| arg | type | description |
|---|---|---|
| mode | string |
setScale(s: number) → void
| arg | type | description |
|---|---|---|
| s | number |
setAimOrigin(x: number?, y: number?) → void
| arg | type | description |
|---|---|---|
| x | number? | |
| y | number? |
device( ) → string
setPromptStyle(style: string) → void
| arg | type | description |
|---|---|---|
| style | string |
setPromptFamily(family: string) → void
| arg | type | description |
|---|---|---|
| family | string |
currentFamily( ) → string
keyCodes(kind: string, k: any) → void
| arg | type | description |
|---|---|---|
| kind | string | |
| k | any |
padCodes(kind: string, p: any) → void
| arg | type | description |
|---|---|---|
| kind | string | |
| p | any |
prompt(action: string, family: string?) → any
What to show for an action on the device the player is holding: { family, style, codes, label }. family is keyboard, xbox, playstation, switch, generic or touch.
| arg | type | description |
|---|---|---|
| action | string | |
| family | string? |
promptWidget(action: string, size: number?, id: string?) → any
A canvas node drawing the action's prompt glyph(s), `size` points tall.
| arg | type | description |
|---|---|---|
| action | string | |
| size | number? | |
| id | string? |
partList(kind: string) → void
| arg | type | description |
|---|---|---|
| kind | string |
slotLists(b: any, kind: string, part: string) → void
The editable key list and pad list behind one (action, part).
| arg | type | description |
|---|---|---|
| b | any | |
| kind | string | |
| part | string |
bindingSlots( ) → void
Every rebindable row of the active scheme, in a stable order: { action, label, kind, part, keys = {codes}, pad = {codes}?, padFixed = string? }.
rebind(action: string, part: string, device: string, index: number, code: string?) → boolean
Bind `code` to one slot (index 1 or 2) of an action part on a device ("keys" or "pad"). nil clears the slot. Returns true on success.
| arg | type | description |
|---|---|---|
| action | string | |
| part | string | |
| device | string | |
| index | number | |
| code | string? |
uses(device: string) → void
Every (code -> users) use on one device, including the implied d-pad and trigger inputs, so a clash with them is caught too.
| arg | type | description |
|---|---|---|
| device | string |
add(code: string?, action: string, part: string) → void
| arg | type | description |
|---|---|---|
| code | string? | |
| action | string | |
| part | string |
conflicts( ) → void
Every input bound to more than one action: { device, code, uses = {{action, part}} }.
resetBindings( ) → void
exportBindings( ) → any
importBindings(data: any) → boolean
| arg | type | description |
|---|---|---|
| data | any |
captureNext(device: string, fn: (string?) → void
Wait for the next key / mouse button ("keys") or pad button ("pad") and hand its code to `fn`; Escape cancels with nil. Game input is muted while capturing.
| arg | type | description |
|---|---|---|
| device | string | |
| fn | (string? |
cancelCapture( ) → void
isCapturing( ) → boolean
stop( ) → void
player(n: number?, filter: any?) → any
The controller for local player `n` (1 = keyboard + mouse, the first pad and touch). `filter` = { keyboard?, mouse?, pad? = slot|"any"|false, touch? }.
| arg | type | description |
|---|---|---|
| n | number? | |
| filter | any? |
p1( ) → any
use(name: string, opts: any?) → any return p1
Switch player 1 to a scheme. opts = { skin, stick, stickSide, buttons, visibility, scale, promptStyle, takeOver }. Returns the scheme's info.
| arg | type | description |
|---|---|---|
| name | string | |
| opts | any? |
examples
Controls.use("twinStick", { skin = "scifi" })scheme( ) → any return p1
The active scheme: { name, label, description, actions, pointerLock }.
schemes( ) → void
Every scheme's name, in catalogue order.
describe(name: string) → any
Label, description and actions of any scheme, active or not.
| arg | type | description |
|---|---|---|
| name | string |
styles( ) → any
Everything a game can pick from, by category.
capabilities( ) → any
What the running engine can and cannot do for the kit.
value(a: string) → any return p1
| arg | type | description |
|---|---|---|
| a | string |
held(a: string) → boolean return p1
| arg | type | description |
|---|---|---|
| a | string |
pressed(a: string) → boolean return p1
| arg | type | description |
|---|---|---|
| a | string |
released(a: string) → boolean return p1
| arg | type | description |
|---|---|---|
| a | string |
charge(a: string) → number return p1
| arg | type | description |
|---|---|---|
| a | string |
lastCharge(a: string) → number return p1
| arg | type | description |
|---|---|---|
| a | string |
point(a: string) → any return p1
| arg | type | description |
|---|---|---|
| a | string |
on(a: string, fn: (any, string) → void
| arg | type | description |
|---|---|---|
| a | string | |
| fn | (any, string |
off(h: number) → boolean return p1
| arg | type | description |
|---|---|---|
| h | number |
onGesture(kind: string, fn: (any) → void
| arg | type | description |
|---|---|---|
| kind | string | |
| fn | (any |
drive(a: string, v: any) → void
| arg | type | description |
|---|---|---|
| a | string | |
| v | any |
device( ) → string return p1
setStick(variant: string, side: string?) → boolean return p1
| arg | type | description |
|---|---|---|
| variant | string | |
| side | string? |
setButtons(layout: string) → boolean return p1
| arg | type | description |
|---|---|---|
| layout | string |
setSkin(name: string) → void
| arg | type | description |
|---|---|---|
| name | string |
setVisibility(mode: string) → void
| arg | type | description |
|---|---|---|
| mode | string |
setScale(s: number) → void
| arg | type | description |
|---|---|---|
| s | number |
setAimOrigin(x: number?, y: number?) → void
| arg | type | description |
|---|---|---|
| x | number? | |
| y | number? |
setPromptStyle(s: string) → void
| arg | type | description |
|---|---|---|
| s | string |
setPromptFamily(f: string) → void
| arg | type | description |
|---|---|---|
| f | string |
prompt(a: string, family: string?) → any return p1
| arg | type | description |
|---|---|---|
| a | string | |
| family | string? |
promptWidget(a: string, size: number?, id: string?) → any return p1
| arg | type | description |
|---|---|---|
| a | string | |
| size | number? | |
| id | string? |
bindingSlots( ) → void
rebind(a: string, part: string, device: string, index: number, code: string?) → boolean return p1
| arg | type | description |
|---|---|---|
| a | string | |
| part | string | |
| device | string | |
| index | number | |
| code | string? |
conflicts( ) → void
resetBindings( ) → void
exportBindings( ) → any return p1
importBindings(d: any) → boolean return p1
| arg | type | description |
|---|---|---|
| d | any |
captureNext(device: string, fn: (string?) → void
| arg | type | description |
|---|---|---|
| device | string | |
| fn | (string? |
cancelCapture( ) → void
isCapturing( ) → boolean return p1
stop( ) → void
Stop every controller, take the touch controls down and hand the default controls back.
_step(dt: number) → void
Advance the kit by hand (tests and headless tools). Normal play
| arg | type | description |
|---|---|---|
| dt | number |
Sub-parts
Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.
Showing up to 3 levels deep. Open a part to see what it holds further down.
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
agent_score is exposed.+ quality × 0.35
+ performance × 0.25
± compat factor
Usability ratings
Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".
Scoped to this part · feeds back into the world's score.