using DCFApixels.DragonECS; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; namespace DCFApixels.DragonECS { public interface IEcsQuery { internal void AddEntity(int entityID); internal void RemoveEntity(int entityID); public EcsQueryMask Mask { get; } } public abstract class EcsQueryBase : IEcsQuery { internal EcsGroup group; internal EcsQueryMask mask; public EcsQueryMask Mask => mask; public void AddEntity(int entityID) => group.Add(entityID); public void RemoveEntity(int entityID) => group.Remove(entityID); [MethodImpl(MethodImplOptions.AggressiveInlining)] void IEcsQuery.AddEntity(int entityID) => group.Add(entityID); [MethodImpl(MethodImplOptions.AggressiveInlining)] void IEcsQuery.RemoveEntity(int entityID) => group.Remove(entityID); } public abstract class EcsQuery : EcsQueryBase where TWorldArchetype : EcsWorld { private int _id; public int ID => _id; public EcsReadonlyGroup entities { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => group.Readonly; } public EcsGroup.Enumerator GetEnumerator() => group.GetEnumerator(); protected virtual void Init(Builder b) { } #region Builder public sealed class Builder : EcsQueryBuilder { private IEcsWorld _world; private List _inc; private List _exc; internal static TQuery Build(IEcsWorld world) where TQuery : IEcsQuery { Builder builder = new Builder(world); Type queryType = typeof(TQuery); ConstructorInfo constructorInfo = queryType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Builder) }, null); EcsQuery newQuery; if (constructorInfo != null) { newQuery = (EcsQuery)constructorInfo.Invoke(new object[] { builder }); } else { newQuery = (EcsQuery)Activator.CreateInstance(typeof(TQuery)); newQuery.Init(builder); } builder.End(out newQuery.mask); newQuery.group = new EcsGroup(world); return (TQuery)(object)newQuery; } private Builder(IEcsWorld world) { _world = world; _inc = new List(8); _exc = new List(4); } public override inc Include() where TComponent : struct { _inc.Add(_world.GetComponentID()); return new inc(_world.GetPool()); } public override exc Exclude() where TComponent : struct { _exc.Add(_world.GetComponentID()); return new exc(_world.GetPool()); } public override opt Optional() where TComponent : struct { return new opt(_world.GetPool()); } private void End(out EcsQueryMask mask) { _inc.Sort(); _exc.Sort(); mask = new EcsQueryMask(_world.ArchetypeType, _inc.ToArray(), _exc.ToArray()); _world = null; _inc.Clear(); _inc = null; _exc.Clear(); _exc = null; } } #endregion } public class EcsQueryMask : EcsMaskBase { public EcsQueryMask(Type worldArchetypeType, int[] inc, int[] exc) { WorldArchetypeType = worldArchetypeType; Inc = inc; Exc = exc; } } public abstract class EcsQueryBuilder { public abstract inc Include() where TComponent : struct; public abstract exc Exclude() where TComponent : struct; public abstract opt Optional() where TComponent : struct; } }