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 #endregion
#region EcsMask #region EcsMask
public sealed class EcsMask public sealed class EcsMask
{ {
internal readonly Type WorldArchetypeType;
internal readonly int UniqueID; internal readonly int UniqueID;
internal readonly int[] Inc; internal readonly int[] Inc;
internal readonly int[] Exc; internal readonly int[] Exc;
internal readonly int Hash;
internal int IncCount internal int IncCount
{ {
@ -93,10 +91,11 @@ namespace DCFApixels.DragonECS
internal int ExcCount internal int ExcCount
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [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; UniqueID = uniqueID;
Inc = inc; Inc = inc;
Exc = exc; Exc = exc;
@ -109,6 +108,17 @@ namespace DCFApixels.DragonECS
private static int _count; private static int _count;
private static int _capacity; 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>() public static EcsMask GetMask<TInc, TExc>()
where TInc : struct, IInc where TInc : struct, IInc
where TExc : struct, IExc where TExc : struct, IExc
@ -127,21 +137,26 @@ namespace DCFApixels.DragonECS
Array.Sort(inc); Array.Sort(inc);
Array.Sort(exc); 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 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) if(targetType != thisType)
{ {
@ -153,7 +168,7 @@ namespace DCFApixels.DragonECS
if (_count >= _capacity) if (_count >= _capacity)
_capacity <<= 1; _capacity <<= 1;
instance = new EcsMask(id, inc, exc); instance = new EcsMask(typeof(TWorldArchetype), id, inc, exc);
} }
public readonly static EcsMask instance; public readonly static EcsMask instance;
@ -161,133 +176,11 @@ namespace DCFApixels.DragonECS
} }
#endregion #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 #region Filter
public interface IEcsFilter public interface IEcsFilter
{ {
public IEcsWorld World { get; } public IEcsWorld World { get; }
public BakedMask Mask { get; } public EcsMask Mask { get; }
public IEcsReadonlyGroup Entities { get; } public IEcsReadonlyGroup Entities { get; }
public int EntitiesCount { get; } public int EntitiesCount { get; }
} }
@ -296,7 +189,7 @@ namespace DCFApixels.DragonECS
{ {
private readonly IEcsWorld _source; private readonly IEcsWorld _source;
private readonly EcsGroup _entities; private readonly EcsGroup _entities;
private readonly BakedMask _mask; private readonly EcsMask _mask;
#region Properties #region Properties
public IEcsWorld World public IEcsWorld World
@ -304,7 +197,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source; get => _source;
} }
public BakedMask Mask public EcsMask Mask
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _mask; get => _mask;
@ -322,7 +215,7 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Constrcutors #region Constrcutors
internal EcsFilter(IEcsWorld source, BakedMask mask, int capasity) internal EcsFilter(IEcsWorld source, EcsMask mask, int capasity)
{ {
_source = source; _source = source;
_mask = mask; _mask = mask;

View File

@ -26,8 +26,8 @@ namespace DCFApixels.DragonECS
public ent NewEntity(); public ent NewEntity();
public void Destroy(); public void Destroy();
public bool IsMaskCompatible(Mask mask, int entity); public bool IsMaskCompatible(EcsMask mask, int entity);
public bool IsMaskCompatibleWithout(Mask mask, int entity, int otherPoolID); public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherPoolID);
internal void OnEntityComponentAdded(int entityID, int changedPoolID); internal void OnEntityComponentAdded(int entityID, int changedPoolID);
internal void OnEntityComponentRemoved(int entityID, int changedPoolID); internal void OnEntityComponentRemoved(int entityID, int changedPoolID);
@ -105,31 +105,24 @@ namespace DCFApixels.DragonECS
#region GetFilter #region GetFilter
public EcsFilter GetFilter<TInc>() where TInc : struct, IInc public EcsFilter GetFilter<TInc>() where TInc : struct, IInc => GetFilter<TInc, Exc>();
{
return GetFilterInternal<Mask<TInc>>();
}
public EcsFilter GetFilter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc public EcsFilter GetFilter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc
{ {
return GetFilterInternal<Mask<TInc, TExc>>(); var mask = EcsMaskMap<TArchetype>.GetMask<TInc, Exc>();
}
private EcsFilter GetFilterInternal<TMask>() where TMask : Mask, new()
{
var bakedmask = BakedMask<TArchetype, TMask>.Instance;
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); var newFilter = new EcsFilter(this, mask, capacirty);
@ -162,19 +155,22 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region IsMaskCompatible/IsMaskCompatibleWithout #region IsMaskCompatible/IsMaskCompatibleWithout
public bool IsMaskCompatible(Mask mask, int entity) public bool IsMaskCompatible(EcsMask mask, int entity)
{ {
BakedMask bakedMask = mask.GetBaked<TArchetype>(); #if DEBUG || !DCFAECS_NO_SANITIZE_CHECKS
for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++) 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; 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; return false;
} }
@ -182,20 +178,23 @@ namespace DCFApixels.DragonECS
return true; 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>(); #if DEBUG || !DCFAECS_NO_SANITIZE_CHECKS
for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++) 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)) if (poolID == otherPoolID || !_pools[poolID].Has(entity))
{ {
return false; 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)) if (poolID != otherPoolID && _pools[poolID].Has(entity))
{ {
return false; return false;
@ -215,7 +214,7 @@ namespace DCFApixels.DragonECS
{ {
foreach (var filter in includeList) foreach (var filter in includeList)
{ {
if (IsMaskCompatible(filter.Mask.Mask, entityID)) if (IsMaskCompatible(filter.Mask, entityID))
{ {
filter.Add(entityID); filter.Add(entityID);
} }
@ -225,7 +224,7 @@ namespace DCFApixels.DragonECS
{ {
foreach (var filter in excludeList) foreach (var filter in excludeList)
{ {
if (IsMaskCompatibleWithout(filter.Mask.Mask, entityID, changedPoolID)) if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID))
{ {
filter.Remove(entityID); filter.Remove(entityID);
} }
@ -242,7 +241,7 @@ namespace DCFApixels.DragonECS
{ {
foreach (var filter in includeList) foreach (var filter in includeList)
{ {
if (IsMaskCompatible(filter.Mask.Mask, entityID)) if (IsMaskCompatible(filter.Mask, entityID))
{ {
filter.Remove(entityID); filter.Remove(entityID);
} }
@ -252,7 +251,7 @@ namespace DCFApixels.DragonECS
{ {
foreach (var filter in excludeList) foreach (var filter in excludeList)
{ {
if (IsMaskCompatibleWithout(filter.Mask.Mask, entityID, changedPoolID)) if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID))
{ {
filter.Add(entityID); filter.Add(entityID);
} }
@ -278,33 +277,33 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Utils #region Utils
internal abstract class ComponentType internal static class ComponentType
{ {
internal static int increment = 1; internal static int increment = 1;
internal static int Capacity internal static int Capacity
{ {
get => types.Length; 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; internal static int uniqueID;
static ComponentType() static ComponentType()
{ {
uniqueID = increment++; uniqueID = ComponentType.increment++;
#if DEBUG || DCFAECS_NO_SANITIZE_CHECKS #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"); throw new EcsFrameworkException($"No more room for new component for this {typeof(TArchetype).FullName} IWorldArchetype");
} }
#endif #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 #endregion

View File

@ -3,4 +3,8 @@
DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных проверок DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных проверок
public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254 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 has4 = x4.GetHashCode();
int has5 = x5.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(); var e = _world.NewEntity();
e.Write<TransfromCom>().position = Vector3.zero; e.Write<TransfromCom>().position = Vector3.zero;
e.Write<View>().Ref = _sharedData.view1; e.Write<View>().Ref = _sharedData.view1;