This commit is contained in:
Mikhail 2024-10-02 22:13:10 +08:00
parent 5bebf812f1
commit a0e359bb12
16 changed files with 364 additions and 124 deletions

7
notes.txt.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e1e8de2a01be77f42b72fd7ba8c81570
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -57,7 +57,7 @@ namespace DCFApixels.DragonECS
private MetaGroup _group; private MetaGroup _group;
private IReadOnlyList<string> _tags; private IReadOnlyList<string> _tags;
private string _metaID; private string _metaID;
private int _typeCode; private EcsTypeCode _typeCode;
private InitFlag _initFlags = InitFlag.None; private InitFlag _initFlags = InitFlag.None;
@ -77,7 +77,7 @@ namespace DCFApixels.DragonECS
_group = new MetaGroup(""), _group = new MetaGroup(""),
_tags = Array.Empty<string>(), _tags = Array.Empty<string>(),
_metaID = string.Empty, _metaID = string.Empty,
_typeCode = EcsTypeCode.Get(typeof(void)), _typeCode = EcsTypeCodeManager.Get(typeof(void)),
_initFlags = InitFlag.All, _initFlags = InitFlag.All,
}; };
@ -250,13 +250,13 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region TypeCode #region TypeCode
public int TypeCode public EcsTypeCode TypeCode
{ {
get get
{ {
if (_initFlags.HasFlag(InitFlag.TypeCode) == false) if (_initFlags.HasFlag(InitFlag.TypeCode) == false)
{ {
_typeCode = EcsTypeCode.Get(_type); _typeCode = EcsTypeCodeManager.Get(_type);
_initFlags |= InitFlag.TypeCode; _initFlags |= InitFlag.TypeCode;
} }
return _typeCode; return _typeCode;

View File

@ -166,11 +166,11 @@ namespace DCFApixels.DragonECS
} }
private void IncludeImplicit(Type type) private void IncludeImplicit(Type type)
{ {
_maskBuilder.Include(type); _maskBuilder.Inc(type);
} }
private void ExcludeImplicit(Type type) private void ExcludeImplicit(Type type)
{ {
_maskBuilder.Exclude(type); _maskBuilder.Exc(type);
} }
public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new() public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new()
{ {

View File

@ -1,14 +1,188 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices;
#endif
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices; [Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif
public sealed class EcsStaticMask : IEquatable<EcsStaticMask>
{
private static ConcurrentDictionary<Key, EcsStaticMask> _ids = new ConcurrentDictionary<Key, EcsStaticMask>();
private static IdDispenser _idDIspenser = new IdDispenser(nullID: 0);
private static object _lock = new object();
private readonly int _id;
/// <summary> Sorted </summary>
private readonly EcsTypeCode[] _inc;
/// <summary> Sorted </summary>
private readonly EcsTypeCode[] _exc;
#region Properties
public int ID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _id; }
}
/// <summary> Sorted set including constraints presented as global type codes. </summary>
public ReadOnlySpan<EcsTypeCode> IncTypeCodes
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _inc; }
}
/// <summary> Sorted set excluding constraints presented as global type codes. </summary>
public ReadOnlySpan<EcsTypeCode> ExcTypeCodes
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _exc; }
}
#endregion
#region Constrcutors
public static Builder New() { return new Builder(); }
public static Builder Inc<T>() { return new Builder().Inc<T>(); }
public static Builder Exc<T>() { return new Builder().Exc<T>(); }
private EcsStaticMask(int id, Key key)
{
_id = id;
_inc = key.inc;
_exc = key.exc;
}
#endregion
#region Methods
public EcsMask ToMask(EcsWorld world)
{
return EcsMask.FromStatic(world, this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(EcsStaticMask other) { return _id == other._id; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() { return _id; }
public override bool Equals(object obj) { return Equals((EcsStaticMask)obj); }
public override string ToString() { return $"s_mask({_id})"; }
#endregion
#region Builder
private readonly struct Key : IEquatable<Key>
{
public readonly EcsTypeCode[] inc;
public readonly EcsTypeCode[] exc;
public readonly int hash;
#region Constructors
public Key(EcsTypeCode[] inc, EcsTypeCode[] exc)
{
this.inc = inc;
this.exc = exc;
unchecked
{
hash = inc.Length + exc.Length;
for (int i = 0, iMax = inc.Length; i < iMax; i++)
{
hash = hash * EcsConsts.MAGIC_PRIME + (int)inc[i];
}
for (int i = 0, iMax = exc.Length; i < iMax; i++)
{
hash = hash * EcsConsts.MAGIC_PRIME - (int)exc[i];
}
}
}
#endregion
#region Object
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Key other)
{
if (inc.Length != other.inc.Length) { return false; }
if (exc.Length != other.exc.Length) { return false; }
for (int i = 0; i < inc.Length; i++)
{
if (inc[i] != other.inc[i]) { return false; }
}
for (int i = 0; i < exc.Length; i++)
{
if (exc[i] != other.exc[i]) { return false; }
}
return true;
}
public override bool Equals(object obj) { return Equals((Key)obj); }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() { return hash; }
#endregion
}
public class Builder
{
private readonly HashSet<EcsTypeCode> _inc = new HashSet<EcsTypeCode>();
private readonly HashSet<EcsTypeCode> _exc = new HashSet<EcsTypeCode>();
#region Constrcutors
internal Builder() { }
#endregion
#region Include/Exclude/Combine
public Builder Inc<T>() { return Inc(EcsTypeCodeManager.Get<T>()); }
public Builder Exc<T>() { return Exc(EcsTypeCodeManager.Get<T>()); }
public Builder Inc(Type type) { return Inc(EcsTypeCodeManager.Get(type)); }
public Builder Exc(Type type) { return Exc(EcsTypeCodeManager.Get(type)); }
public Builder Inc(EcsTypeCode typeCode)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(typeCode) || _exc.Contains(typeCode)) { Throw.ConstraintIsAlreadyContainedInMask(); }
#endif
_inc.Add(typeCode);
return this;
}
public Builder Exc(EcsTypeCode typeCode)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(typeCode) || _exc.Contains(typeCode)) { Throw.ConstraintIsAlreadyContainedInMask(); }
#endif
_exc.Add(typeCode);
return this;
}
#endregion
#region Build
public EcsStaticMask Build()
{
HashSet<EcsTypeCode> combinedIncs = _inc;
HashSet<EcsTypeCode> combinedExcs = _exc;
var inc = combinedIncs.ToArray();
Array.Sort(inc);
var exc = combinedExcs.ToArray();
Array.Sort(exc);
var key = new Key(inc, exc);
if (_ids.TryGetValue(key, out EcsStaticMask result) == false)
{
lock (_lock)
{
if (_ids.TryGetValue(key, out result) == false)
{
result = new EcsStaticMask(_idDIspenser.UseFree(), key);
_ids[key] = result;
}
}
}
return result;
}
#endregion
}
#endregion
}
#if ENABLE_IL2CPP
[Il2CppSetOption (Option.NullChecks, false)] [Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
@ -19,36 +193,44 @@ namespace DCFApixels.DragonECS
internal readonly short _worldID; internal readonly short _worldID;
internal readonly EcsMaskChunck[] _incChunckMasks; internal readonly EcsMaskChunck[] _incChunckMasks;
internal readonly EcsMaskChunck[] _excChunckMasks; internal readonly EcsMaskChunck[] _excChunckMasks;
internal readonly int[] _inc; //Sorted /// <summary> Sorted </summary>
internal readonly int[] _exc; //Sorted internal readonly int[] _inc;
/// <summary> Sorted </summary>
internal readonly int[] _exc;
private EcsMaskIterator _iterator; private EcsMaskIterator _iterator;
#region Properties #region Properties
public int ID public int ID
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _id; } get { return _id; }
} }
public short WorldID public short WorldID
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _worldID; } get { return _worldID; }
} }
public EcsWorld World public EcsWorld World
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return EcsWorld.GetWorld(_worldID); } get { return EcsWorld.GetWorld(_worldID); }
} }
/// <summary>Including constraints</summary> /// <summary> Sorted set including constraints. </summary>
public ReadOnlySpan<int> Inc public ReadOnlySpan<int> Inc
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _inc; } get { return _inc; }
} }
/// <summary>Excluding constraints</summary> /// <summary> Sorted set excluding constraints. </summary>
public ReadOnlySpan<int> Exc public ReadOnlySpan<int> Exc
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _exc; } get { return _exc; }
} }
public bool IsEmpty public bool IsEmpty
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _inc.Length == 0 && _exc.Length == 0; } get { return _inc.Length == 0 && _exc.Length == 0; }
} }
public bool IsBroken public bool IsBroken
@ -58,32 +240,28 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Constructors #region Constructors
public static Builder New(EcsWorld world) public static Builder New(EcsWorld world) { return new Builder(world); }
{ internal static EcsMask Create(int id, short worldID, int[] inc, int[] exc)
return new Builder(world);
}
internal static EcsMask New(int id, short worldID, int[] inc, int[] exc)
{ {
#if DEBUG #if DEBUG
CheckConstraints(inc, exc); CheckConstraints(inc, exc);
#endif #endif
return new EcsMask(id, worldID, inc, exc); return new EcsMask(id, worldID, inc, exc);
} }
internal static EcsMask NewEmpty(int id, short worldID) internal static EcsMask CreateEmpty(int id, short worldID)
{ {
return new EcsMask(id, worldID, new int[0], new int[0]); return new EcsMask(id, worldID, new int[0], new int[0]);
} }
internal static EcsMask NewBroken(int id, short worldID) internal static EcsMask CreateBroken(int id, short worldID)
{ {
return new EcsMask(id, worldID, new int[1] { 1 }, new int[1] { 1 }); return new EcsMask(id, worldID, new int[1] { 1 }, new int[1] { 1 });
} }
private EcsMask(int id, short worldID, int[] inc, int[] exc) private EcsMask(int id, short worldID, int[] inc, int[] exc)
{ {
this._id = id; _id = id;
this._inc = inc; _inc = inc;
this._exc = exc; _exc = exc;
this._worldID = worldID; _worldID = worldID;
_incChunckMasks = MakeMaskChuncsArray(inc); _incChunckMasks = MakeMaskChuncsArray(inc);
_excChunckMasks = MakeMaskChuncsArray(exc); _excChunckMasks = MakeMaskChuncsArray(exc);
@ -343,38 +521,48 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region AbstractMask
public static EcsMask FromStatic(EcsWorld world, EcsStaticMask abstractMask)
{
return world.Get<WorldMaskComponent>().ConvertFromAbstract(abstractMask);
}
#endregion
#region Builder #region Builder
private readonly struct WorldMaskComponent : IEcsWorldComponent<WorldMaskComponent> private readonly struct WorldMaskComponent : IEcsWorldComponent<WorldMaskComponent>
{ {
private readonly EcsWorld _world; private readonly EcsWorld _world;
private readonly Dictionary<Key, EcsMask> _masks; private readonly Dictionary<Key, EcsMask> _masks;
private readonly Dictionary<OpMaskKey, EcsMask> _opMasks; private readonly Dictionary<OpMaskKey, EcsMask> _opMasks;
private readonly SparseArray<EcsMask> _abstractMasks;
public readonly EcsMask EmptyMask; public readonly EcsMask EmptyMask;
public readonly EcsMask BrokenMask; public readonly EcsMask BrokenMask;
#region Constructor/Destructor #region Constructor/Destructor
public WorldMaskComponent(EcsWorld world, Dictionary<Key, EcsMask> masks, Dictionary<OpMaskKey, EcsMask> opMasks, EcsMask emptyMask, EcsMask brokenMask) public WorldMaskComponent(EcsWorld world, Dictionary<Key, EcsMask> masks, EcsMask emptyMask, EcsMask brokenMask)
{ {
_world = world; _world = world;
_masks = masks; _masks = masks;
_opMasks = opMasks; _opMasks = new Dictionary<OpMaskKey, EcsMask>(256);
_abstractMasks = new SparseArray<EcsMask>(256);
EmptyMask = emptyMask; EmptyMask = emptyMask;
BrokenMask = brokenMask; BrokenMask = brokenMask;
} }
public void Init(ref WorldMaskComponent component, EcsWorld world) public void Init(ref WorldMaskComponent component, EcsWorld world)
{ {
var masks = new Dictionary<Key, EcsMask>(256); var masks = new Dictionary<Key, EcsMask>(256);
EcsMask emptyMask = NewEmpty(0, world.id); EcsMask emptyMask = CreateEmpty(0, world.id);
EcsMask brokenMask = NewBroken(1, world.id); EcsMask brokenMask = CreateBroken(1, world.id);
masks.Add(new Key(emptyMask._inc, emptyMask._exc), emptyMask); masks.Add(new Key(emptyMask._inc, emptyMask._exc), emptyMask);
masks.Add(new Key(brokenMask._inc, brokenMask._exc), brokenMask); masks.Add(new Key(brokenMask._inc, brokenMask._exc), brokenMask);
component = new WorldMaskComponent(world, masks, new Dictionary<OpMaskKey, EcsMask>(256), emptyMask, brokenMask); component = new WorldMaskComponent(world, masks, emptyMask, brokenMask);
} }
public void OnDestroy(ref WorldMaskComponent component, EcsWorld world) public void OnDestroy(ref WorldMaskComponent component, EcsWorld world)
{ {
component._masks.Clear(); component._masks.Clear();
component._opMasks.Clear(); component._opMasks.Clear();
component._abstractMasks.Clear();
component = default; component = default;
} }
#endregion #endregion
@ -394,11 +582,29 @@ namespace DCFApixels.DragonECS
} }
return result; return result;
} }
internal EcsMask ConvertFromAbstract(EcsStaticMask abstractMask)
{
if (_abstractMasks.TryGetValue(abstractMask.ID, out EcsMask result) == false)
{
var b = New(_world);
foreach (var typeCode in abstractMask.IncTypeCodes)
{
b.Inc(_world.DeclareOrGetComponentTypeID(typeCode));
}
foreach (var typeCode in abstractMask.ExcTypeCodes)
{
b.Exc(_world.DeclareOrGetComponentTypeID(typeCode));
}
result = b.Build();
_abstractMasks.Add(abstractMask.ID, result);
}
return result;
}
internal EcsMask GetMask(Key maskKey) internal EcsMask GetMask(Key maskKey)
{ {
if (!_masks.TryGetValue(maskKey, out EcsMask result)) if (_masks.TryGetValue(maskKey, out EcsMask result) == false)
{ {
result = New(_masks.Count, _world.id, maskKey.inc, maskKey.exc); result = Create(_masks.Count, _world.id, maskKey.inc, maskKey.exc);
_masks.Add(maskKey, result); _masks.Add(maskKey, result);
} }
return result; return result;
@ -435,30 +641,19 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Key other) public bool Equals(Key other)
{ {
if (inc.Length != other.inc.Length) if (inc.Length != other.inc.Length) { return false; }
{ if (exc.Length != other.exc.Length) { return false; }
return false;
}
if (exc.Length != other.exc.Length)
{
return false;
}
for (int i = 0; i < inc.Length; i++) for (int i = 0; i < inc.Length; i++)
{ {
if (inc[i] != other.inc[i]) if (inc[i] != other.inc[i]) { return false; }
{
return false;
}
} }
for (int i = 0; i < exc.Length; i++) for (int i = 0; i < exc.Length; i++)
{ {
if (exc[i] != other.exc[i]) if (exc[i] != other.exc[i]) { return false; }
{
return false;
}
} }
return true; return true;
} }
public override bool Equals(object obj) { return Equals((Key)obj); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() { return hash; } public override int GetHashCode() { return hash; }
#endregion #endregion
@ -479,38 +674,31 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
#region Include/Exclude/Combine #region Inc/Exc/Combine
public Builder Include<T>() [Obsolete("Use Inc(type)")] public Builder Include<T>() { return Inc<T>(); }
{ [Obsolete("Use Exc(type)")] public Builder Exclude<T>() { return Exc<T>(); }
return Include(_world.GetComponentTypeID<T>()); [Obsolete("Use Inc(type)")] public Builder Include(Type type) { return Inc(type); }
} [Obsolete("Use Exc(type)")] public Builder Exclude(Type type) { return Exc(type); }
public Builder Exclude<T>()
{
return Exclude(_world.GetComponentTypeID<T>());
}
public Builder Include(Type type)
{
return Include(_world.GetComponentTypeID(type));
}
public Builder Exclude(Type type)
{
return Exclude(_world.GetComponentTypeID(type));
}
public Builder Include(int compponentTypeID) public Builder Inc<T>() { return Inc(_world.GetComponentTypeID<T>()); }
public Builder Exc<T>() { return Exc(_world.GetComponentTypeID<T>()); }
public Builder Inc(Type type) { return Inc(_world.GetComponentTypeID(type)); }
public Builder Exc(Type type) { return Exc(_world.GetComponentTypeID(type)); }
public Builder Inc(int componentTypeID)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(compponentTypeID) || _exc.Contains(compponentTypeID)) Throw.ConstraintIsAlreadyContainedInMask(_world.GetComponentType(compponentTypeID)); if (_inc.Contains(componentTypeID) || _exc.Contains(componentTypeID)) { Throw.ConstraintIsAlreadyContainedInMask(_world.GetComponentType(componentTypeID)); }
#endif #endif
_inc.Add(compponentTypeID); _inc.Add(componentTypeID);
return this; return this;
} }
public Builder Exclude(int compponentTypeID) public Builder Exc(int componentTypeID)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(compponentTypeID) || _exc.Contains(compponentTypeID)) Throw.ConstraintIsAlreadyContainedInMask(_world.GetComponentType(compponentTypeID)); if (_inc.Contains(componentTypeID) || _exc.Contains(componentTypeID)) { Throw.ConstraintIsAlreadyContainedInMask(_world.GetComponentType(componentTypeID)); }
#endif #endif
_exc.Add(compponentTypeID); _exc.Add(componentTypeID);
return this; return this;
} }

View File

@ -32,18 +32,18 @@ namespace DCFApixels.DragonECS
component = default; component = default;
} }
} }
internal readonly struct ExeccutorCache<T> : IEcsWorldComponent<ExeccutorCache<T>> internal readonly struct QueryCache<T> : IEcsWorldComponent<QueryCache<T>>
where T : EcsQueryExecutor, new() where T : EcsQueryCache, new()
{ {
public readonly T instance; public readonly T instance;
public ExeccutorCache(T instance) { this.instance = instance; } public QueryCache(T instance) { this.instance = instance; }
void IEcsWorldComponent<ExeccutorCache<T>>.Init(ref ExeccutorCache<T> component, EcsWorld world) void IEcsWorldComponent<QueryCache<T>>.Init(ref QueryCache<T> component, EcsWorld world)
{ {
T instance = new T(); T instance = new T();
instance.Initialize(world, world._executorsMediator); instance.Initialize(world, world._executorsMediator);
component = new ExeccutorCache<T>(instance); component = new QueryCache<T>(instance);
} }
void IEcsWorldComponent<ExeccutorCache<T>>.OnDestroy(ref ExeccutorCache<T> component, EcsWorld world) void IEcsWorldComponent<QueryCache<T>>.OnDestroy(ref QueryCache<T> component, EcsWorld world)
{ {
component = default; component = default;
} }

View File

@ -225,9 +225,9 @@ namespace DCFApixels.DragonECS
return Get<AspectCache<TAspect>>().instance; return Get<AspectCache<TAspect>>().instance;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public TExecutor GetExecutor<TExecutor>() where TExecutor : EcsQueryExecutor, new() public TExecutor GetQueryCache<TExecutor>() where TExecutor : EcsQueryCache, new()
{ {
return Get<ExeccutorCache<TExecutor>>().instance; return Get<QueryCache<TExecutor>>().instance;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -714,6 +714,15 @@ namespace DCFApixels.DragonECS
int count = GetComponentTypeIDsFor(entityID, ref _componentIDsBuffer); int count = GetComponentTypeIDsFor(entityID, ref _componentIDsBuffer);
return new ReadOnlySpan<int>(_componentIDsBuffer, 0, count); return new ReadOnlySpan<int>(_componentIDsBuffer, 0, count);
} }
public void GetComponentPoolsFor(int entityID, List<IEcsPool> list)
{
list.Clear();
int count = GetComponentTypeIDsFor(entityID, ref _componentIDsBuffer);
for (int i = 0; i < count; i++)
{
list.Add(_pools[_componentIDsBuffer[i]]);
}
}
public void GetComponentsFor(int entityID, List<object> list) public void GetComponentsFor(int entityID, List<object> list)
{ {
list.Clear(); list.Clear();

View File

@ -96,19 +96,19 @@ namespace DCFApixels.DragonECS
#region ComponentInfo #region ComponentInfo
public int GetComponentTypeID<TComponent>() public int GetComponentTypeID<TComponent>()
{ {
return DeclareOrGetComponentTypeID(EcsTypeCode.Get<TComponent>()); return DeclareOrGetComponentTypeID(EcsTypeCodeManager.Get<TComponent>());
} }
public int GetComponentTypeID(Type componentType) public int GetComponentTypeID(Type componentType)
{ {
return DeclareOrGetComponentTypeID(EcsTypeCode.Get(componentType)); return DeclareOrGetComponentTypeID(EcsTypeCodeManager.Get(componentType));
} }
public bool IsComponentTypeDeclared<TComponent>() public bool IsComponentTypeDeclared<TComponent>()
{ {
return _cmpTypeCode_2_CmpTypeIDs.Contains(EcsTypeCode.Get<TComponent>()); return _cmpTypeCode_2_CmpTypeIDs.Contains((int)EcsTypeCodeManager.Get<TComponent>());
} }
public bool IsComponentTypeDeclared(Type componentType) public bool IsComponentTypeDeclared(Type componentType)
{ {
return _cmpTypeCode_2_CmpTypeIDs.Contains(EcsTypeCode.Get(componentType)); return _cmpTypeCode_2_CmpTypeIDs.Contains((int)EcsTypeCodeManager.Get(componentType));
} }
public bool IsComponentTypeDeclared(int componentTypeID) public bool IsComponentTypeDeclared(int componentTypeID)
{ {
@ -125,21 +125,21 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Declare #region Declare
private int DeclareOrGetComponentTypeID(int componentTypeCode) internal int DeclareOrGetComponentTypeID(EcsTypeCode componentTypeCode)
{ {
if (_cmpTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int ComponentTypeID) == false) if (_cmpTypeCode_2_CmpTypeIDs.TryGetValue((int)componentTypeCode, out int ComponentTypeID) == false)
{ {
ComponentTypeID = _poolsCount++; ComponentTypeID = _poolsCount++;
_cmpTypeCode_2_CmpTypeIDs.Add(componentTypeCode, ComponentTypeID); _cmpTypeCode_2_CmpTypeIDs.Add((int)componentTypeCode, ComponentTypeID);
} }
return ComponentTypeID; return ComponentTypeID;
} }
private bool TryDeclareComponentTypeID(int componentTypeCode, out int componentTypeID) internal bool TryDeclareComponentTypeID(EcsTypeCode componentTypeCode, out int componentTypeID)
{ {
if (_cmpTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out componentTypeID) == false) if (_cmpTypeCode_2_CmpTypeIDs.TryGetValue((int)componentTypeCode, out componentTypeID) == false)
{ {
componentTypeID = _poolsCount++; componentTypeID = _poolsCount++;
_cmpTypeCode_2_CmpTypeIDs.Add(componentTypeCode, componentTypeID); _cmpTypeCode_2_CmpTypeIDs.Add((int)componentTypeCode, componentTypeID);
return true; return true;
} }
return false; return false;
@ -151,7 +151,7 @@ namespace DCFApixels.DragonECS
{ {
lock (_worldLock) lock (_worldLock)
{ {
int poolTypeCode = EcsTypeCode.Get<TPool>(); int poolTypeCode = (int)EcsTypeCodeManager.Get<TPool>();
if (_poolTypeCode_2_CmpTypeIDs.Contains(poolTypeCode)) if (_poolTypeCode_2_CmpTypeIDs.Contains(poolTypeCode))
{ {
Throw.World_PoolAlreadyCreated(); Throw.World_PoolAlreadyCreated();
@ -169,7 +169,7 @@ namespace DCFApixels.DragonECS
} }
#pragma warning restore IL2090 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The generic parameter of the source method or type does not have matching annotations. #pragma warning restore IL2090 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The generic parameter of the source method or type does not have matching annotations.
#endif #endif
int componentTypeCode = EcsTypeCode.Get(componentType); int componentTypeCode = (int)EcsTypeCodeManager.Get(componentType);
if (_cmpTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID)) if (_cmpTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID))
{ {

View File

@ -6,7 +6,7 @@ namespace DCFApixels.DragonECS
{ {
public partial class EcsWorld public partial class EcsWorld
{ {
private readonly Dictionary<(Type, EcsMask), EcsQueryExecutorCore> _executorCoures = new Dictionary<(Type, EcsMask), EcsQueryExecutorCore>(); private readonly Dictionary<(Type, object), EcsQueryExecutor> _executorCoures = new Dictionary<(Type, object), EcsQueryExecutor>(256);
private readonly ExecutorMediator _executorsMediator; private readonly ExecutorMediator _executorsMediator;
public readonly struct ExecutorMediator public readonly struct ExecutorMediator
{ {
@ -20,10 +20,10 @@ namespace DCFApixels.DragonECS
World = world; World = world;
} }
public TExecutorCore GetCore<TExecutorCore>(EcsMask mask) public TExecutorCore GetCore<TExecutorCore>(EcsMask mask)
where TExecutorCore : EcsQueryExecutorCore, new() where TExecutorCore : EcsQueryExecutor, new()
{ {
var coreType = typeof(TExecutorCore); var coreType = typeof(TExecutorCore);
if (World._executorCoures.TryGetValue((coreType, mask), out EcsQueryExecutorCore core) == false) if (World._executorCoures.TryGetValue((coreType, mask), out EcsQueryExecutor core) == false)
{ {
core = new TExecutorCore(); core = new TExecutorCore();
core.Initialize(World, mask); core.Initialize(World, mask);
@ -31,9 +31,21 @@ namespace DCFApixels.DragonECS
} }
return (TExecutorCore)core; return (TExecutorCore)core;
} }
public TExecutorCore GetCore<TExecutorCore>(EcsStaticMask staticMask)
where TExecutorCore : EcsQueryExecutor, new()
{
var coreType = typeof(TExecutorCore);
if (World._executorCoures.TryGetValue((coreType, staticMask), out EcsQueryExecutor core) == false)
{
core = new TExecutorCore();
core.Initialize(World, staticMask.ToMask(World));
World._executorCoures.Add((coreType, staticMask), core);
}
return (TExecutorCore)core;
}
} }
} }
public abstract class EcsQueryExecutorCore public abstract class EcsQueryExecutor
{ {
private EcsWorld _source; private EcsWorld _source;
private EcsMask _mask; private EcsMask _mask;
@ -66,7 +78,7 @@ namespace DCFApixels.DragonECS
protected abstract void OnInitialize(); protected abstract void OnInitialize();
protected abstract void OnDestroy(); protected abstract void OnDestroy();
} }
public abstract class EcsQueryExecutor public abstract class EcsQueryCache
{ {
private EcsWorld _source; private EcsWorld _source;
private EcsWorld.ExecutorMediator _mediator; private EcsWorld.ExecutorMediator _mediator;

View File

@ -11,7 +11,7 @@ namespace DCFApixels.DragonECS.Internal
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
internal class EcsWhereExecutorCore : EcsQueryExecutorCore internal class EcsWhereExecutor : EcsQueryExecutor
{ {
private EcsMaskIterator _iterator; private EcsMaskIterator _iterator;
private int[] _filteredAllEntities = new int[32]; private int[] _filteredAllEntities = new int[32];
@ -104,10 +104,10 @@ namespace DCFApixels.DragonECS
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
public sealed class EcsWhereExecutor<TAspect> : EcsQueryExecutor where TAspect : EcsAspect, new() public sealed class EcsWhereCache<TAspect> : EcsQueryCache where TAspect : EcsAspect, new()
{ {
private TAspect _aspect; private TAspect _aspect;
private EcsWhereExecutorCore _core; private EcsWhereExecutor _executor;
#region Properties #region Properties
public TAspect Aspect public TAspect Aspect
@ -118,7 +118,7 @@ namespace DCFApixels.DragonECS
public sealed override long Version public sealed override long Version
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _core.Version; } get { return _executor.Version; }
} }
#endregion #endregion
@ -126,7 +126,7 @@ namespace DCFApixels.DragonECS
protected sealed override void OnInitialize() protected sealed override void OnInitialize()
{ {
_aspect = World.GetAspect<TAspect>(); _aspect = World.GetAspect<TAspect>();
_core = Mediator.GetCore<EcsWhereExecutorCore>(_aspect.Mask); _executor = Mediator.GetCore<EcsWhereExecutor>(_aspect.Mask);
} }
protected sealed override void OnDestroy() { } protected sealed override void OnDestroy() { }
#endregion #endregion
@ -135,22 +135,22 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan Execute() public EcsSpan Execute()
{ {
return _core.Execute(); return _executor.Execute();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ExecuteFor(EcsSpan span) public EcsSpan ExecuteFor(EcsSpan span)
{ {
return _core.ExecuteFor(span); return _executor.ExecuteFor(span);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan Execute(Comparison<int> comparison) public EcsSpan Execute(Comparison<int> comparison)
{ {
return _core.Execute(comparison); return _executor.Execute(comparison);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ExecuteFor(EcsSpan span, Comparison<int> comparison) public EcsSpan ExecuteFor(EcsSpan span, Comparison<int> comparison)
{ {
return _core.ExecuteFor(span, comparison); return _executor.ExecuteFor(span, comparison);
} }
#endregion #endregion
} }

View File

@ -10,7 +10,7 @@ namespace DCFApixels.DragonECS.Internal
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
internal class EcsWhereToGroupExecutorCore : EcsQueryExecutorCore internal class EcsWhereToGroupExecutor : EcsQueryExecutor
{ {
private EcsMaskIterator _iterator; private EcsMaskIterator _iterator;
private EcsGroup _filteredAllGroup; private EcsGroup _filteredAllGroup;
@ -90,10 +90,10 @@ namespace DCFApixels.DragonECS
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
public sealed class EcsWhereToGroupExecutor<TAspect> : EcsQueryExecutor where TAspect : EcsAspect, new() public sealed class EcsWhereToGroupCache<TAspect> : EcsQueryCache where TAspect : EcsAspect, new()
{ {
private TAspect _aspect; private TAspect _aspect;
private EcsWhereToGroupExecutorCore _core; private EcsWhereToGroupExecutor _executor;
#region Properties #region Properties
public TAspect Aspect public TAspect Aspect
@ -104,7 +104,7 @@ namespace DCFApixels.DragonECS
public sealed override long Version public sealed override long Version
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _core.Version; } get { return _executor.Version; }
} }
#endregion #endregion
@ -112,11 +112,11 @@ namespace DCFApixels.DragonECS
protected sealed override void OnInitialize() protected sealed override void OnInitialize()
{ {
_aspect = World.GetAspect<TAspect>(); _aspect = World.GetAspect<TAspect>();
_core = Mediator.GetCore<EcsWhereToGroupExecutorCore>(_aspect.Mask); _executor = Mediator.GetCore<EcsWhereToGroupExecutor>(_aspect.Mask);
} }
protected sealed override void OnDestroy() protected sealed override void OnDestroy()
{ {
_core.Destroy(); _executor.Destroy();
} }
#endregion #endregion
@ -124,12 +124,12 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup Execute() public EcsReadonlyGroup Execute()
{ {
return _core.Execute(); return _executor.Execute();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup ExecuteFor(EcsSpan span) public EcsReadonlyGroup ExecuteFor(EcsSpan span)
{ {
return _core.ExecuteFor(span); return _executor.ExecuteFor(span);
} }
#endregion #endregion
} }

View File

@ -24,10 +24,14 @@ namespace DCFApixels.DragonECS
where TAspect : EcsAspect, new() where TAspect : EcsAspect, new()
{ {
EcsWorld world = span.World; EcsWorld world = span.World;
var executor = world.GetExecutor<EcsWhereExecutor<TAspect>>(); var executor = world.GetQueryCache<EcsWhereCache<TAspect>>();
aspect = executor.Aspect; aspect = executor.Aspect;
return executor.ExecuteFor(span); return executor.ExecuteFor(span);
} }
//public static EcsSpan Where<TCollection>(this TCollection entities, EcsStaticMask mask)
//{
//
//}
#endregion #endregion
#region Where with sort #region Where with sort
@ -46,7 +50,7 @@ namespace DCFApixels.DragonECS
where TAspect : EcsAspect, new() where TAspect : EcsAspect, new()
{ {
EcsWorld world = span.World; EcsWorld world = span.World;
var executor = world.GetExecutor<EcsWhereExecutor<TAspect>>(); var executor = world.GetQueryCache<EcsWhereCache<TAspect>>();
aspect = executor.Aspect; aspect = executor.Aspect;
return executor.ExecuteFor(span, comparison); return executor.ExecuteFor(span, comparison);
} }
@ -68,7 +72,7 @@ namespace DCFApixels.DragonECS
where TAspect : EcsAspect, new() where TAspect : EcsAspect, new()
{ {
EcsWorld world = span.World; EcsWorld world = span.World;
var executor = world.GetExecutor<EcsWhereToGroupExecutor<TAspect>>(); var executor = world.GetQueryCache<EcsWhereToGroupCache<TAspect>>();
aspect = executor.Aspect; aspect = executor.Aspect;
return executor.ExecuteFor(span); return executor.ExecuteFor(span);
} }

View File

@ -12,9 +12,9 @@ namespace DCFApixels.DragonECS.Internal
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
internal static class EcsTypeCode internal static class EcsTypeCodeManager
{ {
private static readonly Dictionary<Type, int> _codes = new Dictionary<Type, int>(); private static readonly Dictionary<Type, EcsTypeCode> _codes = new Dictionary<Type, EcsTypeCode>();
private static int _increment = 1; private static int _increment = 1;
private static object _lock = new object(); private static object _lock = new object();
public static int Count public static int Count
@ -22,20 +22,20 @@ namespace DCFApixels.DragonECS.Internal
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _codes.Count; } get { return _codes.Count; }
} }
public static int Get(Type type) public static EcsTypeCode Get(Type type)
{ {
lock (_lock) lock (_lock)
{ {
if (!_codes.TryGetValue(type, out int code)) if (!_codes.TryGetValue(type, out EcsTypeCode code))
{ {
code = _increment++; code = (EcsTypeCode)_increment++;
_codes.Add(type, code); _codes.Add(type, code);
} }
return code; return code;
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Get<T>() { return EcsTypeCodeCache<T>.code; } public static EcsTypeCode Get<T>() { return EcsTypeCodeCache<T>.code; }
public static bool Has(Type type) { return _codes.ContainsKey(type); } public static bool Has(Type type) { return _codes.ContainsKey(type); }
public static bool Has<T>() { return _codes.ContainsKey(typeof(T)); } public static bool Has<T>() { return _codes.ContainsKey(typeof(T)); }
public static IEnumerable<TypeCodeInfo> GetDeclaredTypes() { return _codes.Select(o => new TypeCodeInfo(o.Key, o.Value)); } public static IEnumerable<TypeCodeInfo> GetDeclaredTypes() { return _codes.Select(o => new TypeCodeInfo(o.Key, o.Value)); }
@ -46,7 +46,7 @@ namespace DCFApixels.DragonECS.Internal
#endif #endif
internal static class EcsTypeCodeCache<T> internal static class EcsTypeCodeCache<T>
{ {
public static readonly int code = EcsTypeCode.Get(typeof(T)); public static readonly EcsTypeCode code = EcsTypeCodeManager.Get(typeof(T));
} }
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
[Il2CppSetOption(Option.NullChecks, false)] [Il2CppSetOption(Option.NullChecks, false)]
@ -55,8 +55,8 @@ namespace DCFApixels.DragonECS.Internal
internal struct TypeCodeInfo internal struct TypeCodeInfo
{ {
public Type type; public Type type;
public int code; public EcsTypeCode code;
public TypeCodeInfo(Type type, int code) public TypeCodeInfo(Type type, EcsTypeCode code)
{ {
this.type = type; this.type = type;
this.code = code; this.code = code;

4
src/Utils/EcsTypeCode.cs Normal file
View File

@ -0,0 +1,4 @@
namespace DCFApixels.DragonECS
{
public enum EcsTypeCode : int { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b21f5b69a0fc3b447b93b34ef4377dbf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -37,6 +37,11 @@ namespace DCFApixels.DragonECS.Internal
{ {
internal static class Throw internal static class Throw
{ {
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void ConstraintIsAlreadyContainedInMask()
{
throw new EcsFrameworkException($"The constraint is already contained in the mask.");
}
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void ConstraintIsAlreadyContainedInMask(Type type) internal static void ConstraintIsAlreadyContainedInMask(Type type)
{ {