DragonECS/src/EcsFilter.cs

141 lines
3.5 KiB
C#
Raw Normal View History

2023-02-07 17:11:56 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
public interface IEcsFilter
{
public EcsWorld World { get; }
public int EntitiesCount { get; }
}
public class EcsFilter : IEcsFilter
{
private readonly EcsWorld _source;
private readonly EcsWorld.Mask _mask;
private readonly SparseSet _entities;
private DelayedOp[] _delayedOps;
2023-02-08 17:07:39 +08:00
private int _delayedOpsCount;
2023-02-07 17:11:56 +08:00
private int _lockCount;
#region Properties
public EcsWorld World => _source;
public int EntitiesCount => _entities.Count;
#endregion
#region Constrcutors
internal EcsFilter(EcsWorld source, EcsWorld.Mask mask, int capasity)
{
_source = source;
_mask = mask;
_entities = new SparseSet(capasity);
_delayedOps = new DelayedOp[512];
_lockCount = 0;
}
#endregion
internal void Change(int entityID, bool isAdd)
{
if (isAdd)
Add(entityID);
else
Del(entityID);
}
internal void Add(int entityID)
{
if (_lockCount > 0)
2023-02-08 17:07:39 +08:00
AddDelayedOp(entityID, true);
2023-02-07 17:11:56 +08:00
_entities.Add(entityID);
}
internal void Del(int entityID)
{
if (_lockCount > 0)
AddDelayedOp(entityID, false);
_entities.Remove(entityID);
}
private void AddDelayedOp(int entityID, bool isAdd)
{
2023-02-08 17:07:39 +08:00
if(_delayedOpsCount >= _delayedOps.Length)
{
Array.Resize(ref _delayedOps, _delayedOps.Length << 1);
}
_delayedOps[_delayedOpsCount].Entity = entityID;
_delayedOps[_delayedOpsCount].Added = isAdd;
2023-02-07 17:11:56 +08:00
}
#region GetEnumerator
private void Unlock()
{
#if DEBUG
2023-02-08 17:07:39 +08:00
if (_lockCount <= 0)
{
throw new Exception($"Invalid lock-unlock balance for {nameof(EcsFilter)}.");
}
2023-02-07 17:11:56 +08:00
#endif
_lockCount--;
2023-02-08 17:07:39 +08:00
if (_lockCount <= 0)
{
for (int i = 0; i < _delayedOpsCount; i++)
{
}
}
2023-02-07 17:11:56 +08:00
}
public Enumerator GetEnumerator()
{
_lockCount++;
return new Enumerator(this);
}
#endregion
#region Utils
public ref struct Enumerator
{
readonly EcsFilter _source;
readonly SparseSet _entities;
int _index;
public Enumerator(EcsFilter filter)
{
_source = filter;
_entities = filter._entities;
_index = -1;
}
public int Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _entities[_index];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
return ++_index < _entities.Count;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose()
{
_source.Unlock();
}
}
2023-02-08 17:07:39 +08:00
private struct DelayedOp
2023-02-07 17:11:56 +08:00
{
public bool Added;
public int Entity;
}
#endregion
}
}