forked from sage/MoonTools.ECS.Mirror
More strongly-typed Filters
Requires some very repetitive constructs (no variable-count generics) but simplifies filter iteration for the simplest cases.
This commit is contained in:
parent
76b18a6ba9
commit
50d1ee6035
161
src/Filter.cs
161
src/Filter.cs
|
@ -1,11 +1,166 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using MoonTools.ECS.Collections;
|
||||
|
||||
namespace MoonTools.ECS;
|
||||
|
||||
public class Filter<T> where T : unmanaged
|
||||
{
|
||||
private readonly Filter _underlying;
|
||||
|
||||
internal Filter(Filter underlying)
|
||||
{
|
||||
_underlying = underlying;
|
||||
}
|
||||
|
||||
public TypedEntityEnum<T> GetEnumerator()
|
||||
{
|
||||
return new TypedEntityEnum<T>(_underlying.Entities, _underlying.World);
|
||||
}
|
||||
}
|
||||
|
||||
public ref struct TypedEntityEnum<T> : IEnumerator<(Entity entity, T)> where T : unmanaged
|
||||
{
|
||||
private ReverseSpanEnumerator<Entity> _underlying;
|
||||
private readonly World _world;
|
||||
|
||||
public TypedEntityEnum(ReverseSpanEnumerator<Entity> underlying, World world)
|
||||
{
|
||||
_underlying = underlying;
|
||||
_world = world;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!_underlying.MoveNext())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Entity currentEntity = _underlying.Current;
|
||||
Current = (currentEntity, _world.Get<T>(currentEntity));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public (Entity, T) Current { get; private set; }
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Filter<T1, T2> where T1 : unmanaged where T2 : unmanaged
|
||||
{
|
||||
private readonly Filter _underlying;
|
||||
|
||||
internal Filter(Filter underlying)
|
||||
{
|
||||
_underlying = underlying;
|
||||
}
|
||||
|
||||
public TypedEntityEnum<T1, T2> GetEnumerator()
|
||||
{
|
||||
return new TypedEntityEnum<T1, T2>(_underlying.Entities, _underlying.World);
|
||||
}
|
||||
}
|
||||
|
||||
public ref struct TypedEntityEnum<T1, T2> : IEnumerator<(Entity entity, T1, T2)> where T1 : unmanaged where T2 : unmanaged
|
||||
{
|
||||
private ReverseSpanEnumerator<Entity> _underlying;
|
||||
private readonly World _world;
|
||||
|
||||
public TypedEntityEnum(ReverseSpanEnumerator<Entity> underlying, World world)
|
||||
{
|
||||
_underlying = underlying;
|
||||
_world = world;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!_underlying.MoveNext())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Entity currentEntity = _underlying.Current;
|
||||
Current = (currentEntity, _world.Get<T1>(currentEntity), _world.Get<T2>(currentEntity));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public (Entity, T1, T2) Current { get; private set; }
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Filter<T1, T2, T3> where T1 : unmanaged where T2 : unmanaged where T3 : unmanaged
|
||||
{
|
||||
private readonly Filter _underlying;
|
||||
|
||||
internal Filter(Filter underlying)
|
||||
{
|
||||
_underlying = underlying;
|
||||
}
|
||||
|
||||
public TypedEntityEnum<T1, T2, T3> GetEnumerator()
|
||||
{
|
||||
return new TypedEntityEnum<T1, T2, T3>(_underlying.Entities, _underlying.World);
|
||||
}
|
||||
}
|
||||
|
||||
public ref struct TypedEntityEnum<T1, T2, T3> : IEnumerator<(Entity entity, T1, T2, T3)> where T1 : unmanaged where T2 : unmanaged where T3 : unmanaged
|
||||
{
|
||||
private ReverseSpanEnumerator<Entity> _underlying;
|
||||
private readonly World _world;
|
||||
|
||||
public TypedEntityEnum(ReverseSpanEnumerator<Entity> underlying, World world)
|
||||
{
|
||||
_underlying = underlying;
|
||||
_world = world;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!_underlying.MoveNext())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Entity currentEntity = _underlying.Current;
|
||||
Current = (currentEntity, _world.Get<T1>(currentEntity), _world.Get<T2>(currentEntity), _world.Get<T3>(currentEntity));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public (Entity, T1, T2, T3) Current { get; private set; }
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Filter
|
||||
{
|
||||
private World World;
|
||||
internal World World;
|
||||
internal FilterSignature Signature;
|
||||
|
||||
internal IndexableSet<Entity> EntitySet = new IndexableSet<Entity>();
|
||||
|
@ -17,10 +172,10 @@ public class Filter
|
|||
public bool Empty => EntitySet.Count == 0;
|
||||
public int Count => EntitySet.Count;
|
||||
|
||||
// WARNING: this WILL crash if the index is out of range!
|
||||
/// 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!
|
||||
/// WARNING: this WILL crash if the filter is empty!
|
||||
public Entity RandomEntity => EntitySet[RandomManager.Next(EntitySet.Count)];
|
||||
public RandomEntityEnumerator EntitiesInRandomOrder => new RandomEntityEnumerator(this);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MoonTools.ECS.Collections;
|
||||
using System;
|
||||
using MoonTools.ECS.Collections;
|
||||
|
||||
namespace MoonTools.ECS
|
||||
{
|
||||
|
@ -39,5 +40,20 @@ namespace MoonTools.ECS
|
|||
var signature = new FilterSignature(Included, Excluded);
|
||||
return World.GetFilter(signature);
|
||||
}
|
||||
|
||||
public Filter<T> Of<T>() where T : unmanaged
|
||||
{
|
||||
return new Filter<T>(Include<T>().Build());
|
||||
}
|
||||
|
||||
public Filter<T1, T2> Of<T1, T2>() where T1 : unmanaged where T2 : unmanaged
|
||||
{
|
||||
return new Filter<T1, T2>(Include<T1>().Include<T2>().Build());
|
||||
}
|
||||
|
||||
public Filter<T1, T2, T3> Of<T1, T2, T3>() where T1 : unmanaged where T2 : unmanaged where T3 : unmanaged
|
||||
{
|
||||
return new Filter<T1, T2, T3>(Include<T1>().Include<T2>().Include<T3>().Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue