using System; using System.Runtime.CompilerServices; using System.Reflection; namespace DCFApixels.DragonECS { #region Incs/Excs base public interface IMaskCondition { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld; } #endregion #region Incs public interface IInc : IMaskCondition { } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld => Array.Empty(); } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Inc : IInc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } #endregion #region Excs public interface IExc : IMaskCondition { } public struct Exc : IExc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld => Array.Empty(); } public struct Exc : IExc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, }; } } public struct Exc : IExc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Exc : IExc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Exc : IExc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Exc : IExc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } public struct Exc : IExc { public int[] GetComponentsIDs() where TWorldArchetype : EcsWorld { return new int[] { EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, EcsWorld.ComponentType.uniqueID, }; } } #endregion #region EcsMask public sealed class EcsMask { internal readonly Type WorldArchetypeType; internal readonly int UniqueID; internal readonly int[] Inc; internal readonly int[] Exc; internal int IncCount { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Inc.Length; } internal int ExcCount { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Exc.Length; } internal EcsMask(Type worldArchetypeType, int uniqueID, int[] inc, int[] exc) { WorldArchetypeType = worldArchetypeType; UniqueID = uniqueID; Inc = inc; Exc = exc; } } public static class EcsMaskMap where TWorldArchetype : EcsWorld { private static int _count; private static int _capacity; public static int Count { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _count; } public static int Capacity { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _capacity; } public static EcsMask GetMask() where TInc : struct, IInc where TExc : struct, IExc { return Activator.instance; } private class Activator where TInc : struct, IInc where TExc : struct, IExc { static Activator() { var inc = new TInc().GetComponentsIDs(); var exc = new TExc().GetComponentsIDs(); Array.Sort(inc); Array.Sort(exc); Type thisType = typeof(Activator); Type sortedIncType = typeof(TInc); if (sortedIncType.IsGenericType) { Type[] sortedInc = new Type[inc.Length]; for (int i = 0; i < sortedInc.Length; i++) sortedInc[i] = EcsWorld.ComponentType.types[inc[i]]; sortedIncType = sortedIncType.GetGenericTypeDefinition().MakeGenericType(sortedInc); } Type sortedExcType = typeof(TExc); if (sortedExcType.IsGenericType) { Type[] sortedExc = new Type[exc.Length]; for (int i = 0; i < sortedExc.Length; i++) sortedExc[i] = EcsWorld.ComponentType.types[exc[i]]; sortedExcType = sortedExcType.GetGenericTypeDefinition().MakeGenericType(sortedExc); } Type targetType = typeof(Activator<,>).MakeGenericType(typeof(TWorldArchetype), sortedIncType, sortedExcType); if (targetType != thisType) { instance = (EcsMask)targetType.GetField(nameof(instance), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null); return; } var id = _count++; if (_count >= _capacity) _capacity <<= 1; instance = new EcsMask(typeof(TWorldArchetype), id, inc, exc); } public readonly static EcsMask instance; } } #endregion }