diff --git a/src/EcsFilter.cs b/src/EcsFilter.cs index f222dbc..b9997c0 100644 --- a/src/EcsFilter.cs +++ b/src/EcsFilter.cs @@ -75,15 +75,13 @@ namespace DCFApixels.DragonECS } #endregion - - #region EcsMask public sealed class EcsMask { + internal readonly Type WorldArchetypeType; internal readonly int UniqueID; internal readonly int[] Inc; internal readonly int[] Exc; - internal readonly int Hash; internal int IncCount { @@ -93,10 +91,11 @@ namespace DCFApixels.DragonECS internal int ExcCount { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => Inc.Length; + get => Exc.Length; } - internal EcsMask(int uniqueID, int[] inc, int[] exc) + internal EcsMask(Type worldArchetypeType, int uniqueID, int[] inc, int[] exc) { + WorldArchetypeType = worldArchetypeType; UniqueID = uniqueID; Inc = inc; Exc = exc; @@ -109,6 +108,17 @@ namespace DCFApixels.DragonECS 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 @@ -127,21 +137,26 @@ namespace DCFApixels.DragonECS 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); + 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) { @@ -153,7 +168,7 @@ namespace DCFApixels.DragonECS if (_count >= _capacity) _capacity <<= 1; - instance = new EcsMask(id, inc, exc); + instance = new EcsMask(typeof(TWorldArchetype), id, inc, exc); } public readonly static EcsMask instance; @@ -161,133 +176,11 @@ namespace DCFApixels.DragonECS } #endregion - - #region BakedMask - public abstract class BakedMask - { - internal readonly int[] Inc; - internal readonly int[] Exc; - internal readonly Mask Mask; - - internal int IncCount - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => Inc.Length; - } - internal int ExcCount - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => Exc.Length; - } - - //Уникальный айди в рамках одного архиетипа мира - internal abstract int UniqueID { get; } - internal abstract Type WorldArchetypeType { get; } - - protected BakedMask(int[] inc, int[] exc, Mask mask) - { - Inc = inc; - Exc = exc; - Mask = mask; - } - } - - public abstract class BakedMask : BakedMask - { - internal static int increment = 1; - internal static int capacity = 512; - - protected BakedMask(int[] inc, int[] exc, Mask mask) : base(inc, exc, mask) { } - - - } - - public sealed class BakedMask : BakedMask - where TWorldArchetype : IWorldArchetype - where TMask : Mask, new() - { - public static readonly int uniqueID; - - static BakedMask() - { - uniqueID = increment++; -#if DEBUG || DCFAECS_NO_SANITIZE_CHECKS - if (uniqueID >= ushort.MaxValue) - throw new EcsFrameworkException($"No more room for new BakedMask for this {typeof(TWorldArchetype).FullName} IWorldArchetype"); -#endif - if (increment > capacity) - capacity <<= 1; - - _instance = new BakedMask(); - } - - private BakedMask() : base( - MaskSingleton.Instance.MakeInc(), - MaskSingleton.Instance.MakeExc(), - MaskSingleton.Instance) - { } - - private static readonly BakedMask _instance; - public static BakedMask Instance - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _instance; - } - internal override int UniqueID - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => uniqueID; - } - internal override Type WorldArchetypeType - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => typeof(IWorldArchetype); - } - } - #endregion - - #region Masks - public abstract class Mask - { - internal abstract int[] MakeInc() where TWorldArchetype : IWorldArchetype; - internal abstract int[] MakeExc() where TWorldArchetype : IWorldArchetype; - public abstract BakedMask GetBaked() where TWorldArchetype : IWorldArchetype; - } - public abstract class MaskSingleton - where TSelf : Mask, new() - { - protected static TSelf _instance = new TSelf(); - internal static TSelf Instance - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _instance; - } - } - public class Mask : Mask where TInc : struct, IInc - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int[] MakeInc() => new TInc().GetComponentsIDs().Sort(); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int[] MakeExc() => Array.Empty(); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override BakedMask GetBaked() => BakedMask>.Instance; - } - public class Mask : Mask where TInc : struct, IInc where TExc : struct, IExc - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int[] MakeInc() => new TInc().GetComponentsIDs().Sort(); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal override int[] MakeExc() => new TExc().GetComponentsIDs().Sort(); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override BakedMask GetBaked() => BakedMask>.Instance; - } - #endregion - #region Filter public interface IEcsFilter { public IEcsWorld World { get; } - public BakedMask Mask { get; } + public EcsMask Mask { get; } public IEcsReadonlyGroup Entities { get; } public int EntitiesCount { get; } } @@ -296,7 +189,7 @@ namespace DCFApixels.DragonECS { private readonly IEcsWorld _source; private readonly EcsGroup _entities; - private readonly BakedMask _mask; + private readonly EcsMask _mask; #region Properties public IEcsWorld World @@ -304,7 +197,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _source; } - public BakedMask Mask + public EcsMask Mask { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _mask; @@ -322,7 +215,7 @@ namespace DCFApixels.DragonECS #endregion #region Constrcutors - internal EcsFilter(IEcsWorld source, BakedMask mask, int capasity) + internal EcsFilter(IEcsWorld source, EcsMask mask, int capasity) { _source = source; _mask = mask; diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index a0496b8..8be10df 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -26,8 +26,8 @@ namespace DCFApixels.DragonECS public ent NewEntity(); public void Destroy(); - public bool IsMaskCompatible(Mask mask, int entity); - public bool IsMaskCompatibleWithout(Mask mask, int entity, int otherPoolID); + public bool IsMaskCompatible(EcsMask mask, int entity); + public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherPoolID); internal void OnEntityComponentAdded(int entityID, int changedPoolID); internal void OnEntityComponentRemoved(int entityID, int changedPoolID); @@ -105,31 +105,24 @@ namespace DCFApixels.DragonECS #region GetFilter - public EcsFilter GetFilter() where TInc : struct, IInc - { - return GetFilterInternal>(); - } + public EcsFilter GetFilter() where TInc : struct, IInc => GetFilter(); public EcsFilter GetFilter() where TInc : struct, IInc where TExc : struct, IExc { - return GetFilterInternal>(); - } - private EcsFilter GetFilterInternal() where TMask : Mask, new() - { - var bakedmask = BakedMask.Instance; + var mask = EcsMaskMap.GetMask(); - if (_filters.Length >= BakedMask.capacity) + if (_filters.Length <= EcsMaskMap.Capacity) { - Array.Resize(ref _filters, BakedMask.capacity); + Array.Resize(ref _filters, EcsMaskMap.Capacity); } - if (_filters[bakedmask.UniqueID] == null) + if (_filters[mask.UniqueID] == null) { - _filters[bakedmask.UniqueID] = NewFilter(bakedmask); + _filters[mask.UniqueID] = NewFilter(mask); } - return _filters[bakedmask.UniqueID]; + return _filters[mask.UniqueID]; } - private EcsFilter NewFilter(BakedMask mask, int capacirty = 512) + private EcsFilter NewFilter(EcsMask mask, int capacirty = 512) { var newFilter = new EcsFilter(this, mask, capacirty); @@ -162,19 +155,22 @@ namespace DCFApixels.DragonECS #endregion #region IsMaskCompatible/IsMaskCompatibleWithout - public bool IsMaskCompatible(Mask mask, int entity) + public bool IsMaskCompatible(EcsMask mask, int entity) { - BakedMask bakedMask = mask.GetBaked(); - for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++) +#if DEBUG || !DCFAECS_NO_SANITIZE_CHECKS + if (mask.WorldArchetypeType != typeof(TArchetype)) + throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)"); +#endif + for (int i = 0, iMax = mask.IncCount; i < iMax; i++) { - if (!_pools[bakedMask.Inc[i]].Has(entity)) + if (!_pools[mask.Inc[i]].Has(entity)) { return false; } } - for (int i = 0, iMax = bakedMask.ExcCount; i < iMax; i++) + for (int i = 0, iMax = mask.ExcCount; i < iMax; i++) { - if (_pools[bakedMask.Exc[i]].Has(entity)) + if (_pools[mask.Exc[i]].Has(entity)) { return false; } @@ -182,20 +178,23 @@ namespace DCFApixels.DragonECS return true; } - public bool IsMaskCompatibleWithout(Mask mask, int entity, int otherPoolID) + public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherPoolID) { - BakedMask bakedMask = mask.GetBaked(); - for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++) +#if DEBUG || !DCFAECS_NO_SANITIZE_CHECKS + if (mask.WorldArchetypeType != typeof(TArchetype)) + throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)"); +#endif + for (int i = 0, iMax = mask.IncCount; i < iMax; i++) { - int poolID = bakedMask.Inc[i]; + int poolID = mask.Inc[i]; if (poolID == otherPoolID || !_pools[poolID].Has(entity)) { return false; } } - for (int i = 0, iMax = bakedMask.ExcCount; i < iMax; i++) + for (int i = 0, iMax = mask.ExcCount; i < iMax; i++) { - int poolID = bakedMask.Exc[i]; + int poolID = mask.Exc[i]; if (poolID != otherPoolID && _pools[poolID].Has(entity)) { return false; @@ -215,7 +214,7 @@ namespace DCFApixels.DragonECS { foreach (var filter in includeList) { - if (IsMaskCompatible(filter.Mask.Mask, entityID)) + if (IsMaskCompatible(filter.Mask, entityID)) { filter.Add(entityID); } @@ -225,7 +224,7 @@ namespace DCFApixels.DragonECS { foreach (var filter in excludeList) { - if (IsMaskCompatibleWithout(filter.Mask.Mask, entityID, changedPoolID)) + if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID)) { filter.Remove(entityID); } @@ -242,7 +241,7 @@ namespace DCFApixels.DragonECS { foreach (var filter in includeList) { - if (IsMaskCompatible(filter.Mask.Mask, entityID)) + if (IsMaskCompatible(filter.Mask, entityID)) { filter.Remove(entityID); } @@ -252,7 +251,7 @@ namespace DCFApixels.DragonECS { foreach (var filter in excludeList) { - if (IsMaskCompatibleWithout(filter.Mask.Mask, entityID, changedPoolID)) + if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID)) { filter.Add(entityID); } @@ -278,33 +277,33 @@ namespace DCFApixels.DragonECS #endregion #region Utils - internal abstract class ComponentType + internal static class ComponentType { internal static int increment = 1; internal static int Capacity { get => types.Length; } - internal static Type[] types; + internal static Type[] types = new Type[64]; } - internal sealed class ComponentType : ComponentType + internal static class ComponentType { internal static int uniqueID; static ComponentType() { - uniqueID = increment++; + uniqueID = ComponentType.increment++; #if DEBUG || DCFAECS_NO_SANITIZE_CHECKS - if (increment + 1 > ushort.MaxValue) + if (ComponentType.increment + 1 > ushort.MaxValue) { throw new EcsFrameworkException($"No more room for new component for this {typeof(TArchetype).FullName} IWorldArchetype"); } #endif - if (increment > Capacity) + if (uniqueID >= ComponentType.types.Length) { - Array.Resize(ref types, Capacity << 1); + Array.Resize(ref ComponentType.types, ComponentType.types.Length << 1); } - types[uniqueID] = typeof(T); + ComponentType.types[uniqueID] = typeof(T); } } #endregion diff --git a/src/INFO.txt b/src/INFO.txt index 621e141..51748a4 100644 --- a/src/INFO.txt +++ b/src/INFO.txt @@ -3,4 +3,8 @@ DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных проверок public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254 - public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей \ No newline at end of file + public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей + + + +#if DEBUG || !DCFAECS_NO_SANITIZE_CHECKS diff --git a/test/TestSystem.cs b/test/TestSystem.cs index 2cc0aec..149a958 100644 --- a/test/TestSystem.cs +++ b/test/TestSystem.cs @@ -26,6 +26,11 @@ namespace DCFApixels.DragonECS int has4 = x4.GetHashCode(); int has5 = x5.GetHashCode(); + Debug.Log("1 " + has1); + Debug.Log("2 " + has2); + Debug.Log("3 " + has3); + Debug.Log("4 " + has4); + Debug.Log("5 " + has5); var e = _world.NewEntity(); e.Write().position = Vector3.zero; e.Write().Ref = _sharedData.view1;