remove old mask/fixes

This commit is contained in:
Mikhail 2023-03-13 01:39:04 +08:00
parent 67aa840be9
commit c3e55cb10b
4 changed files with 88 additions and 187 deletions

View File

@ -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<TInc, TExc>()
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<TWorldArchetype>.ComponentType.types[inc[i]];
}
for (int i = 0; i < sortedInc.Length; i++)
{
sortedExc[i] = EcsWorld<TWorldArchetype>.ComponentType.types[exc[i]];
}
Type thisType = typeof(Activator<TInc, TExc>);
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<TWorldArchetype>.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<TWorldArchetype>.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<TWorldArchetype> : 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<TWorldArchetype, TMask> : BakedMask<TWorldArchetype>
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<TWorldArchetype, TMask>();
}
private BakedMask() : base(
MaskSingleton<TMask>.Instance.MakeInc<IWorldArchetype>(),
MaskSingleton<TMask>.Instance.MakeExc<IWorldArchetype>(),
MaskSingleton<TMask>.Instance)
{ }
private static readonly BakedMask<TWorldArchetype, TMask> _instance;
public static BakedMask<TWorldArchetype, TMask> 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<TWorldArchetype>() where TWorldArchetype : IWorldArchetype;
internal abstract int[] MakeExc<TWorldArchetype>() where TWorldArchetype : IWorldArchetype;
public abstract BakedMask GetBaked<TWorldArchetype>() where TWorldArchetype : IWorldArchetype;
}
public abstract class MaskSingleton<TSelf>
where TSelf : Mask, new()
{
protected static TSelf _instance = new TSelf();
internal static TSelf Instance
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _instance;
}
}
public class Mask<TInc> : Mask where TInc : struct, IInc
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int[] MakeInc<TWorldArchetype>() => new TInc().GetComponentsIDs<TWorldArchetype>().Sort();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int[] MakeExc<TWorldArchetype>() => Array.Empty<int>();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override BakedMask GetBaked<TWorldArchetype>() => BakedMask<TWorldArchetype, Mask<TInc>>.Instance;
}
public class Mask<TInc, TExc> : Mask where TInc : struct, IInc where TExc : struct, IExc
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int[] MakeInc<TWorldArchetype>() => new TInc().GetComponentsIDs<TWorldArchetype>().Sort();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int[] MakeExc<TWorldArchetype>() => new TExc().GetComponentsIDs<TWorldArchetype>().Sort();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override BakedMask GetBaked<TWorldArchetype>() => BakedMask<TWorldArchetype, Mask<TInc, TExc>>.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;

View File

@ -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<TInc>() where TInc : struct, IInc
{
return GetFilterInternal<Mask<TInc>>();
}
public EcsFilter GetFilter<TInc>() where TInc : struct, IInc => GetFilter<TInc, Exc>();
public EcsFilter GetFilter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc
{
return GetFilterInternal<Mask<TInc, TExc>>();
}
private EcsFilter GetFilterInternal<TMask>() where TMask : Mask, new()
{
var bakedmask = BakedMask<TArchetype, TMask>.Instance;
var mask = EcsMaskMap<TArchetype>.GetMask<TInc, Exc>();
if (_filters.Length >= BakedMask<TArchetype>.capacity)
if (_filters.Length <= EcsMaskMap<TArchetype>.Capacity)
{
Array.Resize(ref _filters, BakedMask<TArchetype>.capacity);
Array.Resize(ref _filters, EcsMaskMap<TArchetype>.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<TArchetype>();
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<TArchetype>();
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<T> : ComponentType
internal static class ComponentType<T>
{
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

View File

@ -3,4 +3,8 @@
DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных проверок
public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254
public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей
public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей
#if DEBUG || !DCFAECS_NO_SANITIZE_CHECKS

View File

@ -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<TransfromCom>().position = Vector3.zero;
e.Write<View>().Ref = _sharedData.view1;