2023-11-20 23:11:17 +00:00
|
|
|
|
using System;
|
|
|
|
|
using MoonTools.ECS.Collections;
|
2022-03-06 06:12:27 +00:00
|
|
|
|
|
2023-11-03 19:40:26 +00:00
|
|
|
|
namespace MoonTools.ECS;
|
|
|
|
|
|
|
|
|
|
public class Filter
|
2022-03-06 06:12:27 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
private World World;
|
|
|
|
|
internal FilterSignature Signature;
|
2023-11-03 19:40:26 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
internal IndexableSet<Entity> EntitySet = new IndexableSet<Entity>();
|
2023-11-03 19:40:26 +00:00
|
|
|
|
|
2023-11-20 23:11:17 +00:00
|
|
|
|
private bool IsDisposed;
|
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
public ReverseSpanEnumerator<Entity> Entities => EntitySet.GetEnumerator();
|
2023-11-03 19:40:26 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
public bool Empty => EntitySet.Count == 0;
|
|
|
|
|
public int Count => EntitySet.Count;
|
2023-11-03 19:40:26 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
// WARNING: this WILL crash if the index is out of range!
|
|
|
|
|
public Entity NthEntity(int index) => EntitySet[index];
|
2023-11-03 19:40:26 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
// WARNING: this WILL crash if the filter is empty!
|
|
|
|
|
public Entity RandomEntity => EntitySet[RandomManager.Next(EntitySet.Count)];
|
|
|
|
|
public RandomEntityEnumerator EntitiesInRandomOrder => new RandomEntityEnumerator(this);
|
2023-11-03 19:40:26 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
internal Filter(World world, FilterSignature signature)
|
|
|
|
|
{
|
|
|
|
|
World = world;
|
|
|
|
|
Signature = signature;
|
2023-11-03 19:40:26 +00:00
|
|
|
|
}
|
2022-04-02 08:00:48 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
public void DestroyAllEntities()
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
foreach (var entity in EntitySet)
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
World.Destroy(entity);
|
2023-11-03 19:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-04-08 05:52:03 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
internal void Check(Entity entity)
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
foreach (var type in Signature.Included)
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
if (!World.Has(entity, type))
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
EntitySet.Remove(entity);
|
|
|
|
|
return;
|
2023-11-03 19:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-17 22:29:38 +00:00
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
foreach (var type in Signature.Excluded)
|
2023-01-27 00:34:15 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
if (World.Has(entity, type))
|
|
|
|
|
{
|
|
|
|
|
EntitySet.Remove(entity);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-01-27 00:34:15 +00:00
|
|
|
|
}
|
2023-11-08 01:46:44 +00:00
|
|
|
|
|
|
|
|
|
EntitySet.Add(entity);
|
2023-11-03 19:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
internal void AddEntity(in Entity entity)
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
EntitySet.Add(entity);
|
2023-11-03 19:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
internal void RemoveEntity(in Entity entity)
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
EntitySet.Remove(entity);
|
2023-11-03 19:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-08 01:46:44 +00:00
|
|
|
|
internal void Clear()
|
2023-11-03 19:40:26 +00:00
|
|
|
|
{
|
2023-11-08 01:46:44 +00:00
|
|
|
|
EntitySet.Clear();
|
2023-11-03 19:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2022-04-08 05:52:03 +00:00
|
|
|
|
}
|
2023-11-20 23:11:17 +00:00
|
|
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
|
{
|
|
|
|
|
if (!IsDisposed)
|
|
|
|
|
{
|
|
|
|
|
if (disposing)
|
|
|
|
|
{
|
|
|
|
|
EntitySet.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IsDisposed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
|
|
|
|
|
// ~Filter()
|
|
|
|
|
// {
|
|
|
|
|
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
|
|
|
// Dispose(disposing: false);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
|
|
|
Dispose(disposing: true);
|
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
|
}
|
2022-03-06 06:12:27 +00:00
|
|
|
|
}
|