Files
GhostEngine/Ghost.Editor.Core/SceneGraph/IMPLEMENTATION_SUMMARY.md
2026-01-25 22:06:58 +09:00

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 scenes
    • UnloadScene(): Destroys all entities in a scene
    • GetSceneEntities(): 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 saved
    • IsLoaded, IsDirty: Editor state tracking
    • RootEntities: 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 hierarchy
    • OwnerScene: 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 entities
  • EntityData: Name, parent local ID, components dictionary
  • ComponentData: 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:

  1. Build Entity → FileLocalID mapping
  2. Serialize each entity's components
  3. Entity references converted to file-local IDs
  4. Validate no cross-scene references (throws exception if found)
  5. Write JSON to file

Load Process:

  1. Read JSON
  2. Create all entities first (two-pass)
  3. Build FileLocalID → Entity mapping
  4. Deserialize components, remapping file-local IDs back to global Entity IDs
  5. 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 lists
  • GetParent(): Query parent
  • GetChildren(): Get immediate children
  • GetDescendants(): Recursive depth-first traversal
  • IsAncestor(): 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 tag
  • Hierarchy (Ghost.Engine/Components/Hierarchy.cs) - parent-child structure
  • LocalToWorld - transform (referenced but not modified)

ECS Integration

  • Uses QueryBuilder and chunk iteration for queries
  • EntityManager for 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 + SceneManager
  • Systems/HierarchyUtility.cs - Hierarchy helpers

Ghost.Editor.Core:

  • SceneGraph/SceneNode.cs - Scene graph node
  • SceneGraph/EntityNode.cs - Entity graph node
  • SceneGraph/EditorWorldManager.cs - Central manager
  • Serialization/SceneData.cs - JSON data structures
  • Serialization/SceneSerializer.cs - Save/load logic
  • Validation/SceneValidator.cs - Integrity checks

Total: 7 new files, ~1400 lines of code

Next Steps

To complete the scene graph feature:

  1. Create WinUI 3 TreeView bound to EditorWorldManager.LoadedScenes
  2. Add toolbar: New Scene, Save Scene, Unload Scene buttons
  3. Entity creation UI: Right-click menu, "Create Empty" button
  4. Drag-drop: Reparent entities by dragging in TreeView
  5. Rename: Double-click to rename EntityNode.Name
  6. Integration: Wire EditorWorldManager into main editor app lifecycle

All the core logic is complete and follows the plan precisely.