84 lines
2.4 KiB
C#
84 lines
2.4 KiB
C#
|
|
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|