DragonECS/src/Executors/EcsWhereExecutor.cs
2023-05-27 15:59:46 +08:00

96 lines
3.3 KiB
C#

namespace DCFApixels.DragonECS
{
public sealed class EcsWhereExecutor<TSubject> : EcsQueryExecutor where TSubject : EcsSubject
{
private TSubject _subject;
private EcsGroup _filteredGroup;
private long _executeVersion;
private EcsProfilerMarker _executeWhere = new EcsProfilerMarker("Where");
#region Properties
public TSubject Subject => _subject;
internal long ExecuteVersion => _executeVersion;
#endregion
#region OnInitialize/OnDestroy
protected sealed override void OnInitialize()
{
_subject = World.GetSubject<TSubject>();
_filteredGroup = EcsGroup.New(World);
}
protected sealed override void OnDestroy()
{
_filteredGroup.Release();
}
#endregion
#region Methods
public EcsWhereResult<TSubject> Execute() => ExecuteFor(_subject.World.Entities);
public EcsWhereResult<TSubject> ExecuteFor(EcsReadonlyGroup sourceGroup)
{
using (_executeWhere.Auto())
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения.
#endif
//_subject.GetIteratorFor(sourceGroup).CopyTo(_filteredGroup);
var pools = _subject.World._pools;
var mask = _subject.Mask;
_filteredGroup.Clear();
foreach (var e in sourceGroup)
{
for (int i = 0, iMax = mask._inc.Length; i < iMax; i++)
{
if (!pools[mask._inc[i]].Has(e))
goto next;
}
for (int i = 0, iMax = mask._exc.Length; i < iMax; i++)
{
if (pools[mask._exc[i]].Has(e))
goto next;
}
_filteredGroup.AddInternal(e);
next: continue;
}
return new EcsWhereResult<TSubject>(this, _filteredGroup.Readonly);
}
}
#endregion
}
#region WhereExecuter Results
public readonly ref struct EcsWhereResult<TSubject> where TSubject : EcsSubject
{
public readonly TSubject s;
private readonly EcsWhereExecutor<TSubject> _executer;
public readonly EcsReadonlyGroup group;
private readonly long _version;
public bool IsRelevant => _version == _executer.ExecuteVersion;
public EcsWhereResult(EcsWhereExecutor<TSubject> executer, EcsReadonlyGroup group)
{
_executer = executer;
_version = executer.ExecuteVersion;
s = executer.Subject;
this.group = group;
}
public EcsGroup.Enumerator GetEnumerator()
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения.
#endif
return group.GetEnumerator();
}
public override string ToString()
{
return group.ToString();
}
}
#endregion
}