M2 Animated Scene Finalizer
Metadata
| Field |
Value |
| Status |
Implemented extraction |
| Target/work package |
M03 / M03-RND-M2-ANIMATED-SCENE-FINALIZER-001 |
| Owners |
Detached animated candidate, material repair and player validation |
| Last verified |
Worktree work/sindo-main-codex/m03-m2-animated-scene-finalizer, 2026-07-18 |
| Profiles/capabilities |
Existing optional cached-GLB animated M2 path |
Purpose
Finalize one loaded animated M2 scene on the main thread: instantiate a valid
detached Node3D candidate, copy the historical static-prototype material mapping
and accept only candidates containing AnimationPlayer descendants.
Non-goals
- Call ResourceLoader or interpret threaded-load statuses.
- Choose animation eligibility, cache paths, permits or material prototypes.
- Adopt prototypes, mark static fallback or select/play animations.
- Process native M2 animators or static Mesh rebuilds.
Context and boundaries
Allowed dependencies are Godot scene/resource/material types. ResourceLoader,
filesystem, workers, scheduler, builders, raw repositories, prototype cache and
other application layers are forbidden.
Public API
| Symbol |
Kind |
Purpose |
Thread/lifetime |
Errors |
instantiate_candidate(resource) |
Ownership query |
Instantiate PackedScene as detached Node3D |
Main thread; caller receives valid candidate |
Unsupported/invalid null; created wrong-type root freed |
repair_materials(animated_root, material_source_root) |
Command |
Apply historical material overrides |
Main thread; borrowed roots |
Null/empty roots no-op |
finalize_candidate(candidate_root) |
Ownership command/query |
Require AnimationPlayer and transfer root/count |
Main thread; detached candidate |
Null empty; rejected candidate freed |
mesh_instances_in_subtree(root) |
Query |
Depth-first MeshInstance3D inventory |
Main thread; borrowed subtree |
Null returns empty |
animation_players_in_subtree(root) |
Query |
Depth-first AnimationPlayer inventory |
Main thread; borrowed subtree |
Null returns empty |
Inputs and outputs
| Direction |
Contract/data |
Producer |
Consumer |
Ownership |
Thread/lifetime |
| Input |
Loaded Resource |
Loader I/O adapter |
Candidate instantiator |
Borrowed Resource |
One finalize permit |
| Input |
Static material prototype Node3D |
Loader cache/build adapter |
Material repair |
Borrowed Node |
One repair call |
| Input |
Detached animated candidate |
Instantiator |
Repair/final validation |
Finalizer then caller/release |
One attempt |
| Output |
Accepted prototype and player count |
Finalizer |
Loader adoption/log adapter |
Exact Node transferred |
Shutdown cache lifetime |
| Output |
Depth-first engine-node arrays |
Traversal |
Loader preparation/playback |
Borrowed references |
One call |
Side effects are PackedScene instantiation, surface override assignment and
synchronous destruction of rejected detached roots.
Data flow
Lifecycle/state
Main sequence
Dependency diagram
Ownership, threading and resources
- Every method runs synchronously on the renderer main thread.
- A valid candidate is detached and finalizer-owned until acceptance.
- Acceptance transfers the exact Node3D to the loader/prototype cache path.
- Rejection frees the candidate synchronously, including wrong-type roots.
- Traversal results borrow Nodes; source materials remain Resource-owned.
Errors, cancellation and recovery
| Failure |
Detection |
Behavior |
Diagnostic |
Recovery |
| Null/unsupported Resource |
Type guard |
Return null |
Dedicated verifier |
Loader marks static |
| Wrong root type |
Instantiated type guard |
Free and return null |
Node-count regression |
Rebuild cache |
| No material source/meshes |
Null/empty traversal |
Leave materials unchanged |
Material fixture |
Imported materials remain |
| Missing source surface |
Material lookup |
First source material fallback |
Mapping fixture |
Repair static source |
| No AnimationPlayer |
Descendant inventory |
Free and return empty |
Lifetime regression |
Loader marks static |
| Shutdown/cancellation |
Not owned |
No retained state |
N/A |
Loader drains first |
Configuration and capabilities
| Setting/capability |
Default |
Profile |
Runtime mutable |
Effect |
| Finalize permit |
m2_animation_finalize_ops_per_tick = 1 |
Existing profiles |
Yes |
Caller bounds calls |
| Material mapping |
Depth-first/index-clamped |
All |
No |
Preserves current appearance |
| Required players |
At least one |
All |
No |
Rejects non-animated scenes |
Persistence, cache and migration
The service retains no state and serializes nothing. GLB/cache formats, material
versions and prototype lifetimes are unchanged; no rebake is required.
Diagnostics and observability
- Accepted result reports player count for the existing
M2_ANIM_CACHE log.
- Traversal order is deterministic depth-first preorder.
- The service owns no logging or metrics.
Verification
verify_m2_animated_scene_finalizer.gd covers invalid Resources, wrong-root
release, exact transfer, player traversal/count, override priority, fallback,
source-index mapping, source boundaries and timing.
- Adjacent animation pipeline/prototype/shutdown/material/build tests protect callers.
- Fidelity evidence is exact mapping/lifecycle extraction; no asset-backed or
original-client visual parity claim is made.
- Performance budget: 10,000 depth-eight player inventories under one second.
Extension points
Animation playback policy and native animator field copying now belong to
M2AnimationPlaybackController; instance/batch materialization remains loader-owned.
Capability status
| Capability |
Status |
Evidence |
Gap/next step |
| PackedScene candidate |
Implemented extraction |
Type/lifetime fixture |
Proprietary corrupt corpus pending |
| Material repair |
Implemented extraction |
Exact-reference mapping |
Asset-backed comparison pending |
| Player validation |
Implemented extraction |
Nested traversal/transfer |
Multi-player GLB corpus pending |
Known gaps and risks
- Material matching remains positional rather than semantic.
- Accepted prototypes remain unbounded until final loader shutdown.
- No private traversal, descriptor-pressure, p95/p99 or paired-client run exists.
Source map
| Path |
Responsibility |
src/render/m2/m2_animated_scene_finalizer.gd |
Candidate ownership, traversal, material repair and validation |
src/render/m2/m2_animation_playback_controller.gd |
Accepted-instance playback and native animator startup |
src/render/m2/m2_animation_load_pipeline_state.gd |
Pending/terminal records before finalization |
src/render/m2/m2_prototype_cache_state.gd |
Accepted prototype/static-only outcomes |
src/scenes/streaming/streaming_world_loader.gd |
I/O, permits, material source, adoption and logs |
src/tools/verify_m2_animated_scene_finalizer.gd |
Scene/material/lifetime/boundary/timing regression |
Related decisions and references