Log inGet started
·
preset · drop-in viewer
asset⌬ presetpresetprimary: preset.yaml·part ofpackage characterController.package·originates fromworld 07158574-5…

synty_full

Locomotion speeds and all 87 in-place Synty Polygon Masculine clips for the `LocomotionFull` component: idle, walk/run/sprint/crouch direction variants, shuffle, turn, in-air, and start/stop transitions.

byzero-proxy @ DESKTOP-DB3UJOJ·posted 2mo ago
What it does

synty_full

Locomotion speeds and all 87 in-place Synty Polygon Masculine clips for the LocomotionFull component: idle, walk/run/sprint/crouch direction variants, shuffle, turn, in-air, and start/stop transitions.

preset.apply("synty_full", { entity = id, component = "LocomotionFull" })

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

This asset doesn't declare a schema or structured payload.
⌬ Metadata
titleSynty Full Locomotion

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

494items
·
other · born here
▤file
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
◇
component · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
animation · born here
❒asset
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
❒
package · born here
❒asset
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
zanim · born here
▤file
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
▣
module · born here
❒asset
# AnimGraph DAG of animation nodes implemented in pure Luau. Nodes are stored in a slot vector; freed slots are reused on the next `addNode` (mirrors the legacy Rust crate's `Vec<Option<AnimNode>>` pattern). An AnimGraph has exactly one designated "output" node. Each frame the engine calls `graph:update(dt)` followed by `graph:evaluate()`, which recursively walks reachable nodes and returns the pose buffer for the output node. The module re-exports the Node hierarchy on the returned table so callers can reach `AnimGraph.Clip.new(...)`, `AnimGraph.Mixer.new(...)`, etc. without separate requires. ## Exports - `AnimGraph.new(opts: { layout: Layout? }?) -> AnimGraph` — construct a new graph; `layout` defaults to a sensible default. - `AnimGraph:addNode(node: Node) -> number` — insert a node, return its slot id (reuses freed slots). - `AnimGraph:removeNode(id: number)` — free the node at slot `id` and call `:destroy()` on it. - `AnimGraph:setOutput(id: number)` — designate which node is the graph's final output. - `AnimGraph:update(dt: number)` — advance every reachable node. - `AnimGraph:evaluate() -> TypedBuffer?` — return the output node's pose buffer (caller MUST NOT destroy). - `AnimGraph:crossfade(from: number, to: number, duration: number)` — sugar that wires a temporary Mixer between two nodes, ramps weights over `duration`, then collapses to the new output when the ramp completes. - `AnimGraph.Clip`, `AnimGraph.Mixer`, `AnimGraph.BlendSpace2D`, `AnimGraph.Node` — re-exports of the node constructors. Types: - `Layout = { ... }` — pose layout used by the graph and its nodes. ## Usage ```luau local AnimGraph = require("@builtin::systems.anim.AnimGraph") local graph = AnimGraph.new({ layout = myLayout }) local idle = graph:addNode(AnimGraph.Clip.new("idle")) local walk = graph:addNode(AnimGraph.Clip.new("walk")) graph:setOutput(idle) graph:crossfade(idle, walk, 0.25) -- blend to walk over 250ms -- Each frame: graph:update(dt) local pose = graph:evaluate() ``` ## Notes - The output node MUST be set before `evaluate` is called; otherwise the return value is `nil`. - `crossfade` collapses the temporary mixer when the ramp completes, so long-running graphs don't accumulate orphan mixers. - Buffer ownership: nodes own their internal buffers and free them in `:destroy()`. Callers of `evaluate` borrow the returned buffer — do NOT destroy it. - `removeNode` frees the slot id and calls `:destroy()` on the node; the next `addNode` may reuse the same id.
▲ 0↑ born
◇
component · born here
❒asset
# Camera Manages viewport priority, render-to-texture, and capture. State is stored in the native `Camera` ECS component; the Rust camera system handles render scheduling and render targets. Public fields: `fov`, `near`, `far`, `priority`, `textureHandle` (the guid of the texture the camera renders into; empty = main viewport), `renderLayers` (which render layers this camera draws — a space-separated spec of names, e.g. `"all"`, `"all !ui"`, or `"default sky"`; `ui`/`sky`/`debug`/`EditorUI` are built-in layers), `postProcessing` (whether this camera runs the post-process chain), `debugChannel`, plus the behavior slot below. Methods: `:lookAt(target)` (entity id string OR `{x, y, z}` table), `:render()`, `:capture()`, `:setTargetTexture(tex?)` (a `renderer.texture.create` handle to render into, or nil for the viewport). ```luau entity(id).component.add("Camera", { fov = 90, priority = 10 }) entity(id).component.get("Camera"):capture() ``` The scene's play-mode camera is reached as `layers.active.camera`, a handle that reads and writes the fields above on whichever entity currently carries them. `layers.active.camera.entity` is the entity ref for that camera and `layers.active.camera.entityId` its id string, so a script that needs to attach something to the camera — an `AudioListener`, a child entity — goes through the ref: ```luau local cam = layers.active.camera cam.fov = 70 -- the camera's settings cam.entity.component.add("AudioListener") -- the entity carrying them ``` ## How the camera moves: `behavior` and `follow` A `Camera` does not move itself. `behavior` names a component that does, and setting it attaches that component to this entity. Clearing it detaches whatever was attached. ```luau local cam = entity(id).component.get("Camera") cam.behavior = asset.ref("@builtin::controller.orbital_follow", "component") cam.follow = playerBody ``` `follow` is the standard slot every shipped behavior reads. Set the follow target on the **Camera**, not on the behavior, so swapping behaviors keeps it. A behavior that finds its own `follow` field empty falls back to this one, which is what lets a rig keep tracking the player across a behavior swap. `followResolves` answers whether that slot names an entity that is live — `true` while it names a live one or names nothing at all, `false` once the target is despawned or the id names no entity. A rig whose target does not resolve holds its last pose, and this is the field that tells it from a rig posed correctly on a subject that has not moved. `camera.get` carries the same value beside `follow`, and a write naming an id with no entity behind it draws a warning where it lands. ```luau cam.followResolves -- false once the followed entity is gone tools.use("camera", "get", id).followResolves -- the same answer off the tool ``` The shipped behaviors live under `@builtin::controller.*`: `orbital_follow`, `third_person_follow`, `first_person`, `free`, `orbit`, `chase`, `isometric`, `rts`, `birds_eye`, `side_scroller`, `cinematic`, `menu`. ## Writing your own Any component can be a camera behavior. Write one that moves its own entity and attach it the same way: ```luau cam.behavior = asset.ref("MyChaseCam", "component") ``` `follow` lives on the Camera, so a behavior gets no property notification of its own when the target changes. Declare `onFollowChanged(newFollow, oldFollow)` to be told the moment it does — the Camera calls it on the component it attached, which is what lets a rig re-pose on the new subject at once. A behavior that reads `Camera.follow` on its own schedule declares nothing and is attached the same way. ```luau typed function public:onFollowChanged(newFollow: any, oldFollow: any) -- pose this entity against the new target end ``` To make it appear in the discovery catalog alongside the shipped ones, declare the `cameraBehavior` tag in the component's `.metadata`: ```json { "tags": ["cameraBehavior"] } ``` The tag governs **discovery**, not attachment. A tagged component is listed by `layers.active.camera.behaviors` and is what tooling offers when something asks "which camera behaviors exist"; an untagged component attaches just as well and simply stays out of that list. Tag the ones you want other people (and agents) to find. ```luau for name, ref in pairs(layers.active.camera.behaviors) do print(name, ref.identity) end ``` ## Texture colour space `textureColorSpace = "display"` applies the display transform when rendering into a texture. `"linear"` writes scene-linear values instead. `postProcessing` independently controls the effects chain in either mode. Floating-point targets retain values above one; normalized targets clamp to their representable range. The main viewport uses display encoding.
▲ 0↑ born
◇
component · born here
❒asset
# MovementState Component that exposes movement state for controller-driven animation and gameplay consumers.
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
rig · born here
❒asset
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
▣
module · born here
❒asset
# Node Base class for AnimGraph nodes. Subclasses (`Clip`, `Mixer`, `BlendSpace2D`) typically wrap `setmetatable(Node.new(), <Subclass>)` and then set subclass-specific fields before overriding the three lifecycle methods. ## Exports - `Node.new() -> Node` — allocate a bare Node table (no Channels, no buffer). - `Node:update(dt: number)` — advance internal state (clip playhead, weight ramps, …). Default is a no-op; subclasses override. - `Node:evaluate() -> TypedBuffer?` — produce a pose buffer. Caller MUST NOT destroy. Default returns `nil`; subclasses override. - `Node:destroy()` — free owned Channel/buffer/Layout handles. Default is a no-op; subclasses override. Types: - `Node = { kind: string? }` ## Usage ```luau local Node = require("@builtin::systems.anim.AnimGraph.Node") -- Subclassing pattern: local MyNode = setmetatable({}, { __index = Node }) MyNode.__index = MyNode MyNode.kind = "MyNode" function MyNode.new() local self = setmetatable(Node.new(), MyNode) -- subclass-specific fields return self end function MyNode:update(dt) ... end function MyNode:evaluate() ... end function MyNode:destroy() ... end ``` ## Notes - `Node` is the base. Subclasses live next door under `AnimGraph.module/Node.module/` (`Clip`, `Mixer`, `BlendSpace2D`). - Override semantics: default `update` / `evaluate` / `destroy` are safe no-ops, so subclasses that only need one of them can leave the rest at the base implementation. - Buffer ownership: the buffer returned by `evaluate` is owned by the node and must NOT be destroyed by the caller.
▲ 0↑ born
▣
module · born here
❒asset
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
▣
module · born here
❒asset
# BlendSpace2D 2D-coordinate-driven mix of N sample nodes (Node subclass). Each sample is anchored at a `(x, y)` coordinate; the current parameter `(px, py)` lands inside one of the Delaunay triangles formed over the anchors, and barycentric weights for that triangle drive a Mixer-style weighted blend. Parameter outside the hull → nearest sample with weight 1. ## Exports - `BlendSpace2D.new(layout: Layout, samples: { Sample }) -> BlendSpace2D` — construct a BlendSpace2D with N anchored sample nodes. Triangulation runs once at construction. - `BlendSpace2D:setParams(x: number, y: number)` — set the parameter that drives the per-frame blend. - `BlendSpace2D:update(dt: number)` — cascade `update(dt)` to every sample source. - `BlendSpace2D:evaluate() -> TypedBuffer` — compute weights and blend. Caller must NOT destroy the returned buffer. - `BlendSpace2D:destroy()` — destroy the internal Mixer and clear state. Sample sources are not owned and not destroyed. Types: - `Layout = { boneOrder: { string }, stride: number?, slotLayout: { any }? }` - `Sample = { x: number, y: number, source: any }` ## Usage ```luau local BlendSpace2D = require("@builtin::systems.anim.AnimGraph.Node.BlendSpace2D") local bs = BlendSpace2D.new(layout, { { x = 0, y = 0, source = idleClip }, { x = 1, y = 0, source = walkFwd }, { x = 1, y = 1, source = runFwd }, }) bs:setParams(0.5, 0.0) bs:update(dt) local pose = bs:evaluate() ``` ## Notes - Triangulation is a brute-force O(n⁴) Delaunay check. Animation blend-spaces are tiny (n ≤ 20 in practice) so the cost is < 1ms in Luau at construction; runtime cost is just triangle containment plus one Mixer evaluate per frame. - Internal Mixer is owned by the BlendSpace2D and destroyed on `destroy()`. Sample sources are owned by the surrounding `AnimGraph`, not the BlendSpace2D. - When the parameter is outside the triangulated hull, the closest sample (by squared XY distance) gets weight 1 and the rest weight 0 — there is no extrapolation.
▲ 0↑ born
▣
module · born here
❒asset
# Clip Single animation clip wrapper (Node subclass). Wraps one `Channel` per animation channel in the asset, plus a pose buffer and a playhead. `evaluate()` samples every channel at the current time into the buffer. The pose buffer is initialised to rest pose (`translation = 0`, `rotation = identity quat`, `scale = 1`) at construction. Each `evaluate()` overwrites only the slots authored by channels; unauthored slots stay at rest pose. This means a Mixer slerping two clips that don't author rotations produces identity, not `(0,0,0,0)`. ## Exports - `Clip.new(animAsset: AnimAsset, layout: Layout, looping: boolean, speed: number?) -> Clip` — construct a Clip from an animation asset. - `Clip:update(dt: number)` — advance the playhead. Wraps when `looping`, clamps + finishes otherwise. - `Clip:evaluate() -> TypedBuffer` — sample every channel into the pose buffer and return it. Caller must NOT destroy. - `Clip:setPlaying(p: boolean)` — pause/resume the playhead. - `Clip:rewind()` — rewind to t=0, clear `finished`, resume. - `Clip:destroy()` — free every Channel handle and the pose buffer. Types: - `Layout = { boneOrder: { string }, stride: number? }` - `AnimChannel = { target_bone: string, path: string, times: { number }, values: { number }, interp: string? }` - `AnimAsset = { duration: number?, channels: { AnimChannel }? }` ## Usage ```luau local Clip = require("@builtin::systems.anim.AnimGraph.Node.Clip") local clip = Clip.new(asset, layout, true, 1.0) clip:update(dt) local pose = clip:evaluate() ``` ## Notes - The Clip owns its pose buffer and all `Channel` handles. `destroy()` is required to release them — Lua's GC does not free engine resources. - Only channels with a known `path` (`translation` / `rotation` / `scale`) and a `target_bone` present in `layout.boneOrder` are wired up; others are silently dropped. - Looping uses modulo wrap. Non-looping clips clamp to `duration` and set `finished = true`, `playing = false`.
▲ 0↑ born
▣
module · born here
❒asset
▲ 0↑ born
▣
module · born here
❒asset
# Mixer N-input weighted-blend Node subclass. Combines N source nodes into a single pose buffer via `Blend.weightedInto` using a slot layout (translation lerp + rotation slerp + scale lerp by default). Inputs with non-positive weights are skipped at evaluate time. ## Exports - `Mixer.new(layout: Layout, inputs: { MixerInput }) -> Mixer` — construct a Mixer with N weighted inputs. Allocates an output pose buffer. - `Mixer:setWeight(i: number, w: number)` — update an input's weight (no-op if `i` is out of range). - `Mixer:update(dt: number)` — cascade `update(dt)` to every input source. - `Mixer:evaluate() -> TypedBuffer` — blend inputs into the output buffer and return it. Caller must NOT destroy. - `Mixer:destroy()` — free the output buffer and blend layout. Does not destroy child sources. Types: - `Layout = { boneOrder: { string }, stride: number?, slotLayout: { any }? }` - `MixerInput = { source: any, weight: number }` ## Usage ```luau local Mixer = require("@builtin::systems.anim.AnimGraph.Node.Mixer") local mix = Mixer.new(layout, { { source = clipA, weight = 1.0 }, { source = clipB, weight = 0.0 }, }) mix:setWeight(2, 0.5) mix:update(dt) local pose = mix:evaluate() ``` ## Notes - The mixer owns its output buffer and `Blend.layout` handle. Child source nodes are owned by the surrounding `AnimGraph`, not the Mixer — `Mixer:destroy()` does not recurse into them. - Default slot layout assumes a 10-stride bone record: `translation.xyz` (lerp), `rotation.xyzw` (slerp), `scale.xyz` (lerp). Override via `layout.slotLayout`. - Inputs with `weight <= 0` are silently skipped — there is no error for "no active input"; the output buffer is zeroed instead.
▲ 0↑ born
▣
module · born here
❒asset
# `retarget` module `require("modules.retarget")` — skeletal animation retargeting in readable Luau. Map a clip authored on one humanoid rig onto another, preserving the target's shape. This is the runtime retarget path; the behaviour lives here, in Luau, so an agent can follow and tweak it. (`__retarget.oracleBake` is the Rust numerical oracle this is validated against, not the runtime path.) ## How it works Each `.rig` carries a **profile** — a canonical-role → bone map (the driver). Retarget is two steps: 1. **Bone map** — source bone → its role → the target bone filling that role. Roles are the shared vocabulary, so any two rigs interoperate through their profiles without a per-pair mapping. 2. **Shape-preserving transfer** — the target keeps its own bone lengths and rest orientations; the animation contributes only delta-from-rest motion. Rotations are bind-pose-corrected (the target reproduces the source's world-space motion relative to its own rest). Translation is re-expressed in the target parent's frame and size-scaled, then applied RELATIVE to the target's bind: every bone starts at the target's own offset and the clip adds its displacement from rest on top — a bone with no translation motion stays put (proportions preserved), while a bone that moves (the hips' vertical bob, the root's stride) carries that motion across, size-scaled to the target. Retarget is **cold**: `bake` once per (clip, target rig) and cache; the hot path just samples the baked clip, exactly like a native one. ## Surface - `parseRig(rig)` → enriched rig. Accepts a parsed `.rig` table, a `.rig` JSON string, or an already-parsed rig (idempotent). - `plan(srcRig, tgtRig)` → `{ mapped, unmappedSource, unmappedTarget, … }` — which roles map across the rigs, and which don't (the diagnostic). - `bake(clip, srcRig, tgtRig)` → a decoded clip table in the target's bone space. `clip` is a decoded clip (`{ name, duration, channels, bone_names }`). - `bakeBytes(clipBytes, srcRig, tgtRig, cacheKey?)` → retargeted clip `zanim` bytes, with an in-memory cache keyed by `cacheKey`. - `loadRig(ref)` → parsed rig from a `.rig` asset. - `clearCache(cacheKey?)` → drop cached bakes (call after editing a rig profile). ## Example ```lua local retarget = require("modules.retarget") local src = retarget.loadRig(asset.ref("synty_character", "rig")) local tgt = retarget.loadRig(asset.ref("hero", "rig")) -- inspect the mapping local plan = retarget.plan(src, tgt) print(plan.mapped.leftarm.source, "->", plan.mapped.leftarm.target) -- bake a walk clip onto the hero rig (cold, cached), then sample it like any clip local walkBytes = vfs.read(asset.source("walk", "animation") .. "/data.zanim") local walkOnHero = retarget.bakeBytes(walkBytes, src, tgt, "walk|hero") local bind = skeleton.bindClip(walkOnHero, heroBoneOrder) ```
▲ 0↑ born
▣
module · born here
❒asset
# environment Module Environment / reflection capture — bake the scene into reflection-probe cube slots from world positions, persist them as `faces6` `.texture` assets, set per-probe blend data so surfaces reflect the probes covering them, and capture the sky into its own slot as the fallback under them. Public Luau surface over the `__environment` Internal FFI namespace, auto-injected as `_G.environment` via the prelude. ## Purpose The generic "render the scene into a cubemap from a point" capability the reflection-probe system is built on. Captures are queued for the render system (which owns the live scene); `captureSlotToAsset` additionally yields a few frames while the GPU readback completes. Persisted cubes are `faces6` `.texture` assets (px/nx/py/ny/pz/nz PNGs + a `cube.yaml` sidecar — see `docs/specs/cubemap-textures.md` §4 for the face convention). For probe authoring use the higher-level `reflectionProbe` module; reach for `environment` when you need the raw per-slot primitives. ## Usage ```luau -- Register probe blend data: index i maps to cube slot i. environment.setProbes({ { x = 0, y = 2, z = 0, radius = 12 } }) -- Bake slot 0 from a point (queued, next frame). environment.captureSlot(0, 0, 2, 0) -- Bake + persist to /source/probe_lobby.texture/ (yields; call from a -- task/coroutine/execute context). local path, err = environment.captureSlotToAsset("probe_lobby", 0, 0, 2, 0) -- Restore a persisted cube into a slot WITHOUT re-rendering. environment.loadSlotFromAsset("probe_lobby", 0) -- Capture the sky alone into the fallback slot: a surface no probe covers -- reflects the sky rather than black. environment.captureSky() ``` ## Exports - `environment.setProbes(probes) -> boolean` — set active probes' blend data; array of `{ x, y, z, radius, priority? }`, index i → cube slot i, gathered highest `priority` first - `environment.captureSky(x?, y?, z?) -> boolean` — render the sky alone into the fallback slot and arm it (queued) - `environment.setSkyFallback(active) -> boolean` — arm/disarm the fallback against the sky already captured (arming is refused while the slot holds none) - `environment.captureSlot(slot, x, y, z) -> boolean` — bake the scene into a slot from a point (queued) - `environment.captureSlotToAsset(name, slot, x, y, z, timeoutFrames?) -> (string?, string?)` — bake + persist as a `faces6` `.texture`; yields - `environment.loadSlotFromAsset(name, slot) -> (boolean, string?)` — upload a persisted cube into a slot without re-rendering Back-compat single-global-reflection helpers (slot 0 + one full-coverage probe): - `environment.capture(x, y, z) -> boolean` - `environment.captureToAsset(name, x, y, z) -> (string?, string?)` - `environment.loadFromAsset(name) -> (boolean, string?)`
▲ 0↑ born
▣
module · born here
❒asset
# transform Math helpers for positions, rotations, and directions on transforms. Exposed as the global `Transform` table via `--!global Transform` — no explicit require needed in user code. Functions that take an entity accept either an entity ID string or an entity proxy table from `entity("id")`. ## Exports Look-at and entity-aware helpers: - `Transform.lookAtQuat(fx, fy, fz, tx, ty, tz) -> (qx?, qy?, qz?, qw?)` — quaternion from origin toward target. Nil when degenerate. - `Transform.lookAt(entity, txOrTarget, ty?, tz?) -> (boolean, string?)` — make an entity face a world position or another entity. Both slots read world space: the subject and an entity target are read as `entity(id).position` and the aim is written as `entity(id).rotation`, so a parent under either one still leaves the aim on the point named. Returns whether the rotation was written, and the reason when it was not. - `Transform.distance(x1, y1, z1, x2, y2, z2) -> number` — Euclidean distance between two points. - `Transform.distanceBetween(entityA, entityB) -> number?` — distance between two entities' world positions. Nil when either is unresolvable. - `Transform.direction(fromX, fromY, fromZ, toX, toY, toZ) -> (dx, dy, dz)` — unit direction vector. - `Transform.directionBetween(entityA, entityB) -> (dx, dy, dz)` — unit world-space direction between two entities' world positions. Rotation shapes: A quaternion **constructor** here returns the four components as four separate values, so a caller either names them or braces the call to make one table: ```lua local qx, qy, qz, qw = Transform.quatFromAxisAngle(0, 1, 0, math.rad(90)) entity("cam").localRotation = { Transform.quatFromAxisAngle(0, 1, 0, math.rad(90)) } ``` A rotation-taking **surface** reads that table through `Transform.toQuaternion`, which also takes euler DEGREES — so `{ qx, qy, qz, qw }`, `{ x =, y =, z =, w = }`, `{ pitch, yaw, roll }` and `{ pitch =, yaw =, roll = }` all mean the same thing wherever a rotation is assigned: `entity(id).rotation` / `.localRotation`, `entityOps.spawn`, `entityOps.transform`, and the capture viewpoints. - `Transform.toQuaternion(rotation, label?) -> { qx, qy, qz, qw }` — the shared reading of a rotation a caller wrote. Raises when the value matches no form, naming what arrived; a value that is one of the shapes a quaternion helper returns is named as such along with the packing it goes in as. - `Transform.tryQuaternion(rotation, label?) -> ({ qx, qy, qz, qw } | nil, message?)` — the same reading without raising, for a surface that wants to raise the message at its own caller's line. - `Transform.readVec3(value, label?) -> { x, y, z }` — the same for a vector. - `Transform.snapVec3(v, step) -> { x, y, z }` — quantize a vector to a step grid. Quaternion construction / conversion: - `Transform.quatFromYaw(yaw)`, `Transform.quatFromYawPitch(yaw, pitch)`, `Transform.quatFromAxisAngle(ax, ay, az, angle)` — quaternion constructors. - `Transform.quatIdentity()` — identity quaternion. - `Transform.euler(qx, qy, qz, qw) -> (yaw, pitch, roll)` and the named alias `Transform.quatToEuler`. - `Transform.eulerToQuat(yaw, pitch?, roll?)` — euler-to-quaternion in YXZ order. Lerps and interpolation: - `Transform.lerp(ax, ay, az, bx, by, bz, t) -> (x, y, z)` — vec3 lerp. - `Transform.lerp1(a, b, t) -> number` — scalar lerp. - `Transform.normalizeAngle(a) -> number` — wrap angle into `[-pi, pi]`. - `Transform.lerpAngle(a, b, t) -> number` — shortest-arc angle lerp. - `Transform.slerp(ax, ay, az, aw, bx, by, bz, bw, t) -> (qx, qy, qz, qw)` — quaternion slerp with shortest-path and near-parallel fallback. Quaternion operations: - `Transform.quatMul(...) -> (qx, qy, qz, qw)` — `qa * qb` composition. - `Transform.quatInverse(qx, qy, qz, qw) -> (qx, qy, qz, qw)` — inverse (= conjugate for unit quats). - `Transform.quatRotateVec(qx, qy, qz, qw, vx, vy, vz) -> (x, y, z)` — rotate a vec3 by a quaternion. Pose helpers: - `Transform.orbit(centerX, centerY, centerZ, radius, height, angle) -> (x, y, z, qx, qy, qz, qw)` — orbital pose facing the center. - `Transform.worldToLocal(...)` / `Transform.localToWorld(...)` — pose-space conversions. Nested `Transform.vec.*` namespace (component-wise vec3): - `Transform.vec.add`, `sub`, `scale`, `dot`, `cross`, `length`, `normalize`. Types: - `Vec3 = { x: number, y: number, z: number }` - `EntityRef = string | { entityId: string }` ## Usage ```luau -- Look-at by coordinates or by target entity: Transform.lookAt("cam", 0, 1, 0) -- an entity target resolves to that entity's world position local aimed, why = Transform.lookAt("cam", "box") -- Orbit pose around a point: local x, y, z, qx, qy, qz, qw = Transform.orbit(0, 1, 0, 5, 2, t) entity.find("cam").localPosition = { x, y, z } entity.find("cam").localRotation = { qx, qy, qz, qw } -- Quaternion math: local qx, qy, qz, qw = Transform.quatFromYawPitch(math.pi / 4, 0) local sx, sy, sz, sw = Transform.slerp(0, 0, 0, 1, qx, qy, qz, qw, 0.5) -- Component-wise vec3 helpers: local nx, ny, nz = Transform.vec.normalize(1, 1, 0) ``` ## Notes - The `--!global Transform` directive promotes the module's typed functions onto the runtime universe's globals bucket, so `Transform.*` is available without any per-source `require`. - Entity-aware functions (`lookAt`, `distanceBetween`, `directionBetween`) report a missing entity or a missing transform in their return value rather than raising: `lookAt` answers `false, "unresolved"` / `"no-transform"` / `"incomplete-target"` / `"degenerate"`, `distanceBetween` answers `nil`, and `directionBetween` answers zeros. - Quaternion APIs operate on raw `(qx, qy, qz, qw)` tuples for parity with the entity proxy's `localRotation.get`/`set`. Use `Transform.quatIdentity()` rather than hand-rolling `(0, 0, 0, 1)`. - `Transform.slerp` flips the second quaternion if `dot < 0` to take the shortest path, and falls back to lerp+normalize when the inputs are within `dot > 0.9995` to avoid `1/0` near-parallel issues.
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
▣
module · born here
❒asset
# json JSON encode/decode library for Luau. Encodes Lua values to JSON strings and decodes JSON strings back to Lua values. Used for communication with the Rust side of the engine, the VFS read/write bridge, and any wire-format that needs JSON. Pure Luau, no engine dependencies. Compact and pretty-printed encoders, plus a hand-rolled decoder that streams the input by position so it works under WASM as well as native. ## Exports - `Json.encode(value: any, indent?: string, currentIndent?: string) -> string` — compact encode. Functions / unknown types and NaN/Inf encode as `null`. - `Json.encodePretty(value: any, indentStr?: string) -> string` — pretty-printed encode with sorted object keys (diff-friendly). - `Json.encodeArgs(...: any) -> string` — encode varargs as a JSON array. - `Json.decode(str: string) -> any` — decode a JSON string. Returns the decoded value, or `nil` + error message on failure. ## Usage ```luau local Json = require("@builtin::modules.json") local widget = { type = "button", text = "Click Me" } local compact = Json.encode(widget) -- '{"text":"Click Me","type":"button"}' local pretty = Json.encodePretty(widget, " ") local decoded = Json.decode(compact) local v, err = Json.decode("oops") -- v = nil, err = error message ``` ## Notes - Object keys are sorted alphabetically in both encoders for consistent output across runs. - Numeric keys on objects are stringified at encode time (JSON has no numeric keys). Pure-integer key sets get detected as arrays via `isArray` and encoded with brackets. - NaN, +Inf, -Inf encode as `null` — JSON has no representation. Round trips through `decode` recover `null` (Lua `nil`), so they don't preserve. - Unicode `\uXXXX` escapes decode to UTF-8 by hand to stay WASM-safe. Only the BMP is covered; supplementary planes via surrogate pairs are not. - Functions encode as `null`. - Decode is character-streamed — no regex, no `string.match` patterns on the whole input — so the line-and-column information needs to be reconstructed from the position offset.
▲ 0↑ born
▣
module · born here
❒asset
# rigmath Quaternion algebra, vector helpers, and forward kinematics over a bone hierarchy. One definition of the math, shared by retargeting and IK. Quaternions are `{ x, y, z, w }` arrays and vectors are `{ x, y, z }` arrays, matching the conventions the engine's rig data already uses, so values read straight out of `ecs.Skeleton.bones` or a parsed `.rig` need no conversion. ## Exports Vectors: - `vdot(a, b) -> number` — dot product. - `vcross(a, b) -> { number }` — cross product. - `vlen(v) -> number` — Euclidean length. - `vsub(a, b)`, `vadd(a, b)`, `vscale(v, s) -> { number }` — component-wise arithmetic. - `vnormalize(v) -> { number }` — unit vector; a zero-length input returns zero. - `vperpendicular(v) -> { number }` — a deterministic unit vector at right angles to `v`. Quaternions: - `IDENTITY` — `{ 0, 0, 0, 1 }`. - `qmul(a, b) -> { number }` — Hamilton product; applies `b`, then `a`. - `qnormalize(q)`, `qinverse(q) -> { number }`. - `qrotvec(q, v) -> { number }` — rotate a vector. - `shortestArc(a, b) -> { number }` — the rotation carrying unit vector `a` onto `b`. - `axisAngle(axis, angle) -> { number }` — from an axis and radians. - `qslerp(a, b, t) -> { number }` — shortest-arc interpolation. - `qangle(q) -> number` — rotation magnitude in radians, `[0, pi]`. - `signedAngle(a, b, axis) -> number` — roll from `a` to `b` about `axis`, in radians. - `swingTwist(q, axis) -> ({ number }, { number })` — twist about `axis`, then the remaining swing. Scalars: - `isFinite(n) -> boolean`, `clamp(v, lo, hi) -> number`. Forward kinematics: - `computeGlobals(bones) -> (gRot, gPos)` — global rest transforms from local ones. - `computeBoneLengths(bones, gPos) -> { number }` — each bone's distance to its farthest child. ## Usage ```luau local rigmath = require("modules.rigmath") -- Point a bone's forward axis at a target. local dir = rigmath.vnormalize(rigmath.vsub(targetPos, bonePos)) local swing = rigmath.shortestArc(rigmath.qrotvec(boneRot, { 0, 0, 1 }), dir) local aimed = rigmath.qmul(swing, boneRot) -- Blend the result in at a weight. local final = rigmath.qslerp(boneRot, aimed, 0.5) ``` ## Notes - Degenerate input never produces NaN. A zero-length vector normalizes to zero, a degenerate quaternion normalizes to identity, and `shortestArc` on antiparallel vectors resolves to a half turn about a perpendicular axis. - `computeGlobals` tolerates any bone ordering, including a parent listed after its child, and falls back to the local transform for a bone left unresolved by a cyclic parent. - Bone `parent` indices are 0-based with -1 for a root, matching the rig format; the returned arrays are 1-based and parallel to the input.
▲ 0↑ born
·
other · born here
▤file
▲ 0↑ born
backing path · systems/characterController.package/presets/synty_full.preset

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ 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".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.