DriftScript
Documentation

Reference

drift/*

Every capability this host binds, with its effects and whether it is deterministic.

What this host contributes to the language: 327 capabilities across 23 modules, each carrying the effect it has. A different host would supply its own prefix for its own capabilities and inherit the standard library unchanged. This page is generated from the same registry the linker reads, so a newly bound module appears here without anybody editing it.

drift/2d 12

sprite scene.write

fn(batch: SpriteBatch, texture: i32, x: f32, y: f32, w: f32, h: f32) -> void

Put one quad in the batch, covering the whole of a texture.

tinted scene.write

fn(batch: SpriteBatch, texture: i32, x: f32, y: f32, w: f32, h: f32, r: f32, g: f32, b: f32, a: f32) -> void

The same, multiplied by a colour picked for the screen: sRGB, 0 to 1, decoded to linear as a tint on a node is, with alpha kept as given. White is the identity, so a white texture draws exactly this colour — which is how a solid rectangle is drawn.

frame scene.write

fn(batch: SpriteBatch, sheet: SpriteSheet, frame: i32, x: f32, y: f32, w: f32, h: f32) -> void

Put one frame of a sheet in the batch. A frame the sheet does not have draws the whole sheet, which is unmistakable.

named scene.readdeterministic

fn(sheet: SpriteSheet, name: String) -> i32

The index a name has in a sheet, or -1. Ask once and keep the number: a name lookup is a hash and a frame is an array read.

frames scene.readdeterministic

fn(sheet: SpriteSheet) -> i32

How many frames the sheet was cut into.

tilemap scene.write

fn(batch: SpriteBatch, map: Tilemap, sheet: SpriteSheet, x: f32, y: f32, w: f32, h: f32) -> i32

Draw the tiles a view rectangle can see, and answer how many that was. The cost is the view rather than the map.

tile scene.readdeterministic

fn(map: Tilemap, column: i32, row: i32) -> i32

The frame in a cell, or -1 for an empty one — including for a cell outside the map, which answers empty rather than another row.

setTile scene.write

fn(map: Tilemap, column: i32, row: i32, tile: i32) -> void

Put a frame in a cell. A cell outside the map is ignored rather than wrapping into another row.

columns scene.readdeterministic

fn(map: Tilemap) -> i32

How wide the map is, in cells.

rows scene.readdeterministic

fn(map: Tilemap) -> i32

How tall the map is, in cells.

count scene.readdeterministic

fn(batch: SpriteBatch) -> i32

How many quads are in the batch this frame.

dropped scene.readdeterministic

fn(batch: SpriteBatch) -> i32

How many quads did not fit this frame. Zero is the only good value; anything else is a batch that wants a bigger capacity.

drift/ai 9

agent puredeterministic

fn(id: String) -> Agent?

Resolve an agent by the id the consumer registered it under. Absent when there is none.

wake ai

fn(agent: Agent, reason: String, priority: i32) -> void

Tell an agent something happened. Returns immediately; the agent acts at its next tick.

consider ai

fn(agent: Agent) -> void

Ask an agent to think, at ordinary priority. Returns immediately.

intentId puredeterministic

fn(agent: Agent) -> String

What the agent is doing now. Empty before its first tick.

degraded puredeterministic

fn(agent: Agent) -> bool

Whether the agent is over budget and running on its policy floor alone.

reachable navigation.readdeterministic

fn(agent: Agent, x: float, y: float, z: float) -> bool

Whether a route exists from where this agent is to a point, without writing one.

path navigation.readdeterministic

fn(agent: Agent) -> NavPath?

The route object this agent follows, for `drift/navigation` to read or steer along.

deciding network.readdeterministic

fn(agent: Agent) -> bool

Whether this peer decides this agent’s model intents. Elsewhere they arrive already taken.

drift/animation 17

pose puredeterministic

fn(jointCount: u32) -> Pose

A new pose at rest. This is where a bind pose comes from; take one and keep it.

toRest animation.write

fn(pose: Pose, jointCount: u32) -> void

Return a pose to rest without allocating another, which is what a state machine does on re-entry.

sample animation.write

fn(clip: Clip, at: f32, into: Pose) -> void

Sample a clip at a time. A channel no track mentions is left as it was, so a rotation-only clip preserves the rest of the pose.

blend animation.write

fn(a: Pose, b: Pose, amount: f32, into: Pose) -> void

Blend two poses into a third, clamped at the ends. Safe when `into` is also `a` or `b`. It interpolates every channel, so `into` decides what an untouched joint blends from.

blendSet animation.write

fn(tree: Blend, parameter: String, value: f32) -> void

Set one of a tree's parameters. A name no node in that tree declares is refused by name, because a typo that silently did nothing would present as an animation that will not respond. Both kinds of parameter are set this way: a blend weight, and a clock — the time a `clip` node named for its own sampling.

blendAt animation.write

fn(tree: Blend, at: f32, into: Pose) -> void

Evaluate a whole tree into a pose. `at` is the clock for every node that did not name one of its own, so a tree of ordinary clips is sampled at one time and a node with a clock reads that parameter instead.

reach animation.write

fn(skeleton: Skeleton, pose: Pose, root: u32, mid: u32, tip: u32, targetX: f32, targetY: f32, targetZ: f32, poleX: f32, poleY: f32, poleZ: f32) -> bool

Bend a two-bone chain so its tip reaches a target. Answers whether it was reachable; an unreachable target straightens the chain toward it rather than giving up.

motion puredeterministic

fn() -> Motion

A new root displacement, at zero. Take one and keep it; nothing here allocates per frame.

rootMotion animation.write

fn(clip: Clip, joint: u32, from: f32, to: f32, into: Motion) -> void

How far the root travelled between two times, in its own frame at `from`. Loops are accumulated, so a clip that wraps between the two times still answers a step forward. Pair every call with `stripRoot` or the character moves twice.

stripRoot animation.write

fn(clip: Clip, joint: u32, pose: Pose) -> void

Pin a sampled pose's root to the clip's value at time zero, so the displacement `rootMotion` handed you is not also in the pose. Every other joint is left as it was.

motionX puredeterministic

fn(motion: Motion) -> f32

The displacement along the root's own x axis at the earlier time.

motionY puredeterministic

fn(motion: Motion) -> f32

The displacement along the root's own y axis at the earlier time.

motionZ puredeterministic

fn(motion: Motion) -> f32

The displacement along the root's own z axis at the earlier time.

motionTurnX puredeterministic

fn(motion: Motion) -> f32

The x part of the rotation the root turned through, as a quaternion.

motionTurnY puredeterministic

fn(motion: Motion) -> f32

The y part of the rotation the root turned through, as a quaternion.

motionTurnZ puredeterministic

fn(motion: Motion) -> f32

The z part of the rotation the root turned through, as a quaternion.

motionTurnW puredeterministic

fn(motion: Motion) -> f32

The w part of the rotation the root turned through, as a quaternion. One means it did not turn.

drift/audio 9

sound puredeterministic

fn(slot: String) -> Sound?

Resolve a sound slot. Absent when nothing was registered or nothing decoded.

play audio.write

fn(sound: Sound, gain: f32) -> void

Play a resolved sound through the mix.

playPanned audio.write

fn(sound: Sound, gain: f32, pan: f32) -> void

Play a resolved sound at a stereo position, -1 left to 1 right.

distanceGain puredeterministic

fn(distance: f32, radius: f32) -> f32

How loud something is at a distance, falling off to nothing at the radius.

stereoPan puredeterministic

fn(dx: f32, dz: f32, yaw: f32) -> f32

Where something sits in the stereo field, relative to a listener facing yaw.

duck audio.write

fn(bus: String, factor: f32, seconds: f32) -> bool

Take a bus down to factor of its fader over seconds, 1 to bring it back, leaving the fader where the player set it. False when the mix has no bus of that name.

fade audio.write

fn(bus: String, level: f32, seconds: f32) -> bool

Move a bus's fader to level over seconds. For a bus the game made: the music and effects faders are the player's, and duck is how a script goes over them. False when the mix has no bus of that name.

recall audio.write

fn(snapshot: String, seconds: f32) -> bool

Crossfade every level, mute and send to a snapshot the host captured, over seconds. False when nothing was captured under that name.

pulse nondeterministic

fn() -> f32

How hard the music is kicking, 0 to 1, spiking on each kick and falling back. 0 when the host runs no kick detector.

drift/behavior 8

tick behavior.write

fn(behavior: Behavior) -> TreeStatus

Advance the routine one tick, and answer whether it failed, finished or is still going. Does nothing while paused.

step behavior.write

fn(behavior: Behavior) -> TreeStatus

Advance one tick even while paused, which is what a step button is.

restart behavior.write

fn(behavior: Behavior) -> void

Forget where the routine had got to, so the next tick starts it from the top.

setPaused behavior.write

fn(behavior: Behavior, paused: bool) -> void

Hold this one agent while the world carries on.

paused behavior.readdeterministic

fn(behavior: Behavior) -> bool

Whether it is being held.

status behavior.readdeterministic

fn(behavior: Behavior) -> TreeStatus

What the last tick answered, without ticking again.

doing behavior.readdeterministic

fn(behavior: Behavior, node: String) -> bool

Whether the agent is currently inside a node of this name — the routine's own answer, not a copy of it.

depth behavior.readdeterministic

fn(behavior: Behavior) -> i32

How deep in the tree the last tick reached. For a debug readout.

drift/camera 2

snap scene.write

fn(camera: Camera) -> void

Jump the camera to where it is heading, skipping the ease. What a scene cut needs.

shotAge scene.readdeterministic

fn(camera: Camera) -> f32

Seconds since the current shot began. A read, so a deterministic function may ask.

drift/chemistry 53

substance chemistry.readdeterministic

fn(chem: Chemistry, id: String) -> Substance

A registered material by id, such as `oak`. Refuses in words naming what the world has.

species chemistry.readdeterministic

fn(chem: Chemistry, id: String) -> Species

A registered species by id, such as `O2`. Refuses in words if the world has no such species.

parcelCount chemistry.readdeterministic

fn(chem: Chemistry) -> i32

How many parcel handles have ever been issued, live or not.

parcelAt chemistry.readdeterministic

fn(chem: Chemistry, index: i32) -> i32

The handle at an index, for iteration. Check `alive` before reading it.

alive chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> bool

Whether a parcel still exists.

substanceOf chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> Substance

What material a parcel is made of.

temperature chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

K, averaged over the whole parcel.

surfaceTemperature chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

K at the outermost shell — the one that decides whether it catches.

coreTemperature chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

K at the innermost shell — the one that decides whether it is cooked.

mass chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

How much of it there is, in kilograms. Falls as it burns.

speciesMass chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32, species: Species) -> f32

kg of one species held anywhere in this parcel.

moisture chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

kg of water per kg of dry matter — the dry basis, which is how moisture content is quoted. Under 0.25 will burn; over 0.35 will not.

charFraction chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

Share of the parcel that is now carbon, 0 to 1.

charDepth chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

Metres of char measured inward from the surface.

wetness chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

kg of liquid water on the surface, per square metre of it.

wettable chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> bool

Whether this material can hold liquid water, which is what `wet` asks. Rain over everything asks first, since `wet` refuses an iron nail.

phase chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> MatterPhase

Whether the parcel is solid, liquid, gas or mixed. Mixed is a real answer: wet wood is a solid and a liquid at once.

burning chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> bool

Whether a flame stands over it.

smouldering chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> bool

Whether it is glowing with no flame. A smoulder survives air a flame cannot, which is why smothering leaves embers.

heatRelease chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

kW the reactions released last tick. A fire's size is its heat release rate, not its temperature. Negative while a surface is gasifying, which is correct.

ignitionProgress chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

How close to catching, 0 to 1: the least satisfied of the five criteria. A readout — nothing branches on it.

structuralIntegrity chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

How much is still load-bearing, 1 down to 0, as char eats the thickness. This package breaks nothing; it reports.

massFlux chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

kg/(m²·s) of gas leaving the surface — the smoke.

fuelFlux chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

The combustible share of that, which is what ignition is measured against.

positionX chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

Where the consumer said this parcel is.

positionY chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

Where the consumer said this parcel is.

positionZ chemistry.readdeterministic

fn(chem: Chemistry, parcel: i32) -> f32

Where the consumer said this parcel is.

ambientTemperature chemistry.readdeterministic

fn(chem: Chemistry, x: f32, y: f32, z: f32) -> f32

K of the air at a point.

oxygenFraction chemistry.readdeterministic

fn(chem: Chemistry, x: f32, y: f32, z: f32) -> f32

Volume fraction of oxygen. Air is 0.209; a flame stops near 0.14 and a smoulder near 0.05.

humidity chemistry.readdeterministic

fn(chem: Chemistry, x: f32, y: f32, z: f32) -> f32

Relative humidity, 0 to 1. Nothing dries in fog because the vapour pressure deficit is zero.

pressure chemistry.readdeterministic

fn(chem: Chemistry, x: f32, y: f32, z: f32) -> f32

Pascals. Rises where the air is heated and confined, which is what an explosion event reports on.

concentration chemistry.readdeterministic

fn(chem: Chemistry, species: Species, x: f32, y: f32, z: f32) -> f32

Parts per million by volume. The reading a game acts on — carbon monoxide is the one that kills.

smokeDensity chemistry.readdeterministic

fn(chem: Chemistry, x: f32, y: f32, z: f32) -> f32

Extinction coefficient, 1/m: what to attenuate a light along a ray by.

visibility chemistry.readdeterministic

fn(chem: Chemistry, x: f32, y: f32, z: f32) -> f32

How far you can see, metres. Clamped at ten kilometres.

place chemistry.writedeterministic

fn(chem: Chemistry, substance: Substance, kilograms: f32, area: f32, x: f32, y: f32, z: f32) -> i32

Put a new parcel in the world. `area` is the exposed surface in m², and it is required rather than defaulted: a characteristic depth is volume over area, so a parcel with no area has no depth.

destroy chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32) -> void

Remove a parcel. Its handle is never reused.

move chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32, x: f32, y: f32, z: f32) -> void

Where it is. The consumer owns position; this package only reads it to work out what reaches it.

addHeat chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32, joules: f32) -> void

Joules into the surface shell, which is what a flux from outside does.

addHeatDeep chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32, shell: i32, joules: f32) -> void

Joules into a named shell. The difference from `addHeat` is a microwave and an oven.

setTemperature chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32, kelvin: f32) -> void

Set every shell to a temperature. **For authoring and tests, not for a tick** — it discards whatever enthalpy was there rather than accounting for it.

wet chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32, kilograms: f32) -> void

Pour water on it: real liquid water into the surface shell, where boiling will find it. Refuses, naming the material, where that material holds no water.

dry chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32, kilograms: f32) -> void

Take surface water away: a cloth, a hot dry pan, or wind.

ignite chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32) -> void

Supply a pilot for one tick. **This does not start a fire** — it satisfies one of five criteria, so holding a match to wet wood does nothing.

douse chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32) -> void

Remove the pilot and the flame. Embers survive, which is the point of it.

addSpecies chemistry.writedeterministic

fn(chem: Chemistry, parcel: i32, species: Species, kilograms: f32) -> void

Salt the water, oil the pan, poison the well.

mix chemistry.writedeterministic

fn(chem: Chemistry, from: i32, into: i32) -> void

Pour one parcel into another; the first is consumed. Both must be the same material — a mixture of two is a third material, authored as one.

release chemistry.writedeterministic

fn(chem: Chemistry, species: Species, kilograms: f32, x: f32, y: f32, z: f32) -> void

A gas release into the air: a leak, a vent, an extinguisher.

addAirHeat chemistry.writedeterministic

fn(chem: Chemistry, joules: f32, x: f32, y: f32, z: f32) -> void

Joules into a cell of air, which is what a heater does and what a fire does to the room.

eventCount chemistry.readdeterministic

fn(chem: Chemistry) -> i32

Events this tick. Cleared at the top of every one.

eventKind chemistry.readdeterministic

fn(chem: Chemistry, index: i32) -> ChemistryEvent

What happened in one of this tick’s events. An index outside `eventCount` is refused, naming both.

eventParcel chemistry.readdeterministic

fn(chem: Chemistry, index: i32) -> i32

Which parcel it happened to.

eventSpecies chemistry.readdeterministic

fn(chem: Chemistry, index: i32) -> i32

Which species, or -1 where the kind does not name one.

eventValue chemistry.readdeterministic

fn(chem: Chemistry, index: i32) -> f32

The kind's own quantity.

drift/ecs 17

create ecs.write

fn(world: World) -> Entity

A fresh entity with nothing on it. The handle is exact; do not put one in an `f32`.

destroy ecs.write

fn(world: World, entity: Entity) -> bool

Remove an entity and every component it had. False when the handle was already stale.

alive ecs.readdeterministic

fn(world: World, entity: Entity) -> bool

Whether this handle still names a live entity. A handle to something destroyed is false, even after its slot is reused.

has ecs.readdeterministic

fn(world: World, entity: Entity, component: String) -> bool

Whether an entity carries a component.

attach ecs.write

fn(world: World, entity: Entity, component: String) -> void

Give an entity a component, every field at the zero for its type. Set them with `write`.

detach ecs.write

fn(world: World, entity: Entity, component: String) -> bool

Take a component away. False when it did not have one.

read ecs.readdeterministic

fn(world: World, entity: Entity, component: String, field: String) -> f64

One numeric field. Reading a field of a component an entity does not have is 0.

write ecs.write

fn(world: World, entity: Entity, component: String, field: String, value: f64) -> void

Set one numeric field.

count ecs.readdeterministic

fn(world: World, component: String) -> u32

How many entities carry a component.

at ecs.readdeterministic

fn(world: World, component: String, index: u32) -> Entity

The nth entity carrying a component. **The order is insertion modified by swap-removal**, so a walk that removes should count downwards — removing moves the last entity into a position already passed.

findNearest ecs.readdeterministic

fn(world: World, component: String, fieldX: String, fieldY: String, fieldZ: String, x: float, y: float, z: float, radius: float) -> bool

Whether any entity carrying a component has position fields putting it within a radius, and the search `nearest` then reads. **A linear scan of that component's column, not an index** — the entity model keeps no spatial structure, so this costs one pass over everything carrying the component. Position is read from three fields you name, so nothing here knows what a transform is called.

nearest ecs.readdeterministic

fn(world: World) -> Entity

The entity the last `findNearest` on this world found. **Valid only until the next one**, and meaningless when that answered false — the same lifetime a raycast hit has.

instantiate ecs.write

fn(world: World, prefab: String) -> Entity

Make an entity from a prefab, with every component it names. Overrides are the host’s to apply; a script that wants a different value writes it after.

query ecs.readdeterministic

fn(world: World, a: String, b: String, c: String, d: String) -> Cursor

Open a walk over everything carrying these components. The cursor is borrowed from the world’s pool; ending the walk gives it back.

without ecs.readdeterministic

fn(cursor: Cursor, component: String) -> void

Narrow an open walk to entities that do **not** carry a component.

view ecs.readdeterministic

fn(world: World, component: String, forWriting: bool) -> View

A component’s live columns. `forWriting` decides which of a system’s declarations is checked — a loop that only reads takes a readable view, and asking for more than the system declared is refused.

drift/editor 43

translateMode editor

fn(gizmo: Gizmo) -> void

Make this an arrow gizmo, which moves what it is on.

rotateMode editor

fn(gizmo: Gizmo) -> void

Make this a ring gizmo, which turns what it is on.

scaleMode editor

fn(gizmo: Gizmo) -> void

Make this a scale gizmo. Scale is always in the object’s own axes, whatever the space says, because a non-uniform scale along a world axis would shear it.

gizmoMode editor

fn(gizmo: Gizmo) -> GizmoMode

Which of the three the gizmo is: translate, rotate or scale.

worldSpace editor

fn(gizmo: Gizmo) -> void

Point the handles along the world axes.

localSpace editor

fn(gizmo: Gizmo) -> void

Point the handles along the object’s own axes.

space editor

fn(gizmo: Gizmo) -> GizmoSpace

Which the handles are pointing along: the world or the object.

size editor

fn(gizmo: Gizmo) -> f32

How big the gizmo is in metres. The host keeps this the same on screen as the camera moves.

setSize editor

fn(gizmo: Gizmo, metres: f32) -> void

Set how big the gizmo is in metres. Non-positive draws nothing and picks nothing rather than failing.

hovered editor

fn(gizmo: Gizmo) -> GizmoHandle

What the pointer is over: `None`, or a handle such as `TranslateX`, `TranslateYZ`, `RotateY` or `ScaleUniform`.

dragging editor

fn(gizmo: Gizmo) -> bool

Whether a drag is running.

dragAngle editor

fn(gizmo: Gizmo) -> f32

How far a rotation drag has turned, in radians, signed and past a full turn if it went that far. Zero when the drag is not a rotation. This is what to snap or clamp; the rotation itself cannot tell a three-quarter turn from a quarter turn back.

positionX editor

fn(gizmo: Gizmo) -> f32

Where the thing being edited is, along x.

positionY editor

fn(gizmo: Gizmo) -> f32

The same, along y.

positionZ editor

fn(gizmo: Gizmo) -> f32

The same, along z.

setPosition editor

fn(gizmo: Gizmo, x: f32, y: f32, z: f32) -> void

Put the gizmo, and the transform it is editing, somewhere. A drag that is running is not interrupted, so do this between drags.

scaleX editor

fn(gizmo: Gizmo) -> f32

How much the thing being edited is scaled, along x.

scaleY editor

fn(gizmo: Gizmo) -> f32

The same, along y.

scaleZ editor

fn(gizmo: Gizmo) -> f32

The same, along z.

rotationX editor

fn(gizmo: Gizmo) -> f32

The orientation being edited, as a quaternion: x.

rotationY editor

fn(gizmo: Gizmo) -> f32

The same: y.

rotationZ editor

fn(gizmo: Gizmo) -> f32

The same: z.

rotationW editor

fn(gizmo: Gizmo) -> f32

The same: w. Identity is (0, 0, 0, 1).

mode editor

fn(editor: Editor) -> EditorMode

What the editor is doing: editing, playing or paused.

playing editor

fn(editor: Editor) -> bool

Whether the world is advancing. False while paused and while editing.

play editor

fn(editor: Editor) -> bool

Start playing, taking a snapshot of the world first so `stop` can put it back. Resuming from paused does not re-snapshot. False when no world is bound to snapshot.

pause editor

fn(editor: Editor) -> void

Hold the world where it is. The frame keeps drawing.

step editor

fn(editor: Editor) -> void

Advance exactly one fixed tick, then hold. Does nothing while editing, where there is nothing to step.

stop editor

fn(editor: Editor) -> bool

Leave play and put the world back as it was. Every entity handle changes, so a selection is re-found by its place in the snapshot and one that play created is dropped. False when there was nothing to put back.

rowCount editor

fn(editor: Editor) -> i32

How many rows the tree showed at its last rebuild.

rebuildTree editor

fn(editor: Editor, root: Node) -> void

Walk a node and everything under it into rows, honouring which branches are collapsed.

rowName editor

fn(editor: Editor, row: i32) -> String

What the node on a row is called, or "" for a row that does not exist.

rowDepth editor

fn(editor: Editor, row: i32) -> i32

How deep a row sits, with the root at zero. Minus one for a row that does not exist.

rowExpanded editor

fn(editor: Editor, row: i32) -> bool

Whether a row is showing its children. Meaningless for a row with none.

toggleRow editor

fn(editor: Editor, row: i32) -> void

Open a closed row or close an open one. Call `rebuildTree` afterwards to see it.

selectRow editor

fn(editor: Editor, row: i32) -> void

Select the node on a row, which points the gizmo at it. A row that does not exist selects nothing.

selectedRow editor

fn(editor: Editor) -> i32

Which row is selected, or minus one.

fieldCount editor

fn(editor: Editor) -> i32

How many fields the inspector is showing.

fieldLabel editor

fn(editor: Editor, field: i32) -> String

A field’s name as it was declared, or "" for a field that does not exist.

fieldGroup editor

fn(editor: Editor, field: i32) -> String

What a field belongs to: a component’s name, or "transform" for a node.

fieldKind editor

fn(editor: Editor, field: i32) -> FieldKind

How to show a field: a number, an integer, a boolean, text, an entity or an enum. Taken from the declared type, because a read cannot tell them apart. A field outside `fieldCount` is refused, naming both.

fieldNumber editor

fn(editor: Editor, field: i32) -> f32

A field’s value as a number. Zero for a field that is not one, and for one that does not exist.

setFieldNumber editor

fn(editor: Editor, field: i32, value: f32) -> bool

Write a number into a field. False where the field does not exist or will not take one.

drift/events 3

push puredeterministic

fn(queue: Queue, id: String, priority: f32, holdFor: f32) -> void

Queue a message by identity. A repeat of the same id inside the dedupe window is dropped.

current puredeterministic

fn(queue: Queue) -> String?

The id of the message showing now, if any. The queue carries identity and priority; the words are the consumer's.

clear puredeterministic

fn(queue: Queue) -> void

Drop everything queued.

drift/input 14

down input.read

fn(actions: Actions, action: String) -> bool

Whether an action is held.

pressed input.read

fn(actions: Actions, action: String) -> bool

Whether an action went down this frame.

axisX input.read

fn(actions: Actions, action: String) -> f32

A directional action's horizontal component, shortened to the rim with the vertical one so a keyboard diagonal is not faster than a straight line. For two independent controls such as throttle and steering, read rawAxisX instead.

axisY input.read

fn(actions: Actions, action: String) -> f32

A directional action's vertical component, shortened to the rim with the horizontal one. For two independent controls, read rawAxisY instead.

rawAxisX input.read

fn(actions: Actions, action: String) -> f32

An action's horizontal axis on its own, not shortened against the vertical one. This is what a throttle or a steering input wants: holding two keys gives a full 1 on each.

rawAxisY input.read

fn(actions: Actions, action: String) -> f32

An action's vertical axis on its own, not shortened against the horizontal one.

canRumble host

fn(actions: Actions) -> bool

Whether the pad these actions read has motors this browser can drive. Grey the control out when it is false; most pads on most browsers cannot.

rumble host

fn(actions: Actions, durationMs: f32, strong: f32, weak: f32) -> bool

Rumble for a duration in milliseconds, at two magnitudes in [0, 1]: `strong` is the low-frequency motor and `weak` the high-frequency one. Answers whether the platform took it; false is a real answer, not an error.

stopRumble host

fn(actions: Actions) -> bool

Stop whatever that pad is playing. Answers whether the platform took it.

touchX input.read

fn(touch: Touch) -> f32

The touch stick's horizontal, -1 to 1, 0 while no thumb is on it.

touchY input.read

fn(touch: Touch) -> f32

The touch stick's vertical, -1 to 1, up negative as a gamepad stick's is.

touchHeld input.read

fn(touch: Touch) -> bool

Whether a thumb is held still on the action side of the screen: the held form of the primary.

touchTap input.read

fn(touch: Touch) -> bool

Whether the action side was tapped since this was last asked. True once per tap, so ask it once a tick.

touchSlide input.read

fn(touch: Touch) -> bool

Whether a downward flick on the action side is being held: the secondary, a slide or a crouch.

drift/navigation 12

nearest navigation.readdeterministic

fn(graph: NavGraph, x: float, y: float, z: float) -> i32

The node nearest a place, or -1 where the graph has none. How an agent gets onto the network.

nearestWithin navigation.readdeterministic

fn(graph: NavGraph, x: float, y: float, z: float, maxDistance: float) -> i32

The nearest node within a distance, or -1. Use it so an agent that has walked off the network is not snapped to the far side of the map.

route navigation.writedeterministic

fn(path: NavPath, graph: NavGraph, fromX: float, fromY: float, fromZ: float, toX: float, toY: float, toZ: float) -> bool

Path from one place to another, storing the route. False where there is no way through, which is an answer and not a failure.

routeBetween navigation.writedeterministic

fn(path: NavPath, graph: NavGraph, from: i32, to: i32) -> bool

The same, between two nodes you already have. For a consumer with their own spatial index.

path navigation.readdeterministic

fn(agent: Entity) -> NavPath

The route this agent is following, kept by the host between steps. Empty until something routes it, and empty again if the agent's handle is reused.

clear navigation.writedeterministic

fn(path: NavPath) -> void

Forget the route. The walker is then arrived, wherever it is.

following navigation.readdeterministic

fn(path: NavPath) -> bool

Whether there is a route to follow.

steerX navigation.readdeterministic

fn(path: NavPath, x: float, y: float, z: float) -> float

Where a walker at this place should aim, along x. A point ahead on the path rather than the next node, so corners are cut smoothly instead of snapped at.

steerY navigation.readdeterministic

fn(path: NavPath, x: float, y: float, z: float) -> float

The same aim point, along y.

steerZ navigation.readdeterministic

fn(path: NavPath, x: float, y: float, z: float) -> float

The same aim point, along z.

remaining navigation.readdeterministic

fn(path: NavPath, x: float, y: float, z: float) -> float

How far is left, following the path rather than as the crow flies.

arrived navigation.readdeterministic

fn(path: NavPath, x: float, y: float, z: float) -> bool

Whether the walker is there. True with no route at all, so one check covers both.

drift/network 9

self network.readdeterministic

fn(session: Session) -> i32

Which participant this peer is. Fixed for the life of the session, which is why a deterministic system may read it.

authority network.readdeterministic

fn(session: Session) -> bool

Whether this peer’s world is the authoritative one. Fixed when the session is created.

participants nondeterministic

fn(session: Session) -> i32

How many participants the session holds. Nondeterministic because somebody may join or leave between two runs of the same recording.

confirmed nondeterministic

fn(session: Session) -> i32

The highest tick every participant’s input has arrived for, or -1. Moves with packet timing, so a deterministic system may not branch on it.

halted nondeterministic

fn(session: Session) -> bool

Whether the session has stopped, because an input arrived too late to apply or two peers computed different worlds.

haltReason nondeterministic

fn(session: Session) -> String

Why it halted, as a sentence, or an empty string. Names the tick a divergence began at.

slots nondeterministic

fn(session: Session) -> i32

How many replicated scalars each participant has. A consumer sizes this when the session is made.

replicated nondeterministic

fn(session: Session, participant: i32, slot: i32) -> f32

Read a participant’s published scalar. An index out of range answers zero rather than failing, because a frame loop has nothing to do with a refusal.

replicate network.write

fn(session: Session, slot: i32, value: f32) -> void

Publish a value in one of this peer’s slots. Not callable from a deterministic system: a replay re-runs one and a send is not idempotent.

drift/persistence 5

read persistence.read

fn(store: Store, key: String) -> String?

What is stored under a key. Absent when nothing is, which is ordinary rather than exceptional.

write persistence.write

fn(store: Store, key: String, value: String) -> void

Store a value under a key.

remove persistence.write

fn(store: Store, key: String) -> void

Forget a key.

saveStatus persistence.read

fn(store: Store) -> SaveStatus

Whether writes have landed: idle, pending, saving or failed. A store that writes synchronously is always idle, which is the true answer rather than a stub.

pendingSaves persistence.read

fn(store: Store) -> u32

How many keys are waiting to reach the backend. Zero for a store that writes synchronously.

drift/physics 42

colliderCount physics.readdeterministic

fn(colliders: Colliders) -> u32

How many colliders a set holds.

colliderCapacity physics.readdeterministic

fn(colliders: Colliders) -> u32

How many slots the set has allocated, live or not. Equal to `colliderCount` until a group is removed; after that the live colliders are sparse within it.

colliderBytes physics.readdeterministic

fn(colliders: Colliders) -> u32

What the set costs in memory, in bytes. The slots and shapes are exact; the spatial index includes an estimate of per-object overhead a JavaScript engine does not expose.

beginColliderGroup physics.write

fn(colliders: Colliders) -> void

Open a group. Add boxes with `addColliderBox`, then `endColliderGroup` to put them in and get the handle back.

addColliderBox physics.write

fn(colliders: Colliders, cx: f32, cy: f32, cz: f32, hx: f32, hy: f32, hz: f32) -> void

A box in the open group, by centre and half-extents — the same numbers a mesh builder takes, so nothing is authored twice. Nothing is queryable until `endColliderGroup`.

endColliderGroup physics.write

fn(colliders: Colliders) -> u32

Put the open group into the set and return the handle that drops it again. Keep the handle: it is the only way to remove those colliders.

removeColliderGroup physics.write

fn(colliders: Colliders, group: u32) -> void

Drop a group and everything in it. Refuses a handle the set does not hold, and refuses the colliders the set was constructed with — a set meant to stream is constructed empty.

anyWithin physics.readdeterministic

fn(colliders: Colliders, x: f32, y: f32, z: f32, radius: f32) -> bool

Whether any collider overlaps the *box* around a sphere. The cheapest answer there is, and it over-reports a collider that only reaches the box corners. `nearestWithin` measures the sphere.

nearestWithin physics.readdeterministic

fn(colliders: Colliders, x: f32, y: f32, z: f32, radius: f32) -> bool

Find the closest collider within a radius and record it. Read the result with the `near` functions. Valid until the next `nearestWithin` on this set.

nearCollider physics.readdeterministic

fn(colliders: Colliders) -> i32

The collider the last `nearestWithin` on this set found, or −1.

nearX physics.readdeterministic

fn(colliders: Colliders) -> f32

The closest point on that collider’s bounds, along x — the point on the wall rather than the wall’s centre.

nearY physics.readdeterministic

fn(colliders: Colliders) -> f32

The closest point on that collider’s bounds, along y.

nearZ physics.readdeterministic

fn(colliders: Colliders) -> f32

The closest point on that collider’s bounds, along z.

nearDistance physics.readdeterministic

fn(colliders: Colliders) -> f32

How far that collider’s bounds are, in metres. Zero when the query point is inside them.

bodyCount physics.readdeterministic

fn(world: PhysicsWorld) -> i32

How many bodies the world holds.

bodyX physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> f32

A body's world position along x.

bodyY physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> f32

A body's world position along y.

bodyZ physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> f32

A body's world position along z.

bodyVelX physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> f32

A body's velocity along x, in metres per second.

bodyVelY physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> f32

A body's velocity along y, in metres per second.

bodyVelZ physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> f32

A body's velocity along z, in metres per second.

bodyMass physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> f32

A body's mass in kilograms, or zero where it has none because it is static or kinematic.

sleeping physics.readdeterministic

fn(world: PhysicsWorld, body: i32) -> bool

Whether a body has been still long enough to stop being solved.

raycast physics.readdeterministic

fn(world: PhysicsWorld, x: f32, y: f32, z: f32, dx: f32, dy: f32, dz: f32, maxDistance: f32, mask: i32) -> bool

Cast a ray and record what it hit. `mask` is required: without one the first thing a ray finds is often the body it started inside. Read the result with the `hit` functions.

hitBody physics.readdeterministic

fn(world: PhysicsWorld) -> i32

The body the last `raycast` on this world found, or −1. Valid until the next raycast.

hitX physics.readdeterministic

fn(world: PhysicsWorld) -> f32

Where the last raycast struck, along x. Valid until the next raycast.

hitY physics.readdeterministic

fn(world: PhysicsWorld) -> f32

Where the last raycast struck, along y. Valid until the next raycast.

hitZ physics.readdeterministic

fn(world: PhysicsWorld) -> f32

Where the last raycast struck, along z. Valid until the next raycast.

hitNormalX physics.readdeterministic

fn(world: PhysicsWorld) -> f32

The surface normal the last raycast struck, along x.

hitNormalY physics.readdeterministic

fn(world: PhysicsWorld) -> f32

The surface normal the last raycast struck, along y.

hitNormalZ physics.readdeterministic

fn(world: PhysicsWorld) -> f32

The surface normal the last raycast struck, along z.

hitFraction physics.readdeterministic

fn(world: PhysicsWorld) -> f32

How far along the ray the last hit was, from 0 to 1.

contactCount physics.readdeterministic

fn(world: PhysicsWorld) -> i32

How many contact events the last step produced. Drain them after stepping, never during.

contactKind physics.readdeterministic

fn(world: PhysicsWorld, index: i32) -> ContactKind

An event's kind: the two bodies began touching, are still touching, or have parted.

contactA physics.readdeterministic

fn(world: PhysicsWorld, index: i32) -> i32

The lower-indexed body of a contact event.

contactB physics.readdeterministic

fn(world: PhysicsWorld, index: i32) -> i32

The higher-indexed body of a contact event.

applyImpulse physics.write

fn(world: PhysicsWorld, body: i32, px: f32, py: f32, pz: f32, atX: f32, atY: f32, atZ: f32) -> void

Apply an impulse at a world point. The point is required: through the centre of mass an impulse produces no rotation at all, which reads as a broken impulse rather than a missing argument.

applyForce physics.write

fn(world: PhysicsWorld, body: i32, fx: f32, fy: f32, fz: f32, dt: f32, atX: f32, atY: f32, atZ: f32) -> void

A force applied for one step, which is an impulse of force times dt. The point is required for the same reason.

setVelocity physics.write

fn(world: PhysicsWorld, body: i32, vx: f32, vy: f32, vz: f32) -> void

Set a body's velocity outright, waking its island.

setPosition physics.write

fn(world: PhysicsWorld, body: i32, x: f32, y: f32, z: f32) -> void

Move a body outright. A teleport rather than a push: the broadphase moves with it.

wake physics.write

fn(world: PhysicsWorld, body: i32) -> void

Wake a body and everything sharing its island, because a sleeping neighbour would settle it again.

setGravity physics.write

fn(world: PhysicsWorld, x: f32, y: f32, z: f32) -> void

The world's gravity, in metres per second squared.

drift/random 3

unit puredeterministic

fn(seed: u32) -> f32

A value from 0 to 1 for a seed. The same seed always gives the same value.

range puredeterministic

fn(seed: u32, low: f32, high: f32) -> f32

A value between two bounds for a seed.

index puredeterministic

fn(seed: u32, count: u32) -> u32

An index into a collection of `count` items. Zero for an empty one.

drift/render 10

bloom scene.write

fn(renderer: Renderer, scale: f32) -> void

How much of the frame's bloom ceiling to take, 0 to 1. Held until changed. Does nothing when the quality profile's `bloom` is 0, because the chain is never built.

bloomAbove scene.write

fn(renderer: Renderer, scale: f32, threshold: f32) -> void

How much of the bloom ceiling to take, 0 to 1, and how bright a pixel must be before it blooms, in scene units, above 0. Both held until changed. The threshold is compared before exposure, so a script that moves `exposure` through a day moves this with it: pass the brightness wanted on screen over the exposure, or sunlit stone blooms at noon and lamps never do at night.

exposure scene.write

fn(renderer: Renderer, stops: f32) -> void

How far this frame is scaled into the tone curve, above 0. Replaces the profile's `outputExposure` for this frame onward. Adaptation is yours: a game knows it walked into a cave, and the renderer could only find out a frame late. Ignored where the output transform is `none` or `srgb`, since there is then no curve to be exposed into.

filmic scene.write

fn(renderer: Renderer, slope: f32, toe: f32, shoulder: f32, blackClip: f32, whiteClip: f32) -> void

The `filmic` output transform's curve, held until changed: the straight segment's slope through mid grey, how much of the curve the toe and the shoulder take (0 to 1), and how far black and white clip past their ends (0 to 1). The engine defaults are 0.88, 0.55, 0.26, 0 and 0.04. Mid grey stays mid grey whatever they are. A number out of range is clamped into it. Ignored unless the quality profile's output transform is `filmic`.

motionBlur scene.write

fn(renderer: Renderer, scale: f32) -> void

How much of the camera motion blur ceiling this frame takes, 0 to 1. Held until changed. Ramp it with whatever "fast" means here: blur that is always on stops being a speed cue within seconds and costs eight taps a moving pixel while doing so.

speedBlur scene.write

fn(renderer: Renderer, strength: f32) -> void

How much speed blur the frame resolves with, 0 to 1. Held until changed, and ignored when screen effects are off.

focus scene.write

fn(renderer: Renderer, distance: f32, range: f32, scale: f32) -> void

Where this frame's lens is focused and how deep the sharp zone is, in metres, and how much of the depth-of-field ceiling to take, 0 to 1. Held until changed. `scale` is required here though the engine defaults it to 1, because taking the whole ceiling is the expensive answer and a script author is further from that cost than a TypeScript caller.

occlusionFade scene.write

fn(renderer: Renderer, distance: f32, radius: f32) -> void

Where ambient occlusion fades out with distance: whole up to `distance` metres from the eye and gone `radius` metres past it, so far scenery and a distant sky are not shaded in rings that follow the depth buffer. A negative distance is no fade, the default. Held until changed. Does nothing when the quality profile's `ambientOcclusion` is 0.

medium scene.write

fn(renderer: Renderer, density: f32, albedo: f32, anisotropy: f32, maxDistance: f32) -> void

How thick the air is: a medium filling the whole frustum, rather than a beam inside a hull. `density` is extinction per metre and 0 is off — nothing is allocated and nothing is drawn, so a script that never raises it costs nothing. `albedo` is how much of what the air takes out comes back as light rather than heat, 0 to 1; `anisotropy` is -1 back to 1 forward, and is what makes haze glow toward a low sun; `maxDistance` is where the search for light to scatter stops, in metres, which is not where the fog stops. Held until changed. Does nothing when the quality profile's `globalMediumSteps` is 0, because no march is built.

veil scene.write

fn(renderer: Renderer, red: f32, green: f32, blue: f32, alpha: f32) -> void

Composite a flat colour over the finished frame, for a cut dipping to white or to black. **Once per frame: a frame that does not call this draws with no veil at all**, unlike the dials above, because a transition that forgets to turn itself off is worse than one that forgets to turn on.

drift/rollback 6

tick nondeterministic

fn(rewind: Rewind) -> i32

The last tick that was stepped, or -1 before the first.

isReplaying nondeterministic

fn(rewind: Rewind) -> bool

Whether this tick is being re-run to correct a mispredicted one. Anything that should not happen twice — a sound, a particle, a message — asks this first.

depth nondeterministic

fn(rewind: Rewind) -> i32

How many ticks back a rewind can reach. Eight at 60 Hz is 133 milliseconds of correction.

earliest nondeterministic

fn(rewind: Rewind) -> i32

The oldest tick still retained, or -1. An input older than this cannot be applied and the session cannot be made correct.

replays nondeterministic

fn(rewind: Rewind) -> i32

How many rewinds have happened. A session correcting constantly has a link problem.

replayedTicks nondeterministic

fn(rewind: Rewind) -> i32

How many ticks those rewinds re-ran in total. Divided by `replays`, the average depth of a correction.

drift/scene 11

positionX scene.readdeterministic

fn(node: Node) -> f32

A node's local x.

positionY scene.readdeterministic

fn(node: Node) -> f32

A node's local y.

positionZ scene.readdeterministic

fn(node: Node) -> f32

A node's local z.

setPosition scene.write

fn(node: Node, x: f32, y: f32, z: f32) -> void

Move a node, marking it and its subtree for a world update.

setScale scene.write

fn(node: Node, x: f32, y: f32, z: f32) -> void

Scale a node.

setRotation scene.write

fn(node: Node, x: f32, y: f32, z: f32, radians: f32) -> void

Rotate a node about an axis.

windDirectionX scene.readdeterministic

fn(wind: Wind) -> f32

The prevailing wind's x, normalised; zero when there is no wind to have a direction.

windDirectionZ scene.readdeterministic

fn(wind: Wind) -> f32

The prevailing wind's z, normalised; zero when there is no wind to have a direction.

windSpeed scene.readdeterministic

fn(wind: Wind) -> f32

How hard it is blowing, metres a second, never negative.

windGust scene.readdeterministic

fn(wind: Wind) -> f32

The gust alone, -1 to 1, for a behaviour that wants the deviation and not the total.

distance scene.readdeterministic

fn(a: Node, b: Node) -> f32

The distance between two nodes, in local space.

drift/terrain 8

heightAt physics.readdeterministic

fn(terrain: Terrain, x: float, z: float) -> float

How high the ground is at a place, in metres. The surface that is drawn, not an approximation of it, so a thing put here stands on what you can see.

normalX physics.readdeterministic

fn(terrain: Terrain, x: float, z: float) -> float

Which way the ground faces at a place, along x.

normalY physics.readdeterministic

fn(terrain: Terrain, x: float, z: float) -> float

The same, along y. One on the flat and smaller on a slope.

normalZ physics.readdeterministic

fn(terrain: Terrain, x: float, z: float) -> float

The same, along z.

slopeAt physics.readdeterministic

fn(terrain: Terrain, x: float, z: float) -> float

How steep the ground is at a place, in radians from flat. Zero on the level; a quarter turn on a wall.

covers physics.readdeterministic

fn(terrain: Terrain, x: float, z: float) -> bool

Whether a place is over the field at all. A query outside it answers the nearest edge rather than nothing, so ask this first where it matters.

extentX physics.readdeterministic

fn(terrain: Terrain) -> f32

How far the field reaches along x, in metres.

extentZ physics.readdeterministic

fn(terrain: Terrain) -> f32

How far the field reaches along z, in metres.

drift/time 4

fixedDelta clock.read

fn() -> f32

The fixed simulation step, in seconds. Prefer the `dt` your function was given.

frameDelta clock.read

fn() -> f32

Seconds since the previous rendered frame, after clamping.

wallDelta clock.read

fn() -> f32

Seconds of real time since the previous frame, unclamped. Outside the boundary in every sense.

elapsed clock.read

fn() -> f32

Seconds since the loop started.

drift/ui 18

layout scene.write

fn(tree: UiTree, x: f32, y: f32, w: f32, h: f32) -> void

Lay the tree out into a box. The box is what is available: a tree sized by its contents comes to what its contents come to.

draw scene.write

fn(tree: UiTree, batch: SpriteBatch, white: i32) -> i32

Put the tree in a batch and answer how many quads that was. `white` is the sprite pass's own white slot, which is what a background is drawn on.

has scene.readdeterministic

fn(tree: UiTree, name: String) -> bool

Whether the tree holds a node of this name. Every reader below answers a defined value without it, so this is for a script that wants to know rather than one that would crash.

left scene.readdeterministic

fn(tree: UiTree, name: String) -> f32

Where a node ended up, along x. Zero for a name the tree does not hold.

top scene.readdeterministic

fn(tree: UiTree, name: String) -> f32

The same, along y.

width scene.readdeterministic

fn(tree: UiTree, name: String) -> f32

How wide a node ended up.

height scene.readdeterministic

fn(tree: UiTree, name: String) -> f32

How tall a node ended up.

visible scene.readdeterministic

fn(tree: UiTree, name: String) -> bool

Whether a node is shown. A hidden node is out of the layout and out of the hit test, not merely invisible.

show scene.write

fn(tree: UiTree, name: String, visible: bool) -> void

Show or hide a node and everything under it.

setText scene.write

fn(tree: UiTree, name: String, text: String) -> void

Change what a node says. What draws it is the caller's: this package draws quads, and core already draws two kinds of text.

tint scene.write

fn(tree: UiTree, name: String, r: f32, g: f32, b: f32, a: f32) -> void

Change a node's background colour, given as picked for the screen: sRGB, 0 to 1, decoded here to the linear light the renderer draws, as a theme's hex token is. Alpha is coverage and is kept as given. A node with no background gets one.

hovered input.read

fn(tree: UiTree, name: String) -> bool

Whether the pointer is over a node.

pressed input.read

fn(tree: UiTree, name: String) -> bool

Whether the pointer went down on a node and has not come up.

focused input.read

fn(tree: UiTree, name: String) -> bool

Whether a node has the keyboard.

point input.readscene.write

fn(tree: UiTree, x: f32, y: f32, down: bool) -> bool

Route the pointer, and answer whether this call activated anything. An activation is a press and a release on the same node, so somebody who pressed the wrong button can slide off it.

activated input.read

fn(tree: UiTree, name: String) -> bool

Whether the last `point` activated this node. Read it in the same step that called `point`; the next one clears it.

key input.readscene.write

fn(tree: UiTree, key: String, shift: bool) -> bool

Route a key, and answer whether it activated what has focus. Tab moves focus, Enter and space activate, and everything else is reported unhandled so the caller can have it.

focus scene.write

fn(tree: UiTree, name: String) -> void

Give a node the keyboard. A name the tree does not hold focuses nothing.

drift/xr 12

presenting scene.read

fn() -> bool

Whether a session is running. False before one starts and after the user takes the headset off.

supported scene.read

fn() -> bool

Whether this device could present at all. False on a machine with no headset attached.

headX input.read

fn() -> f32

Where the viewer’s head is, in metres. Zero outside a session.

headY input.read

fn() -> f32

Where the viewer’s head is, in metres. Zero outside a session.

headZ input.read

fn() -> f32

Where the viewer’s head is, in metres. Zero outside a session.

trigger input.read

fn(hand: Hand) -> f32

How far a hand’s trigger is pulled, 0 to 1. Zero for a hand that is not there.

squeeze input.read

fn(hand: Hand) -> f32

How far a hand’s grip is squeezed, 0 to 1. Zero for a hand that is not there.

holding input.read

fn(hand: Hand) -> bool

Whether a hand is tracked this frame. False while a controller is set down or out of view.

jointX input.read

fn(hand: Hand, joint: HandJoint) -> f32

Where a hand joint is, in metres. Zero for a joint that is not tracked.

jointY input.read

fn(hand: Hand, joint: HandJoint) -> f32

Where a hand joint is, in metres. Zero for a joint that is not tracked.

jointZ input.read

fn(hand: Hand, joint: HandJoint) -> f32

Where a hand joint is, in metres. Zero for a joint that is not tracked.

pinching input.read

fn(hand: Hand) -> bool

Whether a hand’s thumb and index tips are close enough to count as a pinch.