92 lines
5.1 KiB
Markdown
92 lines
5.1 KiB
Markdown
# Animation Authoring
|
|
|
|
Blacksite's first production animation path supports skinned glTF 2.0 models (`.gltf` and `.glb`).
|
|
It normalizes imported rig and clip metadata into generated manifests, keeps authored scene data
|
|
independent of Bevy's runtime graph/player components, and uses the same controller contract in
|
|
editor preview, PIE, and standalone builds.
|
|
|
|
## Import And Placement
|
|
|
|
Place animated sources under `assets/` and refresh or reimport them from the Asset Browser. The
|
|
registry writes `assets/animations/generated/<asset-id>.animation.ron` beside the existing static
|
|
mesh artifact. Expanding a model row shows:
|
|
|
|
- skeleton entries with joint count and signature summary;
|
|
- animation clips with duration and event count;
|
|
- mesh, material, and texture entries from the static import contract.
|
|
|
|
Skeleton rows are inspect-only. Dragging an animation clip into the viewport creates one
|
|
`ImportedModel` actor with a stable `ModelRef` and `AnimationControllerDesc` and selects it for
|
|
immediate inspection. When an imported-model actor is selected, the same drag assigns the clip as a
|
|
new controller state instead. Assignment is one undoable command and requires an exact
|
|
skeleton-signature match.
|
|
|
|
Skinned primitive rows are inspect-only because their vertex data requires the source skin
|
|
hierarchy. Their thumbnails render the complete source scene, and drag/place actions direct authors
|
|
to place the model or an animation clip instead of creating an invalid detached mesh.
|
|
|
|
## Controller Inspector
|
|
|
|
The Animation Controller component exposes the selected skeleton, default crossfade, named states,
|
|
default state, clip, loop, speed, and optional playback range. State IDs are gameplay keys and must
|
|
be non-empty and unique; labels are presentation only. Component add, remove, reset, copy, paste,
|
|
and property changes use typed editor history and participate in scene dirty tracking.
|
|
|
|
The Preview section selects a state, plays or pauses it, stops playback, and scrubs within the
|
|
authored range. Preview requests use the game runtime adapter and do not change the controller,
|
|
history, or scene dirty state. Entering PIE clears any paused edit-mode scrub so the authored
|
|
default state can run; leaving PIE clears transient playback while retaining authored data.
|
|
|
|
## Runtime API
|
|
|
|
Gameplay changes state by sending a validated request through `game::animation`:
|
|
|
|
```rust
|
|
game::animation::request_animation_state(
|
|
world,
|
|
game::animation::AnimationStateRequest::new(actor, "run").with_crossfade(0.15),
|
|
)?;
|
|
```
|
|
|
|
An omitted crossfade uses the controller default. Invalid actor or state requests return an error
|
|
and preserve current playback. If edited controller data cannot rebuild its runtime graph, the old
|
|
graph is stopped and cleared instead of continuing stale playback. `AnimationGraph`,
|
|
`AnimationPlayer`, transitions, preview state, and hydrated model roots are runtime-only and never
|
|
serialize into authored scenes.
|
|
|
|
## Stable Identity And Moves
|
|
|
|
`ModelRef`, skeleton references, and clip references carry the model registry UUID. Generated
|
|
artifacts are keyed by that UUID; source paths are cached resolution and repair hints. When one
|
|
model is moved or renamed on disk, catalog refresh reconciles it by its animation-manifest content
|
|
hash, preserves the UUID, and regenerates both manifests with the new source path. An identical copy
|
|
is not treated as a move while the original still exists. Ambiguous content matches intentionally
|
|
receive a new identity rather than silently binding the wrong asset.
|
|
|
|
Legacy path-only `ModelRef` values remain readable and use their cached path. Reassign or replace a
|
|
legacy model actor to opt it into stable move resolution.
|
|
|
|
Skeleton compatibility hashes the exact Bevy 0.19 glTF node-name segments and bind poses, including
|
|
whitespace and slash characters. The readable joint paths shown by the editor are deliberately not
|
|
used as identity. Animation-manifest schema v1 artifacts must be reimported to generate schema v2
|
|
signatures.
|
|
|
|
## Validation And Format Boundary
|
|
|
|
Interactive diagnostics and `cargo validate-levels` resolve registry UUIDs, generated manifests,
|
|
stable subasset IDs, source dependencies, default/state IDs, playback ranges, speeds, crossfades,
|
|
runtime format support, exact source-content fingerprints, and exact rig compatibility. Findings
|
|
identify the owning actor and controller property and include a repair action. Packaging includes
|
|
the same source files and generated artifacts checked by validation.
|
|
|
|
FBX remains supported for static model import only. An FBX containing skin deformers or animation
|
|
stacks emits a blocking diagnostic directing the author to convert it to glTF. Animation v1 does
|
|
not support one glTF asset containing animation channels under multiple top-level roots, because
|
|
Bevy creates a separate `AnimationPlayer` for each root. Split those rigs into separate assets or
|
|
export them beneath one common root. Animation v1 also does not provide implicit retargeting, blend
|
|
trees, a visual state graph, root motion, IK, or motion matching.
|
|
|
|
See [ADR 0031](../adr/0031-animation-authoring-runtime-contract.md) for the persistent/runtime
|
|
boundary and [the working implementation plan](../../.cursor/plans/animation_authoring_2026-07-11.plan.md)
|
|
for acceptance gates.
|