Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

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

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.