2026-07-18 19:50:31 +08:00
|
|
|
namespace OECS;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Accumulates <see cref="EntityChange"/> entries during a system run.
|
|
|
|
|
///
|
|
|
|
|
/// Deduplication: if the same (entity, kind, componentType) change is marked
|
2026-07-18 21:42:08 +08:00
|
|
|
/// multiple times, only one entry is kept. However, if a structurally opposed
|
|
|
|
|
/// change arrives (Added vs Removed) for the same (entity, componentType),
|
|
|
|
|
/// the old entry is removed so observers see the full state transition.
|
2026-07-18 19:50:31 +08:00
|
|
|
/// </summary>
|
|
|
|
|
internal class ChangeSet
|
|
|
|
|
{
|
|
|
|
|
private readonly List<EntityChange> _changes = new();
|
2026-07-18 21:42:08 +08:00
|
|
|
private readonly Dictionary<(Entity Entity, ChangeKind Kind, Type? ComponentType), int> _dedup = new();
|
2026-07-18 19:50:31 +08:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// All accumulated changes in insertion order.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public IReadOnlyList<EntityChange> Changes => _changes;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Number of changes in this set.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public int Count => _changes.Count;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Records that an entity was created.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void MarkEntityAdded(Entity entity)
|
|
|
|
|
{
|
|
|
|
|
TryAdd(new EntityChange(entity, ChangeKind.EntityAdded));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Records that an entity was destroyed.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void MarkEntityRemoved(Entity entity)
|
|
|
|
|
{
|
|
|
|
|
TryAdd(new EntityChange(entity, ChangeKind.EntityRemoved));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Records that a component was added to an entity.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void MarkComponentAdded(Entity entity, Type componentType)
|
|
|
|
|
{
|
|
|
|
|
TryAdd(new EntityChange(entity, ChangeKind.ComponentAdded, componentType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Records that a component was removed from an entity.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void MarkComponentRemoved(Entity entity, Type componentType)
|
|
|
|
|
{
|
|
|
|
|
TryAdd(new EntityChange(entity, ChangeKind.ComponentRemoved, componentType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Records that a component's value was modified.
|
|
|
|
|
/// Must be called explicitly by user code via <see cref="World.MarkModified{T}"/>.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void MarkComponentModified(Entity entity, Type componentType)
|
|
|
|
|
{
|
|
|
|
|
TryAdd(new EntityChange(entity, ChangeKind.ComponentModified, componentType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Clears all accumulated changes.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Clear()
|
|
|
|
|
{
|
|
|
|
|
_changes.Clear();
|
|
|
|
|
_dedup.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void TryAdd(EntityChange change)
|
|
|
|
|
{
|
|
|
|
|
var key = (change.Entity, change.Kind, change.ComponentType);
|
2026-07-18 21:42:08 +08:00
|
|
|
if (_dedup.ContainsKey(key))
|
2026-07-18 19:50:31 +08:00
|
|
|
{
|
2026-07-18 21:42:08 +08:00
|
|
|
// Same (entity, kind, componentType) already recorded — deduplicate.
|
|
|
|
|
return;
|
2026-07-18 19:50:31 +08:00
|
|
|
}
|
2026-07-18 21:42:08 +08:00
|
|
|
|
|
|
|
|
// When a component is re-added after being removed within the same
|
|
|
|
|
// batch, remove the old ComponentRemoved entry so observers see the
|
|
|
|
|
// full Add → Remove → Add sequence.
|
|
|
|
|
if (change.Kind == ChangeKind.ComponentAdded && change.ComponentType != null)
|
|
|
|
|
{
|
|
|
|
|
var removedKey = (change.Entity, ChangeKind.ComponentRemoved, change.ComponentType);
|
|
|
|
|
if (_dedup.Remove(removedKey, out int oldIndex))
|
|
|
|
|
{
|
|
|
|
|
_changes.RemoveAt(oldIndex);
|
|
|
|
|
// Adjust indices for all entries that shifted down.
|
|
|
|
|
foreach (var k in _dedup.Keys.ToList())
|
|
|
|
|
{
|
|
|
|
|
if (_dedup[k] > oldIndex)
|
|
|
|
|
_dedup[k]--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_dedup[key] = _changes.Count;
|
|
|
|
|
_changes.Add(change);
|
2026-07-18 19:50:31 +08:00
|
|
|
}
|
|
|
|
|
}
|