diff --git a/src/EcsFilter.cs b/src/EcsFilter.cs index 8e8e643..f222dbc 100644 --- a/src/EcsFilter.cs +++ b/src/EcsFilter.cs @@ -1,17 +1,18 @@ using System; using System.Runtime.CompilerServices; +using System.Reflection; namespace DCFApixels.DragonECS { #region Incs/Excs base - public interface ICondition + public interface IMaskCondition { public int[] GetComponentsIDs() where TWorldArchetype : IWorldArchetype; } #endregion #region Incs - public interface IInc : ICondition { } + public interface IInc : IMaskCondition { } public struct Inc : IInc { @@ -43,7 +44,7 @@ namespace DCFApixels.DragonECS #endregion #region Excs - public interface IExc : ICondition { } + public interface IExc : IMaskCondition { } public struct Exc : IExc { @@ -74,6 +75,93 @@ namespace DCFApixels.DragonECS } #endregion + + + #region EcsMask + public sealed class EcsMask + { + internal readonly int UniqueID; + internal readonly int[] Inc; + internal readonly int[] Exc; + internal readonly int Hash; + + internal int IncCount + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => Inc.Length; + } + internal int ExcCount + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => Inc.Length; + } + internal EcsMask(int uniqueID, int[] inc, int[] exc) + { + UniqueID = uniqueID; + Inc = inc; + Exc = exc; + } + } + + public static class EcsMaskMap + where TWorldArchetype : IWorldArchetype + { + private static int _count; + private static int _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[] sortedInc = new Type[inc.Length]; + Type[] sortedExc = new Type[exc.Length]; + for (int i = 0; i < sortedInc.Length; i++) + { + sortedInc[i] = EcsWorld.ComponentType.types[inc[i]]; + } + for (int i = 0; i < sortedInc.Length; i++) + { + sortedExc[i] = EcsWorld.ComponentType.types[exc[i]]; + } + Type thisType = typeof(Activator); + Type sortedIncType = typeof(TInc).GetGenericTypeDefinition().MakeGenericType(sortedInc); + Type sortedExcType = typeof(TExc).GetGenericTypeDefinition().MakeGenericType(sortedExc); + + Type targetType = typeof(Activator<,>).MakeGenericType(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(id, inc, exc); + } + + public readonly static EcsMask instance; + } + } + #endregion + + #region BakedMask public abstract class BakedMask { @@ -193,16 +281,6 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public override BakedMask GetBaked() => BakedMask>.Instance; } - - internal static class ArrayExt - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static T[] Sort(this T[] self) - { - Array.Sort(self); - return self; - } - } #endregion #region Filter @@ -267,4 +345,19 @@ namespace DCFApixels.DragonECS #endregion } #endregion + + #region Utils + internal static class ArrayExt + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static T[] Sort(this T[] self) + { + Array.Sort(self); + + return self; + } + + + } + #endregion } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 58226e1..a0496b8 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -90,9 +90,9 @@ namespace DCFApixels.DragonECS if (uniqueID >= _pools.Length) { - Array.Resize(ref _pools, ComponentType.capacity); - Array.Resize(ref _filtersByIncludedComponents, ComponentType.capacity); - Array.Resize(ref _filtersByExcludedComponents, ComponentType.capacity); + Array.Resize(ref _pools, ComponentType.Capacity); + Array.Resize(ref _filtersByIncludedComponents, ComponentType.Capacity); + Array.Resize(ref _filtersByExcludedComponents, ComponentType.Capacity); } if (_pools[uniqueID] == null) @@ -281,7 +281,11 @@ namespace DCFApixels.DragonECS internal abstract class ComponentType { internal static int increment = 1; - internal static int capacity = 512; + internal static int Capacity + { + get => types.Length; + } + internal static Type[] types; } internal sealed class ComponentType : ComponentType { @@ -296,11 +300,11 @@ namespace DCFApixels.DragonECS throw new EcsFrameworkException($"No more room for new component for this {typeof(TArchetype).FullName} IWorldArchetype"); } #endif - - if (increment > capacity) + if (increment > Capacity) { - capacity <<= 1; + Array.Resize(ref types, Capacity << 1); } + types[uniqueID] = typeof(T); } } #endregion