oecs-sharp/src/OECS/ChangeSet.cs

84 lines
2.4 KiB
C#
Raw Normal View History

namespace OECS;
/// <summary>
/// Accumulates <see cref="EntityChange"/> entries during a system run.
///
/// Deduplication: if the same (entity, kind, componentType) change is marked
/// multiple times, only one entry is kept. Entity-level changes (Added/Removed)
/// take precedence over component-level changes for the same entity.
/// </summary>
internal class ChangeSet
{
private readonly List<EntityChange> _changes = new();
private readonly HashSet<(Entity Entity, ChangeKind Kind, Type? ComponentType)> _dedup = new();
/// <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);
if (_dedup.Add(key))
{
_changes.Add(change);
}
}
}