227 lines
10 KiB
Markdown
227 lines
10 KiB
Markdown
# M2 Raw Model Repository
|
|
|
|
## Metadata
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Status | Implemented extraction |
|
|
| Target/work package | M03 / `M03-RND-M2-RAW-MODEL-REPOSITORY-001` |
|
|
| Owners | Native M2Loader availability, file existence and raw Dictionary loading |
|
|
| Last verified | Worktree `work/sindo-main-codex/m03-m2-raw-model-repository`, 2026-07-17 |
|
|
| Profiles/capabilities | Static and native-animated raw M2 reads |
|
|
|
|
## Purpose
|
|
|
|
Provide one stateless boundary between renderer orchestration and the optional
|
|
native `M2Loader`. The repository resolves an extracted path and returns the raw
|
|
static or animated Dictionary consumed by existing builders and classifiers.
|
|
|
|
## Non-goals
|
|
|
|
- Normalize relative paths or choose `.tscn`/`.glb` cache fallbacks.
|
|
- Cache successful data, missing paths, Meshes, Nodes or animation decisions.
|
|
- Build geometry/materials, own queues or attach renderer objects.
|
|
- Change native parsing, cache formats, retry policy or visible behavior.
|
|
|
|
## Context and boundaries
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
Loader[StreamingWorldLoader] --> Repository[M2RawModelRepository]
|
|
Repository --> File[Extracted M2 file]
|
|
Repository --> Native[ClassDB M2Loader]
|
|
Native --> Raw[Raw Dictionary]
|
|
Raw --> Loader
|
|
Loader --> Builder[Existing M2 builders/finalizer]
|
|
```
|
|
|
|
Allowed dependencies are `ProjectSettings`, `FileAccess` and `ClassDB` for the
|
|
native file boundary. Resource caches, builders, SceneTree types, worker pools,
|
|
renderer policy and other application layers are forbidden.
|
|
|
|
## Public API
|
|
|
|
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|
|
|---|---|---|---|---|
|
|
| `load_static_model_data(extracted_directory, normalized_relative_path)` | Query | Invoke native `load_m2` for one existing extracted file | Synchronous; stateless | Returns `{}` for rejected/unavailable/invalid result |
|
|
| `load_animated_model_data(extracted_directory, normalized_relative_path)` | Query | Invoke native `load_m2_animated` for one existing extracted file | Synchronous; stateless | Returns `{}` for rejected/unavailable/invalid result |
|
|
|
|
## Inputs and outputs
|
|
|
|
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|
|
|---|---|---|---|---|---|
|
|
| Input | Extracted directory String | Loader configuration | Repository path resolution | Copied value | One call |
|
|
| Input | Already-normalized relative M2 path String | Loader normalization | Repository | Copied value | One call |
|
|
| Input | Extracted `.m2` bytes | Local legal extraction | Native M2Loader | File-owned | Native call |
|
|
| Output | Static raw M2 Dictionary | Native `load_m2` | Loader/finalizer/M2Builder | Fresh native result | One caller operation |
|
|
| Output | Animated raw M2 Dictionary | Native `load_m2_animated` | Loader/animated builder | Fresh native result | One caller operation |
|
|
| Output | Empty Dictionary | Repository guards | Loader fallback and prototype outcome adapter | Fresh value | One failed call |
|
|
|
|
Side effects are limited to file-existence inspection, synchronous native file
|
|
parsing and creation of one temporary native loader instance per accepted call.
|
|
|
|
## Data flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Request[Directory plus normalized path] --> Empty{Path empty?}
|
|
Empty -->|yes| Reject[Return empty Dictionary]
|
|
Empty -->|no| Class{M2Loader registered?}
|
|
Class -->|no| Reject
|
|
Class -->|yes| Resolve[globalize directory/path join]
|
|
Resolve --> Exists{File exists?}
|
|
Exists -->|no| Reject
|
|
Exists -->|yes| Instance[Instantiate M2Loader]
|
|
Instance --> Method{Instance and method available?}
|
|
Method -->|no| Reject
|
|
Method -->|yes| Parse[Call static or animated method]
|
|
Parse --> Type{Dictionary result?}
|
|
Type -->|no| Reject
|
|
Type -->|yes| Return[Return raw Dictionary]
|
|
```
|
|
|
|
## Lifecycle/state
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> Ready: construct repository
|
|
Ready --> Resolving: load request
|
|
Resolving --> Ready: rejected input/unavailable dependency
|
|
Resolving --> Parsing: file and native method available
|
|
Parsing --> Ready: Dictionary or empty result returned
|
|
Ready --> [*]: caller releases reference
|
|
```
|
|
|
|
No request, result or failure state survives a call.
|
|
|
|
## Main sequence
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Loader as StreamingWorldLoader
|
|
participant Repo as M2RawModelRepository
|
|
participant File as FileAccess
|
|
participant Native as M2Loader
|
|
Loader->>Repo: load static/animated(directory, path)
|
|
Repo->>File: file_exists(globalized joined path)
|
|
alt dependency or file unavailable
|
|
Repo-->>Loader: empty Dictionary
|
|
else available
|
|
Repo->>Native: instantiate and call exact native method
|
|
Native-->>Repo: Variant
|
|
Repo-->>Loader: Dictionary or empty Dictionary
|
|
end
|
|
```
|
|
|
|
## Dependency diagram
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
Loader[StreamingWorldLoader] --> Repository[M2RawModelRepository]
|
|
Repository --> ProjectSettings
|
|
Repository --> FileAccess
|
|
Repository --> ClassDB
|
|
ClassDB --> Native[M2Loader extension]
|
|
Loader --> Finalizer[M2RuntimeMeshFinalizer]
|
|
Loader --> StaticBuilder[M2Builder]
|
|
Loader --> AnimatedBuilder[M2NativeAnimatedBuilder]
|
|
Repository -. no dependency .-> Finalizer
|
|
Repository -. no dependency .-> StaticBuilder
|
|
Repository -. no dependency .-> Cache[Renderer caches/queues]
|
|
```
|
|
|
|
## Ownership, threading and resources
|
|
|
|
- The repository owns only call-local path, native instance and result values.
|
|
- The loader owns path normalization and fallback selection;
|
|
`M2PrototypeCacheState` owns prototype/negative adoption.
|
|
- Native `M2Loader` owns parsing behavior and returns a new Dictionary value.
|
|
- Calls are synchronous on the caller's thread; current renderer callers use the
|
|
main thread. The module starts no tasks and touches no SceneTree objects.
|
|
- No file handle, native instance, Dictionary or engine Resource is retained.
|
|
|
|
## Errors, cancellation and recovery
|
|
|
|
| Failure | Detection | Behavior | Diagnostic | Recovery |
|
|
|---|---|---|---|---|
|
|
| Empty normalized path | String guard | Return `{}` | Dedicated verifier | Correct caller normalization |
|
|
| Native extension absent | `ClassDB.class_exists` | Return `{}` | Existing renderer fallback | Install/load extension and retry |
|
|
| Extracted file absent | `FileAccess.file_exists` | Return `{}` | Prototype cache records historical missing state through loader | Restore extraction and start a new loader session |
|
|
| Instance/method absent | Null/`has_method` guard | Return `{}` | Source contract verifier | Repair extension registration |
|
|
| Parse/non-Dictionary result | Result type check | Return `{}` | Existing loader fallback | Repair asset/parser and retry |
|
|
| Cancellation requested | Not supported inside synchronous native call | Call completes | None | Caller controls whether to start call |
|
|
|
|
## Configuration and capabilities
|
|
|
|
| Setting/capability | Default | Profile | Runtime mutable | Effect |
|
|
|---|---|---|---|---|
|
|
| Native class name | `M2Loader` | All | No | Exact GDExtension registration |
|
|
| Static method | `load_m2` | All | No | Existing static parser path |
|
|
| Animated method | `load_m2_animated` | Experimental animated path | No | Existing native animation parser |
|
|
| Extracted directory | Loader `extracted_dir` | Scene configuration | Yes, caller-owned | Root used for path join |
|
|
|
|
## Persistence, cache and migration
|
|
|
|
The module adds no persistence or cache. Native methods, normalized relative
|
|
paths and `.tscn/.glb`/material versions are unchanged, so no migration or rebake
|
|
is required.
|
|
|
|
## Diagnostics and observability
|
|
|
|
- Logs: none; loader retains existing fallback and debug output.
|
|
- Metrics: none; rejected-input timing is verifier-only.
|
|
- Debug views: none.
|
|
- Correlation ID: normalized relative M2 path in the caller.
|
|
|
|
## Verification
|
|
|
|
- `verify_m2_raw_model_repository.gd` covers empty/missing/repeated failures,
|
|
exact static/animated method ownership, three loader delegations, forbidden
|
|
dependencies and 10,000 empty-path rejects under one second.
|
|
- Adjacent finalizer/extractor/cache/pipeline/animation/material/shutdown tests
|
|
protect caller behavior and ownership.
|
|
- Fidelity evidence is structural: exact path join/globalization and native
|
|
method names are preserved. No proprietary M2 or original-client visual claim
|
|
is made by this extraction.
|
|
|
|
## Extension points
|
|
|
|
Future asset-backed verification may add a legal fixture around these value
|
|
contracts. Caching, asynchronous I/O and parser replacement require separate
|
|
measured work packages rather than expansion of this repository.
|
|
|
|
## Capability status
|
|
|
|
| Capability | Status | Evidence | Gap/next step |
|
|
|---|---|---|---|
|
|
| Static raw M2 read | Implemented extraction | Source/invalid/missing verifier | Legal success fixture pending |
|
|
| Native animated raw M2 read | Implemented extraction | Exact method/source contract | Legal animated fixture pending |
|
|
| Stateless failure behavior | Verified synthetic | Repeated missing call and source boundary | Asset-backed corrupt input pending |
|
|
|
|
## Known gaps and risks
|
|
|
|
- Native parsing remains synchronous and has no mid-call cancellation.
|
|
- The repository deliberately does not distinguish missing dependency, missing
|
|
file and parser failure; loader fallback behavior historically treats them alike.
|
|
- Proprietary asset traversal, descriptor pressure, p95/p99 and visual comparison
|
|
remain outside this structural extraction.
|
|
|
|
## Source map
|
|
|
|
| Path | Responsibility |
|
|
|---|---|
|
|
| `src/render/m2/m2_raw_model_repository.gd` | Stateless native class/file/method boundary |
|
|
| `src/render/m2/m2_prototype_cache_state.gd` | Prototype and negative-result retention |
|
|
| `src/scenes/streaming/streaming_world_loader.gd` | Path normalization, fallback decisions and result consumers |
|
|
| `src/native/src/m2_loader.cpp` | Native static/animated parsing implementation |
|
|
| `src/tools/verify_m2_raw_model_repository.gd` | Rejected-input/source/dependency/timing regression |
|
|
|
|
## Related decisions and references
|
|
|
|
- [`m2-runtime-mesh-finalizer.md`](m2-runtime-mesh-finalizer.md)
|
|
- [`m2-mesh-resource-cache-state.md`](m2-mesh-resource-cache-state.md)
|
|
- [`m2-mesh-load-pipeline-state.md`](m2-mesh-load-pipeline-state.md)
|
|
- [`world-renderer.md`](world-renderer.md)
|
|
- [`../../RENDER.md`](../../RENDER.md)
|
|
- [`../../targets/roadmap/02-rendering-and-graphics.md`](../../targets/roadmap/02-rendering-and-graphics.md)
|