6.2 KiB
Scene Graph System Implementation Summary
All planned features from the SceneGraph Plan.md have been implemented successfully. Here's what was created:
1. Runtime Types (Ghost.Engine)
Scene.cs
- Scene struct: Lightweight runtime identifier for scenes
- SceneManager class: Manages scene lifecycle in a world
CreateScene(): Creates new scenesUnloadScene(): Destroys all entities in a sceneGetSceneEntities(): Queries entities by scene ID
Key design: Minimal runtime footprint, no metadata stored.
2. Editor Data Structures (Ghost.Editor.Core)
SceneNode.cs
- Editor-only scene representation
- Properties:
Name: Display name (NOT in runtime)FilePath: Where scene is savedIsLoaded,IsDirty: Editor state trackingRootEntities: Observable collection of root entity nodes
- Methods for managing root entities and finding nodes
EntityNode.cs
- Editor-only entity representation
- Properties:
Name: Display name (NOT in runtime)Parent,Children: Editor hierarchyOwnerScene: Back-reference to scene
- Methods for hierarchy management (AddChild, RemoveChild, FindNode, GetAllDescendants)
Both classes use ObservableCollection for WinUI 3 TreeView binding support.
3. Editor World Management
EditorWorldManager.cs
- Central manager for editor world and scene graph
- Features:
- Scene creation/unloading
- Entity creation/destruction with automatic SceneID assignment
- Hierarchy component management
- Entity/Scene node tracking via dictionaries
RebuildSceneGraph(): Reconstructs scene graph from world state after loading
Maintains bidirectional mapping: Entity ↔ EntityNode, SceneID ↔ SceneNode
4. Serialization (Ghost.Editor.Core)
SceneData.cs
JSON data structures:
SceneData: Contains name + list of entitiesEntityData: Name, parent local ID, components dictionaryComponentData: Type name + fields dictionary
Key Feature: Entities are ordered by file-local ID (index in list).
SceneSerializer.cs
Complete save/load implementation with entity reference remapping:
Save Process:
- Build
Entity → FileLocalIDmapping - Serialize each entity's components
- Entity references converted to file-local IDs
- Validate no cross-scene references (throws exception if found)
- Write JSON to file
Load Process:
- Read JSON
- Create all entities first (two-pass)
- Build
FileLocalID → Entitymapping - Deserialize components, remapping file-local IDs back to global Entity IDs
- Rebuild hierarchy
Uses reflection to serialize/deserialize component fields. Entity references are detected by field type and specially handled.
5. Hierarchy System (Ghost.Engine)
HierarchyUtility.cs
Runtime utilities for working with Hierarchy component:
SetParent(): Update parent-child relationships, maintains sibling listsGetParent(): Query parentGetChildren(): Get immediate childrenGetDescendants(): Recursive depth-first traversalIsAncestor(): Check ancestor relationship
Uses the existing Hierarchy component (parent, firstChild, nextSibling pattern).
6. Validation (Ghost.Editor.Core)
SceneValidator.cs
Validates scene integrity:
ValidateSceneReferences:
- Checks all Entity fields in components
- Ensures referenced entities exist
- Enforces same-scene constraint (errors on cross-scene refs)
ValidateHierarchy:
- Detects circular parent-child loops
- Warns if parent is outside scene
Returns ValidationResult with errors/warnings lists.
Architecture Highlights
Runtime vs Editor Separation
- Runtime (
Ghost.Engine): Only SceneID component, SceneManager, HierarchyUtility - Editor (
Ghost.Editor.Core): All metadata (names), scene graph tree, serialization - Zero runtime overhead for editor-only data
Entity Reference Remapping
Per plan, entity references use file-local IDs in saved scenes:
- Avoids brittle global IDs
- Enables scene prefabs/templates in future
- Automatically remapped on load
Cross-Scene Reference Prevention
- Validation layer enforces no cross-references
- SerializeComponent throws exception if detected during save
- Plan notes: Use queries/singletons for cross-scene access
JSON for Editor, Binary for Runtime
- Current impl: JSON serialization for editor (SceneSerializer.cs)
- Plan notes MemoryPack for runtime binary format
- Reflection allowed in editor, AOT-compatible runtime preserved
Integration Points
Existing Components Used
SceneID(Ghost.Engine/Components/SceneID.cs) - scene membership tagHierarchy(Ghost.Engine/Components/Hierarchy.cs) - parent-child structureLocalToWorld- transform (referenced but not modified)
ECS Integration
- Uses
QueryBuilderand chunk iteration for queries EntityManagerfor all entity operations- Archetype layouts for component enumeration
What's NOT Implemented (As Per Plan)
The plan explicitly states:
"Leave the actual UI implementation (TreeView) for later"
Not included in this implementation:
- WinUI 3 TreeView XAML
- UI controls for hierarchy panel
- Drag-drop entity reparenting
- Context menus
- Icons/gizmos
These are left for UI layer implementation. The data structures (SceneNode, EntityNode with ObservableCollection) are designed to bind directly to TreeView.
Files Created
Ghost.Engine:
Scene.cs- Scene struct + SceneManagerSystems/HierarchyUtility.cs- Hierarchy helpers
Ghost.Editor.Core:
SceneGraph/SceneNode.cs- Scene graph nodeSceneGraph/EntityNode.cs- Entity graph nodeSceneGraph/EditorWorldManager.cs- Central managerSerialization/SceneData.cs- JSON data structuresSerialization/SceneSerializer.cs- Save/load logicValidation/SceneValidator.cs- Integrity checks
Total: 7 new files, ~1400 lines of code
Next Steps
To complete the scene graph feature:
- Create WinUI 3 TreeView bound to
EditorWorldManager.LoadedScenes - Add toolbar: New Scene, Save Scene, Unload Scene buttons
- Entity creation UI: Right-click menu, "Create Empty" button
- Drag-drop: Reparent entities by dragging in TreeView
- Rename: Double-click to rename EntityNode.Name
- Integration: Wire EditorWorldManager into main editor app lifecycle
All the core logic is complete and follows the plan precisely.