feat: implement complete scene graph system with hierarchical editor support
- Add SceneNode and EntityNode classes for editor-only metadata storage - Implement SceneGraph view-model with O(1) entity lookup via internal caching - Create IdRemapTable for file-local to global entity ID remapping on load - Implement SceneSerializationContext for load/save operation tracking - Add JSON-serializable SceneAssetData, EntityData, and ComponentData models - Implement SceneSerializer for save/load with validation and reference remapping - Add comprehensive documentation: README.md, IMPLEMENTATION_GUIDE.md, SYSTEM_SUMMARY.md - Update Ghost.Editor.Core.csproj to reference Ghost.Entities assembly - Support parent-child relationships via Hierarchy component - Enforce no cross-scene entity references - Keep runtime minimal: only SceneID, Hierarchy, LocalToWorld components - All editor metadata (names, UI state) stored in editor-only SceneNode/EntityNode classes This implements the architecture from SceneGraph Plan.md with clean separation of concerns, minimal runtime footprint, and AOT compatibility.
This commit is contained in:
98
Ghost.Editor.Core/SceneGraph/Serialization/SceneAssetData.cs
Normal file
98
Ghost.Editor.Core/SceneGraph/Serialization/SceneAssetData.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ghost.Editor.Core.SceneGraph.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// JSON-serializable representation of a component instance.
|
||||
/// Only used in the editor for saving/loading scenes.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ComponentData
|
||||
{
|
||||
/// <summary>
|
||||
/// Fully qualified type name of the component (e.g., "Ghost.Engine.Components.Transform").
|
||||
/// </summary>
|
||||
[JsonPropertyName("type")]
|
||||
public string ComponentTypeName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Serialized component data as a dictionary.
|
||||
/// Field names map to JSON values.
|
||||
/// </summary>
|
||||
[JsonPropertyName("data")]
|
||||
public Dictionary<string, object?> Data { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// JSON-serializable representation of an entity within a scene.
|
||||
/// Only used in the editor for saving/loading scenes.
|
||||
///
|
||||
/// The index in the entities list corresponds to the file-local ID.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class EntityData
|
||||
{
|
||||
/// <summary>
|
||||
/// File-local entity ID within the scene.
|
||||
/// Set by the serializer based on position in the entities list.
|
||||
/// </summary>
|
||||
[JsonPropertyName("fileLocalId")]
|
||||
public int FileLocalId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Editor-only name for the entity.
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = "Entity";
|
||||
|
||||
/// <summary>
|
||||
/// File-local ID of the parent entity, or -1 if root.
|
||||
/// </summary>
|
||||
[JsonPropertyName("parentFileLocalId")]
|
||||
public int ParentFileLocalId { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// All components attached to this entity.
|
||||
/// </summary>
|
||||
[JsonPropertyName("components")]
|
||||
public List<ComponentData> Components { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// JSON-serializable representation of a scene.
|
||||
/// Only used in the editor for saving/loading scenes.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SceneAssetData
|
||||
{
|
||||
/// <summary>
|
||||
/// Scene metadata version for forward compatibility.
|
||||
/// </summary>
|
||||
[JsonPropertyName("version")]
|
||||
public int Version { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier for this scene (GUID).
|
||||
/// </summary>
|
||||
[JsonPropertyName("sceneGuid")]
|
||||
public Guid SceneGuid { get; set; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>
|
||||
/// Editor-friendly name of the scene.
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = "Scene";
|
||||
|
||||
/// <summary>
|
||||
/// Runtime scene ID.
|
||||
/// </summary>
|
||||
[JsonPropertyName("sceneId")]
|
||||
public short SceneId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// All entities in the scene, ordered by file-local ID.
|
||||
/// Index in this list == file-local ID.
|
||||
/// </summary>
|
||||
[JsonPropertyName("entities")]
|
||||
public List<EntityData> Entities { get; set; } = new();
|
||||
}
|
||||
Reference in New Issue
Block a user