Character (Animation Controller)
App: apps/character_anim/
The end-to-end demo for the Animation Controller: a skinned Blender
character (Character.blend / Fire_Sprite) driven through node.attachController("controllers/biped.toml").
The controller owns and drives the character’s pose from a TOML-authored graph — a blend-node
locomotion State, a typed speed param fed from input, root-motion designation, and a tagged
cancel section — and the engine auto-ticks it each frame. The character skins and animates on the
GPU via the controller (not node.animations).
(This sits alongside — it does not replace — character_controller,
the Jolt CharacterVirtual physics demo. “Controller” here is the animation controller.)
Run from root
Section titled “Run from root”% ./plume3d character_animControls
Section titled “Controls”| Key | Action |
|---|---|
| WASD / Arrow keys | Move → sets the speed blend param |
| Shift | Run (higher speed) |
| E | A one-shot intent that is buffered and consumed only inside the clip’s cancel section |
| Mouse (right-drag) | Fly-camera look |
What it demonstrates
Section titled “What it demonstrates”node.attachController(path)loads a TOML controller asset and binds it to the skinned node; the engine hot-reloads it if you edit the file while it runs.- A blend-node locomotion State (
blend1doverspeed) authored in TOML. - Typed params driven from input, and a behaviour hook (
onEnter) firing from the auto-tick. - Clip phase: a tagged
cancelsection drives the input-buffering / cancel-window pattern — anEpress is held and consumed only whilectrl.inSection("cancel"). - Root motion (read-only):
ctrl.rootMotionDeltais applied to the character’s transform.
Fixture note
Section titled “Fixture note”The shipped Character.blend carries a single action (Idle_ArmSwing), so the locomotion blend is a
single-entry blend1d and there is no distinct masked-Action clip yet. A full walk/run blend and an
upper-body Action need a richer rig (multiple actions) — the engine supports both today (they are
unit-tested); the demo is fixture-limited, not engine-limited.