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);
}
}