using MoonTools.ECS.Collections; namespace MoonTools.ECS; // TODO: do we want to get fancy with queries beyond Include and Exclude? public class Filter { private World World; internal FilterSignature Signature; internal IndexableSet EntitySet = new IndexableSet(); public ReverseSpanEnumerator Entities => EntitySet.GetEnumerator(); public bool Empty => EntitySet.Count == 0; public int Count => EntitySet.Count; // WARNING: this WILL crash if the index is out of range! public Entity NthEntity(int index) => EntitySet[index]; // WARNING: this WILL crash if the filter is empty! public Entity RandomEntity => EntitySet[RandomManager.Next(EntitySet.Count)]; public RandomEntityEnumerator EntitiesInRandomOrder => new RandomEntityEnumerator(this); internal Filter(World world, FilterSignature signature) { World = world; Signature = signature; } public void DestroyAllEntities() { foreach (var entity in EntitySet) { World.Destroy(entity); } } internal void Check(Entity entity) { foreach (var type in Signature.Included) { if (!World.Has(entity, type)) { EntitySet.Remove(entity); return; } } foreach (var type in Signature.Excluded) { if (World.Has(entity, type)) { EntitySet.Remove(entity); return; } } EntitySet.Add(entity); } internal void AddEntity(in Entity entity) { EntitySet.Add(entity); } internal void RemoveEntity(in Entity entity) { EntitySet.Remove(entity); } internal void Clear() { EntitySet.Clear(); } public ref struct RandomEntityEnumerator { private Filter Filter; private LinearCongruentialEnumerator LinearCongruentialEnumerator; public RandomEntityEnumerator GetEnumerator() => this; internal RandomEntityEnumerator(Filter filter) { Filter = filter; LinearCongruentialEnumerator = RandomManager.LinearCongruentialSequence(filter.Count); } public bool MoveNext() => LinearCongruentialEnumerator.MoveNext(); public Entity Current => Filter.NthEntity(LinearCongruentialEnumerator.Current); } }