using System.Collections.ObjectModel; using Ghost.Entities; namespace Ghost.Editor.Core.SceneGraph.Serialization; /// /// Maps file-local entity IDs to global entity IDs. /// Used when loading scenes to remap entity references from file-local IDs to runtime global IDs. /// public class IdRemapTable { /// /// Maps file-local ID (index) to global Entity ID. /// private readonly Dictionary _localToGlobal; /// /// Maps global Entity ID to file-local ID. /// private readonly Dictionary _globalToLocal; public IdRemapTable() { _localToGlobal = new Dictionary(); _globalToLocal = new Dictionary(); } /// /// Registers the mapping between a file-local ID and global entity ID. /// public void Register(int fileLocalId, Entity globalEntityId) { if (fileLocalId < 0) throw new ArgumentException("File-local ID must be >= 0", nameof(fileLocalId)); _localToGlobal[fileLocalId] = globalEntityId; _globalToLocal[globalEntityId] = fileLocalId; } /// /// Gets the global entity ID for a file-local ID. /// Returns Entity.Invalid if not found. /// public Entity GetGlobalId(int fileLocalId) { _localToGlobal.TryGetValue(fileLocalId, out var globalId); return globalId; } /// /// Gets the file-local ID for a global entity ID. /// Returns -1 if not found. /// public int GetLocalId(Entity globalEntityId) { return _globalToLocal.TryGetValue(globalEntityId, out var localId) ? localId : -1; } /// /// Remaps an entity reference from file-local ID to global ID. /// Throws if the file-local ID is not registered. /// public Entity RemapReference(int fileLocalId) { if (!_localToGlobal.TryGetValue(fileLocalId, out var globalId)) { throw new KeyNotFoundException($"File-local entity ID {fileLocalId} not found in remap table."); } return globalId; } /// /// Gets the count of mapped entities. /// public int Count => _localToGlobal.Count; /// /// Gets all mapped local->global pairs. /// public IEnumerable> GetMappings() { return _localToGlobal.AsEnumerable(); } } /// /// Contains context information for loading or saving a scene. /// Includes component type information and entity remapping logic. /// public class SceneSerializationContext { /// /// Maps file-local entity IDs to runtime global entity IDs. /// public IdRemapTable IdRemap { get; } /// /// Scene ID being serialized/deserialized. /// public short SceneId { get; } /// /// Editor world where entities are being loaded/saved. /// public World EditorWorld { get; } /// /// List of entities in the order they appear in the saved file. /// Index corresponds to file-local ID. /// public List EntityOrder { get; } /// /// Validation errors encountered during serialization. /// public List ValidationErrors { get; } public SceneSerializationContext(short sceneId, World editorWorld) { SceneId = sceneId; EditorWorld = editorWorld ?? throw new ArgumentNullException(nameof(editorWorld)); IdRemap = new IdRemapTable(); EntityOrder = new List(); ValidationErrors = new List(); } /// /// Adds a validation error message. /// public void AddValidationError(string message) { ValidationErrors.Add(message); } /// /// Returns true if there are any validation errors. /// public bool HasErrors => ValidationErrors.Count > 0; /// /// Gets all validation errors as a single string. /// public string GetErrorsSummary() { return string.Join("\n", ValidationErrors); } }