docs(architecture): close live animation slice

Record the shipped presentation owner, exact frame-handoff lifetime, retail short-frame behavior, current GameWindow metrics, and Slice 3 as the next structural boundary.
This commit is contained in:
Erik 2026-07-21 10:03:20 +02:00
parent 833520253a
commit 9a150e2421
7 changed files with 94 additions and 23 deletions

View file

@ -1,5 +1,41 @@
# Animation Runtime Crib
## Current live presentation ownership (2026-07-21)
`LiveEntityAnimationScheduler` owns ordinary-object time, PartArray advance,
root motion, and the retail manager tail. `RetailStaticAnimatingObjectScheduler`
owns the separate retail static-object workset. `LiveEntityAnimationPresenter`
is the sole consumer that composes final drawable part transforms, publishes
rigid part/effect poses, and binds `MotionDone`. `GameWindow` wires these owners
but no longer contains the presentation body.
The frame handoff is identity- and lifetime-bound. A schedule carries the exact
`LiveEntityRecord`, `WorldEntity`, animation state, sequencer, object-clock
epoch, projection mutation version, and presentation revision. Both ordinary
and static schedulers copy the sequencer's borrowed PartArray view into their
own buffers before invoking callbacks. Presentation is non-reentrant because
it consumes legacy elapsed time and static prepared frames exactly once.
Appearance rebinding increments `PresentationRevision`. That rejects a pose
prepared against the old part template without replacing the live animation
component. For a static owner, rejecting only that stale visual pose must retain
the same sequencer's pending `process_hooks` tail so `MotionDone` is not lost;
owner, sequencer, residency, projection, or clock mismatches still invalidate
the entire handoff.
Retail `CPartArray::UpdateParts` updates only the authored AnimFrame prefix.
When a frame contains fewer parts than the Setup, trailing parts keep their
previous pose (or their rest pose on first presentation) in both channels:
- visual: `DefaultScale * rotation * translation(origin) * ObjScale`;
- rigid/effect: `rotation * translation(origin * ObjScale)`.
Canonical per-frame order remains scheduler tick, static tick, live presenter,
equipped-child update, static `process_hooks`, deferred hook drain, attached
effects/lights, particles, and draw. The end-to-end order assertion belongs to
Slice 6's extracted update orchestrator; do not reintroduce local ordering into
the presenter.
## Live entity lifecycle invariant
`CreateObject` creates a live entity and a real `DeleteObject` destroys it.