From 6fd85813c3415e2af2388eba78225313d11d527e Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 00:24:38 +0800 Subject: [PATCH 1/8] refactoring --- src/Consts.cs | 1 - src/EcsGroup.cs | 116 ++++++------------------------------- src/EcsPipeline.cs | 33 ++--------- src/EcsSubject.cs | 29 +++++----- src/EcsWorld.cs | 139 +++++++++++++++++++-------------------------- 5 files changed, 94 insertions(+), 224 deletions(-) diff --git a/src/Consts.cs b/src/Consts.cs index d7c2323..b21827b 100644 --- a/src/Consts.cs +++ b/src/Consts.cs @@ -9,7 +9,6 @@ public const string DEBUG_WARNING_TAG = "WARNING"; public const string DEBUG_ERROR_TAG = "ERROR"; - public const string PRE_BEGIN_LAYER = nameof(PRE_BEGIN_LAYER); public const string BEGIN_LAYER = nameof(BEGIN_LAYER); public const string BASIC_LAYER = nameof(BASIC_LAYER); diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 96d7d71..16a2159 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -1,8 +1,6 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using Unity.Profiling; -using delayedOp = System.Int32; namespace DCFApixels.DragonECS { @@ -45,7 +43,7 @@ namespace DCFApixels.DragonECS public bool IsReleazed { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _source.IsReleazed; + get => _source.IsReleased; } public int this[int index] { @@ -93,26 +91,13 @@ namespace DCFApixels.DragonECS #endregion } - // индексация начинается с 1 - // _delayedOps это int[] для отложенных операций, хранятся отложенные операции в виде int значения, если старший бит = 0 то это опреация добавленияб если = 1 то это операция вычитания public unsafe class EcsGroup : IDisposable, IEquatable { - private const int DEALAYED_ADD = 0; - private const int DEALAYED_REMOVE = int.MinValue; - private EcsWorld _source; - private int[] _dense; private int[] _sparse; - private int _count; - - private delayedOp[] _delayedOps; - private int _delayedOpsCount; - - private int _lockCount; - - private bool _isReleazed = true; + private bool _isReleased = true; #region Properties public EcsWorld World => _source; @@ -136,10 +121,10 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new EcsReadonlyGroup(this); } - public bool IsReleazed + public bool IsReleased { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _isReleazed; + get => _isReleased; } public int this[int index] { @@ -161,27 +146,15 @@ namespace DCFApixels.DragonECS return world.GetGroupFromPool(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal EcsGroup(EcsWorld world, int denseCapacity = 64, int delayedOpsCapacity = 128) + internal EcsGroup(EcsWorld world, int denseCapacity = 64) { _source = world; _source.RegisterGroup(this); _dense = new int[denseCapacity]; _sparse = new int[world.Capacity]; - _delayedOps = new delayedOp[delayedOpsCapacity]; - - _lockCount = 0; - _delayedOpsCount = 0; _count = 0; } - - //защита от криворукости - //перед сборкой мусора снова создает сильную ссылку и возвращает в пул - //TODO переделат или удалить, так как сборщик мусора просыпается только после 12к и более экземпляров, только тогда и вызывается финализатор, слишком жирно - ~EcsGroup() - { - Release(); - } #endregion #region Has @@ -211,16 +184,6 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void AddInternal(int entityID) { - //if (_lockCount > 0) - //{ - // AddDelayedOp(entityID, DEALAYED_ADD); - // return; - //} - AggressiveAdd(entityID); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void AggressiveAdd(int entityID) - { #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS if (Has(entityID)) ThrowAlreadyContains(entityID); #endif @@ -239,16 +202,6 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void RemoveInternal(int entityID) { - //if (_lockCount > 0) - //{ - // AddDelayedOp(entityID, DEALAYED_REMOVE); - // return; - //} - AggressiveRemove(entityID); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void AggressiveRemove(int entityID) - { #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS if (!Has(entityID)) ThrowDoesNotContain(entityID); #endif @@ -257,22 +210,12 @@ namespace DCFApixels.DragonECS _sparse[entityID] = 0; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void AddDelayedOp(int entityID, int isAddBitFlag) - { - if (_delayedOpsCount >= _delayedOps.Length) - { - Array.Resize(ref _delayedOps, _delayedOps.Length << 1); - } - _delayedOps[_delayedOpsCount++] = entityID | isAddBitFlag; // delayedOp = entityID add isAddBitFlag - } - public void RemoveUnusedEntityIDs() { foreach (var e in this) { if (!_source.IsUsed(e)) - AggressiveRemove(e); + RemoveInternal(e); } } #endregion @@ -299,7 +242,7 @@ namespace DCFApixels.DragonECS if(_count > 0) Clear(); foreach (var item in group) - AggressiveAdd(item); + AddInternal(item); } public EcsGroup Clone() { @@ -321,7 +264,7 @@ namespace DCFApixels.DragonECS #endif foreach (var item in group) if (!Has(item)) - AggressiveAdd(item); + AddInternal(item); } /// as Except sets @@ -335,7 +278,7 @@ namespace DCFApixels.DragonECS #endif foreach (var item in this) if (group.Has(item)) - AggressiveRemove(item); + RemoveInternal(item); } /// as Intersect sets @@ -349,7 +292,7 @@ namespace DCFApixels.DragonECS #endif foreach (var item in this) if (!group.Has(item)) - AggressiveRemove(item); + RemoveInternal(item); } /// as Symmetric Except sets @@ -363,9 +306,9 @@ namespace DCFApixels.DragonECS #endif foreach (var item in group) if (Has(item)) - AggressiveRemove(item); + RemoveInternal(item); else - AggressiveAdd(item); + AddInternal(item); } #endregion @@ -380,7 +323,7 @@ namespace DCFApixels.DragonECS EcsGroup result = a._source.GetGroupFromPool(); foreach (var item in a) if (!b.Has(item)) - result.AggressiveAdd(item); + result.AddInternal(item); a._source.ReleaseGroup(a); return result; } @@ -394,7 +337,7 @@ namespace DCFApixels.DragonECS EcsGroup result = a._source.GetGroupFromPool(); foreach (var item in a) if (b.Has(item)) - result.AggressiveAdd(item); + result.AddInternal(item); a._source.ReleaseGroup(a); return result; } @@ -407,7 +350,7 @@ namespace DCFApixels.DragonECS #endif EcsGroup result = a._source.GetGroupFromPool(); foreach (var item in a) - result.AggressiveAdd(item); + result.AddInternal(item); foreach (var item in a) result.Add(item); return result; @@ -415,34 +358,9 @@ namespace DCFApixels.DragonECS #endregion #region GetEnumerator - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Unlock() - { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - if (_lockCount <= 0) - { - throw new Exception($"Invalid lock-unlock balance for {nameof(EcsGroup)}."); - } -#endif - if (--_lockCount <= 0) - { - for (int i = 0; i < _delayedOpsCount; i++) - { - delayedOp op = _delayedOps[i]; - if (op >= 0) //delayedOp.IsAdded - AggressiveAdd(op & int.MaxValue); //delayedOp.EcsEntity - else - AggressiveRemove(op & int.MaxValue); //delayedOp.EcsEntity - } - } - } - private ProfilerMarker _getEnumeratorReturn = new ProfilerMarker("EcsGroup.GetEnumerator"); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { - // _lockCount++; return new Enumerator(this); } #endregion @@ -538,7 +456,7 @@ namespace DCFApixels.DragonECS } public void Release() { - _isReleazed = true; + _isReleased = true; _source.ReleaseGroup(this); } #endregion @@ -558,6 +476,7 @@ namespace DCFApixels.DragonECS #endregion } + #region Extensions public static class EcsGroupExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -571,4 +490,5 @@ namespace DCFApixels.DragonECS if (array.Length < self.CapacityDense) Array.Resize(ref array, self.CapacityDense); } } + #endregion } diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index a898ecb..198bad8 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -10,21 +10,6 @@ namespace DCFApixels.DragonECS { public sealed class EcsPipeline { - private static EcsPipeline _empty; - public static EcsPipeline Empty - { - get - { - if(_empty == null) - { - _empty = new EcsPipeline(Array.Empty()); - _empty.Init(); - _empty._isEmptyDummy = true; - } - return _empty; - } - } - private IEcsSystem[] _allSystems; private Dictionary _runners; private IEcsRunProcess _runRunnerCache; @@ -350,30 +335,21 @@ namespace DCFApixels.DragonECS public interface IEcsModule { - public void ImportSystems(EcsPipeline.Builder b); + void ImportSystems(EcsPipeline.Builder b); } #region Extensions public static class EcsPipelineExtensions { - public static bool IsNullOrDestroyed(this EcsPipeline self) - { - return self == null || self.IsDestoryed; - } + public static bool IsNullOrDestroyed(this EcsPipeline self) => self == null || self.IsDestoryed; public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable range, string layerName = null) { - foreach (var item in range) - { - self.Add(item, layerName); - } + foreach (var item in range) self.Add(item, layerName); return self; } public static EcsPipeline.Builder AddUnique(this EcsPipeline.Builder self, IEnumerable range, string layerName = null) { - foreach (var item in range) - { - self.AddUnique(item, layerName); - } + foreach (var item in range) self.AddUnique(item, layerName); return self; } public static EcsPipeline BuildAndInit(this EcsPipeline.Builder self) @@ -382,7 +358,6 @@ namespace DCFApixels.DragonECS result.Init(); return result; } - } #endregion } diff --git a/src/EcsSubject.cs b/src/EcsSubject.cs index eff687f..3dd86f5 100644 --- a/src/EcsSubject.cs +++ b/src/EcsSubject.cs @@ -13,7 +13,6 @@ namespace DCFApixels.DragonECS internal EcsWorld source; [EditorBrowsable(EditorBrowsableState.Always)] internal EcsMask mask; - private bool _isInit; #region Properties @@ -26,7 +25,7 @@ namespace DCFApixels.DragonECS #endregion #region Methods - public bool IsMatches(int entityID) => source.IsMaskCompatible(mask, entityID); + public bool IsMatches(int entityID) => source.IsMatchesMask(mask, entityID); #endregion #region Builder @@ -111,6 +110,7 @@ namespace DCFApixels.DragonECS #endregion } + #region Extensions public static class EcsSubjectExtensions { public static EcsSubjectIterator GetIterator(this TSubject self) where TSubject : EcsSubject @@ -122,6 +122,7 @@ namespace DCFApixels.DragonECS return new EcsSubjectIterator(self, sourceGroup); } } + #endregion #region BuilderBase public abstract class EcsSubjectBuilderBase @@ -135,20 +136,18 @@ namespace DCFApixels.DragonECS #region Mask public sealed class EcsMask { - internal readonly Type WorldType; - internal readonly int[] Inc; - internal readonly int[] Exc; - + internal readonly Type _worldType; + internal readonly int[] _inc; + internal readonly int[] _exc; public EcsMask(Type worldType, int[] inc, int[] exc) { - WorldType = worldType; - Inc = inc; - Exc = exc; + _worldType = worldType; + _inc = inc; + _exc = exc; } - public override string ToString() { - return $"Inc({string.Join(", ", Inc)}) Exc({string.Join(", ", Exc)})"; + return $"Inc({string.Join(", ", _inc)}) Exc({string.Join(", ", _exc)})"; } } #endregion @@ -181,7 +180,7 @@ namespace DCFApixels.DragonECS group.Clear(); var enumerator = GetEnumerator(); while (enumerator.MoveNext()) - group.AggressiveAdd(enumerator.Current); + group.AddInternal(enumerator.Current); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() => new Enumerator(sourceGroup, s); @@ -207,9 +206,9 @@ namespace DCFApixels.DragonECS public Enumerator(EcsReadonlyGroup sourceGroup, EcsSubject subject) { _sourceGroup = sourceGroup.GetEnumerator(); - _inc = subject.mask.Inc; - _exc = subject.mask.Exc; - _pools = subject.World.pools; + _inc = subject.mask._inc; + _exc = subject.mask._exc; + _pools = subject.World._pools; } public int Current { diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 9b8f66d..752f3ab 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { @@ -27,17 +26,17 @@ namespace DCFApixels.DragonECS private IntDispenser _entityDispenser; private int _entitiesCount; private int _entitesCapacity; - private short[] _gens; //старший бит указывает на то жива ли сущьность. + private short[] _gens; //старший бит указывает на то жива ли сущность private short[] _componentCounts; private EcsGroup _allEntites; - //буфер удаления откладывает освобождение андишников сущьностей. - //Нужен для того чтобы запускать некоторые процесыы связанные с удалением сущьности не по одному при каждом удалении, а пачкой + //буфер удаления откладывает освобождение андишников сущностей. + //Нужен для того чтобы запускать некоторые процесыы связанные с удалением сущности не по одному при каждом удалении, а пачкой //В теории такой подход частично улучшает ситуацию с переполнением поколений private int[] _delEntBuffer; private int _delEntBufferCount; - internal IEcsPoolImplementation[] pools; + internal IEcsPoolImplementation[] _pools; private EcsNullPool _nullPool; private int _poolsCount = 0; @@ -55,7 +54,7 @@ namespace DCFApixels.DragonECS public int Count => _entitiesCount; public int Capacity => _entitesCapacity; //_denseEntities.Length; public EcsReadonlyGroup Entities => _allEntites.Readonly; - public ReadOnlySpan AllPools => pools;// new ReadOnlySpan(pools, 0, _poolsCount); + public ReadOnlySpan AllPools => _pools;// new ReadOnlySpan(pools, 0, _poolsCount); public int PoolsCount => _poolsCount; #endregion @@ -84,8 +83,8 @@ namespace DCFApixels.DragonECS _entityDispenser = new IntDispenser(0); _nullPool = EcsNullPool.instance; - pools = new IEcsPoolImplementation[512]; - ArrayUtility.Fill(pools, _nullPool); + _pools = new IEcsPoolImplementation[512]; + ArrayUtility.Fill(_pools, _nullPool); _gens = new short[_entitesCapacity]; _componentCounts = new short[_entitesCapacity]; @@ -106,7 +105,7 @@ namespace DCFApixels.DragonECS _entityDispenser = null; //_denseEntities = null; _gens = null; - pools = null; + _pools = null; _nullPool = null; _subjects = null; _executors = null; @@ -130,23 +129,23 @@ namespace DCFApixels.DragonECS { int uniqueID = WorldMetaStorage.GetComponentId(_worldTypeID); - if (uniqueID >= pools.Length) + if (uniqueID >= _pools.Length) { - int oldCapacity = pools.Length; - Array.Resize(ref pools, pools.Length << 1); - ArrayUtility.Fill(pools, _nullPool, oldCapacity, oldCapacity - pools.Length); + int oldCapacity = _pools.Length; + Array.Resize(ref _pools, _pools.Length << 1); + ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length); } - if (pools[uniqueID] == _nullPool) + if (_pools[uniqueID] == _nullPool) { var pool = new TPool(); - pools[uniqueID] = pool; + _pools[uniqueID] = pool; pool.OnInit(this, uniqueID); _poolsCount++; //EcsDebug.Print(pool.GetType().FullName); } - return (TPool)pools[uniqueID]; + return (TPool)_pools[uniqueID]; } #endregion @@ -258,21 +257,21 @@ namespace DCFApixels.DragonECS #endregion - #region IsMaskCompatible - public bool IsMaskCompatible(EcsMask mask, int entityID) + #region IsMatchesMask + public bool IsMatchesMask(EcsMask mask, int entityID) { #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - if (mask.WorldType != Archetype) + if (mask._worldType != Archetype) throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TTableArhetype)"); #endif - for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++) + for (int i = 0, iMax = mask._inc.Length; i < iMax; i++) { - if (!pools[mask.Inc[i]].Has(entityID)) + if (!_pools[mask._inc[i]].Has(entityID)) return false; } - for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++) + for (int i = 0, iMax = mask._exc.Length; i < iMax; i++) { - if (pools[mask.Exc[i]].Has(entityID)) + if (_pools[mask._exc[i]].Has(entityID)) return false; } return true; @@ -305,7 +304,7 @@ namespace DCFApixels.DragonECS _groups.RemoveAt(last); } } - foreach (var item in pools) + foreach (var item in _pools) item.OnWorldResize(_gens.Length); _listeners.InvokeOnWorldResize(_gens.Length); @@ -341,30 +340,30 @@ namespace DCFApixels.DragonECS public void ReleaseDelEntityBuffer() { ReadOnlySpan buffser = new ReadOnlySpan(_delEntBuffer, 0, _delEntBufferCount); - foreach (var pool in pools) + foreach (var pool in _pools) pool.OnReleaseDelEntityBuffer(buffser); _listeners.InvokeOnReleaseDelEntityBuffer(buffser); for (int i = 0; i < _delEntBufferCount; i++) _entityDispenser.Release(_delEntBuffer[i]); _delEntBufferCount = 0; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public short GetGen(int entityID) => _gens[entityID]; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public short GetComponentsCount(int entityID) => _componentCounts[entityID]; public void DeleteEmptyEntites() { foreach (var e in _allEntites) { - if (_componentCounts[e] <= 0) - DelEntity(e); + if (_componentCounts[e] <= 0) DelEntity(e); } } public void CopyEntity(int fromEntityID, int toEntityID) { - foreach (var pool in pools) + foreach (var pool in _pools) { - if(pool.Has(fromEntityID)) - pool.Copy(fromEntityID, toEntityID); + if(pool.Has(fromEntityID)) pool.Copy(fromEntityID, toEntityID); } } public int CloneEntity(int fromEntityID) @@ -376,7 +375,7 @@ namespace DCFApixels.DragonECS public void CloneEntity(int fromEntityID, int toEntityID) { CopyEntity(fromEntityID, toEntityID); - foreach (var pool in pools) + foreach (var pool in _pools) { if (!pool.Has(fromEntityID)&& pool.Has(toEntityID)) pool.Del(toEntityID); @@ -384,19 +383,14 @@ namespace DCFApixels.DragonECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void IncrementEntityComponentCount(int entityID) - { - _componentCounts[entityID]++; - } + internal void IncrementEntityComponentCount(int entityID) => _componentCounts[entityID]++; [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void DecrementEntityComponentCount(int entityID) { var count = --_componentCounts[entityID]; - if(count == 0 && _allEntites.Has(entityID)) - DelEntity(entityID); - + if(count == 0 && _allEntites.Has(entityID)) DelEntity(entityID); #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - if (count < 0) throw new EcsFrameworkException("нарушен баланс инкремента.декремента компонентов"); + if (count < 0) throw new EcsFrameworkException("нарушен баланс инкремента/декремента компонентов"); #endif } #endregion @@ -408,8 +402,7 @@ namespace DCFApixels.DragonECS } internal EcsGroup GetGroupFromPool() { - if (_groupsPool.Count <= 0) - return new EcsGroup(this); + if (_groupsPool.Count <= 0) return new EcsGroup(this); return _groupsPool.Pop(); } internal void ReleaseGroup(EcsGroup group) @@ -431,10 +424,10 @@ namespace DCFApixels.DragonECS if (itemsCount == 0) return; - for (var i = 0; i < pools.Length; i++) + for (var i = 0; i < _pools.Length; i++) { - if (pools[i].Has(entityID)) - list.Add(pools[i].GetRaw(entityID)); + if (_pools[i].Has(entityID)) + list.Add(_pools[i].GetRaw(entityID)); if (list.Count >= itemsCount) break; } @@ -485,41 +478,25 @@ namespace DCFApixels.DragonECS } #region Utils - [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 24)] - internal readonly struct PoolRunners - { - public readonly IEcsComponentAdd add; - public readonly IEcsComponentWrite write; - public readonly IEcsComponentDel del; - - public PoolRunners(EcsPipeline pipeline) - { - add = pipeline.GetRunner(); - write = pipeline.GetRunner(); - del = pipeline.GetRunner(); - } - } public static class WorldMetaStorage { - private static List resizer = new List(); - private static int tokenCount = 0; - private static int[] componentCounts = new int[0]; - private static int[] queryCounts = new int[0]; - + private static List _resizer = new List(); + private static int _tokenCount = 0; + private static int[] _componentCounts = new int[0]; + private static int[] _subjectsCounts = new int[0]; private static Dictionary _worldIds = new Dictionary(); - private static class WorldIndex { public static int id = GetWorldId(typeof(TWorldArchetype)); } private static int GetToken() { - tokenCount++; - Array.Resize(ref componentCounts, tokenCount); - Array.Resize(ref queryCounts, tokenCount); - foreach (var item in resizer) - item.Resize(tokenCount); - return tokenCount - 1; + _tokenCount++; + Array.Resize(ref _componentCounts, _tokenCount); + Array.Resize(ref _subjectsCounts, _tokenCount); + foreach (var item in _resizer) + item.Resize(_tokenCount); + return _tokenCount - 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetWorldId(Type archetype) @@ -557,17 +534,17 @@ namespace DCFApixels.DragonECS public static int[] ids; static Component() { - ids = new int[tokenCount]; + ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; - resizer.Add(new Resizer()); + _resizer.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) - id = componentCounts[token]++; + id = _componentCounts[token]++; return id; } } @@ -576,17 +553,17 @@ namespace DCFApixels.DragonECS public static int[] ids; static Subject() { - ids = new int[tokenCount]; + ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; - resizer.Add(new Resizer()); + _resizer.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) - id = queryCounts[token]++; + id = _subjectsCounts[token]++; return id; } } @@ -595,24 +572,24 @@ namespace DCFApixels.DragonECS public static int[] ids; static Executor() { - ids = new int[tokenCount]; + ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; - resizer.Add(new Resizer()); + _resizer.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) - id = queryCounts[token]++; + id = _subjectsCounts[token]++; return id; } } } #endregion - #region Callbacks Interface //TODO + #region Callbacks Interface public interface IEcsWorldEventListener { void OnWorldResize(int newSize); @@ -624,7 +601,7 @@ namespace DCFApixels.DragonECS #endregion #region Extensions - public static class WorldEventListExtensions + internal static class WorldEventListExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void InvokeOnWorldResize(this List self, int newSize) From caef8d8baee2a24a9e15bcd411ce558ef523f5fc Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 03:45:35 +0800 Subject: [PATCH 2/8] refactoring --- src/Builtin/InjectSystem.cs | 124 +++++++++++++++--------------------- src/Builtin/Systems.cs | 70 ++++++++++---------- src/Builtin/WorldRunners.cs | 106 ------------------------------ src/Builtin/Worlds.cs | 4 ++ src/EcsWorld.cs | 12 +--- 5 files changed, 93 insertions(+), 223 deletions(-) delete mode 100644 src/Builtin/WorldRunners.cs diff --git a/src/Builtin/InjectSystem.cs b/src/Builtin/InjectSystem.cs index 5fa251f..e387514 100644 --- a/src/Builtin/InjectSystem.cs +++ b/src/Builtin/InjectSystem.cs @@ -5,37 +5,8 @@ using System.Linq; namespace DCFApixels.DragonECS { //TODO развить идею инжектов - //1) добавить расширенный метод инжекта, с 2 джинерик-аргументами, первый базовый тип и второй инжектируемый тип. - //напримере это будет работать так Inject делает инжект объекта типа Foo для систем с IEcsInject или с IEcsInject - //2) добавить контейнер, который автоматически создается, собирает в себя все пре-инжекты и авто-инжектится во все системы. + //добавить контейнер, который автоматически создается, собирает в себя все пре-инжекты и авто-инжектится во все системы. //но это спорная идея - namespace Internal - { - internal class PreInitInjectController - { - private EcsPipeline _source; - private InjectSystemBase[] _injectSystems; - private int _injectCount; - public PreInitInjectController(EcsPipeline source) - { - _injectCount = 0; - _source = source; - _injectSystems = _source.AllSystems.OfType().ToArray(); - } - public bool OnInject() - { - _injectCount++; - return IsInjectionEnd; - } - public bool IsInjectionEnd => _injectCount >= _injectSystems.Length; - public void Destroy() - { - _source = null; - _injectSystems = null; - } - } - } - public interface IEcsPreInject : IEcsSystem { void PreInject(object obj); @@ -52,6 +23,29 @@ namespace DCFApixels.DragonECS namespace Internal { + internal class PreInitInjectController + { + private EcsPipeline _source; + private InjectSystemBase[] _injectSystems; + private int _injectCount; + public bool IsInjectionEnd => _injectCount >= _injectSystems.Length; + public PreInitInjectController(EcsPipeline source) + { + _injectCount = 0; + _source = source; + _injectSystems = _source.AllSystems.OfType().ToArray(); + } + public bool OnInject() + { + _injectCount++; + return IsInjectionEnd; + } + public void Destroy() + { + _source = null; + _injectSystems = null; + } + } [DebugHide, DebugColor(DebugColor.Gray)] public sealed class EcsPreInjectRunner : EcsRunner, IEcsPreInject { @@ -86,55 +80,43 @@ namespace DCFApixels.DragonECS foreach (var item in targets) item.OnPreInitInjectionBefore(); } } - } - - public class InjectSystemBase { } - - [DebugHide, DebugColor(DebugColor.Gray)] - public class InjectSystem : InjectSystemBase, IEcsPreInitProcess, IEcsInject, IEcsPreInitInjectProcess - { - private T _injectedData; - - private PreInitInjectController _injectController; - void IEcsInject.Inject(PreInitInjectController obj) => _injectController = obj; - - public InjectSystem(T injectedData) + public class InjectSystemBase { } + [DebugHide, DebugColor(DebugColor.Gray)] + public class InjectSystem : InjectSystemBase, IEcsPreInitProcess, IEcsInject, IEcsPreInitInjectProcess { - _injectedData = injectedData; - } - - public void PreInit(EcsPipeline pipeline) - { - if (_injectedData == null) - return; - - if (_injectController == null) + private T _injectedData; + private PreInitInjectController _injectController; + void IEcsInject.Inject(PreInitInjectController obj) => _injectController = obj; + public InjectSystem(T injectedData) { - _injectController = new PreInitInjectController(pipeline); - var injectMapRunner = pipeline.GetRunner>(); - pipeline.GetRunner().OnPreInitInjectionBefore(); - injectMapRunner.Inject(_injectController); + _injectedData = injectedData; } - - var injectRunnerGeneric = pipeline.GetRunner>(); - injectRunnerGeneric.Inject(_injectedData); - - if (_injectController.OnInject()) + public void PreInit(EcsPipeline pipeline) { - _injectController.Destroy(); - var injectCallbacksRunner = pipeline.GetRunner(); - injectCallbacksRunner.OnPreInitInjectionAfter(); - EcsRunner.Destroy(injectCallbacksRunner); + if (_injectedData == null) return; + if (_injectController == null) + { + _injectController = new PreInitInjectController(pipeline); + var injectMapRunner = pipeline.GetRunner>(); + pipeline.GetRunner().OnPreInitInjectionBefore(); + injectMapRunner.Inject(_injectController); + } + var injectRunnerGeneric = pipeline.GetRunner>(); + injectRunnerGeneric.Inject(_injectedData); + if (_injectController.OnInject()) + { + _injectController.Destroy(); + var injectCallbacksRunner = pipeline.GetRunner(); + injectCallbacksRunner.OnPreInitInjectionAfter(); + EcsRunner.Destroy(injectCallbacksRunner); + } } - } - public void OnPreInitInjectionBefore() { } - public void OnPreInitInjectionAfter() - { - _injectController = null; + public void OnPreInitInjectionBefore() { } + public void OnPreInitInjectionAfter() => _injectController = null; } } - public static class InjectSystemExstensions + public static class InjectSystemExtensions { public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T data) { diff --git a/src/Builtin/Systems.cs b/src/Builtin/Systems.cs index 431afa3..15ff527 100644 --- a/src/Builtin/Systems.cs +++ b/src/Builtin/Systems.cs @@ -1,53 +1,51 @@ using System.Collections.Generic; +using DCFApixels.DragonECS.Internal; namespace DCFApixels.DragonECS { - [DebugHide, DebugColor(DebugColor.Black)] - public class SystemsBlockMarkerSystem : IEcsSystem + namespace Internal { - public readonly string name; - public SystemsBlockMarkerSystem(string name) { this.name = name; } - } - - [DebugHide, DebugColor(DebugColor.Grey)] - public class DeleteEmptyEntitesSystem : IEcsRunProcess, IEcsPreInject - { - private List _worlds = new List(); - public void PreInject(object obj) + [DebugHide, DebugColor(DebugColor.Black)] + public class SystemsBlockMarkerSystem : IEcsSystem { - if (obj is EcsWorld world) - _worlds.Add(world); + public readonly string name; + public SystemsBlockMarkerSystem(string name) => this.name = name; } - public void Run(EcsPipeline pipeline) + [DebugHide, DebugColor(DebugColor.Grey)] + public class DeleteEmptyEntitesSystem : IEcsRunProcess, IEcsPreInject { - foreach (var world in _worlds) - world.DeleteEmptyEntites(); - } - } - - [DebugHide, DebugColor(DebugColor.Grey)] - public class DeleteOneFrameComponentSystem : IEcsRunProcess, IEcsInject - where TWorld : EcsWorld - where TComponent : struct, IEcsComponent - { - private TWorld _world; - public void Inject(TWorld obj) => _world = obj; - private sealed class Subject : EcsSubject - { - public EcsPool pool; - public Subject(Builder b) + private List _worlds = new List(); + public void PreInject(object obj) { - pool = b.Include(); + if (obj is EcsWorld world) + _worlds.Add(world); + } + public void Run(EcsPipeline pipeline) + { + foreach (var world in _worlds) + world.DeleteEmptyEntites(); } } - public void Run(EcsPipeline pipeline) + [DebugHide, DebugColor(DebugColor.Grey)] + public class DeleteOneFrameComponentSystem : IEcsRunProcess, IEcsInject + where TWorld : EcsWorld + where TComponent : struct, IEcsComponent { - foreach (var e in _world.Where(out Subject s)) - s.pool.Del(e); + private sealed class Subject : EcsSubject + { + public EcsPool pool; + public Subject(Builder b) => pool = b.Include(); + } + private TWorld _world; + public void Inject(TWorld obj) => _world = obj; + public void Run(EcsPipeline pipeline) + { + foreach (var e in _world.Where(out Subject s)) + s.pool.Del(e); + } } } - - public static class DeleteOneFrameComponentSystemExt + public static class DeleteOneFrameComponentSystemExtensions { private const string AUTO_DEL_LAYER = nameof(AUTO_DEL_LAYER); public static EcsPipeline.Builder AutoDel(this EcsPipeline.Builder b) diff --git a/src/Builtin/WorldRunners.cs b/src/Builtin/WorldRunners.cs deleted file mode 100644 index 105432b..0000000 --- a/src/Builtin/WorldRunners.cs +++ /dev/null @@ -1,106 +0,0 @@ -using DCFApixels.DragonECS.RunnersCore; - -namespace DCFApixels.DragonECS -{ - public interface IEcsComponentAdd : IEcsSystem - { - void OnComponentAdd(int entityID); - } - public interface IEcsComponentWrite : IEcsSystem - { - void OnComponentWrite(int entityID); - } - public interface IEcsComponentDel : IEcsSystem - { - void OnComponentDel(int entityID); - } - public interface IEcsComponentLifecycle : IEcsComponentAdd, IEcsComponentWrite, IEcsComponentDel { } - - namespace Internal - { - [DebugColor(DebugColor.Orange)] - public sealed class EcsEntityAddComponentRunner : EcsRunner, IEcsComponentAdd - { - public void OnComponentAdd(int entityID) - { - foreach (var item in targets) item.OnComponentAdd(entityID); - } - } - [DebugColor(DebugColor.Orange)] - public sealed class EcsEntityChangeComponentRunner : EcsRunner, IEcsComponentWrite - { - public void OnComponentWrite(int entityID) - { - foreach (var item in targets) item.OnComponentWrite(entityID); - } - } - [DebugColor(DebugColor.Orange)] - public sealed class EcsEntityDelComponentRunner : EcsRunner, IEcsComponentDel - { - public void OnComponentDel(int entityID) - { - foreach (var item in targets) item.OnComponentDel(entityID); - } - } - } - - public interface IEcsEntityCreate : IEcsSystem - { - void OnEntityCreate(int entityID); - } - public interface IEcsEntityDestroy : IEcsSystem - { - void OnEntityDestroy(int entityID); - } - public interface IEcsEntityLifecycle : IEcsEntityCreate, IEcsEntityDestroy { } - - namespace Internal - { - [DebugColor(DebugColor.Orange)] - public sealed class EcsEntityCreateRunner : EcsRunner, IEcsEntityCreate - { - public void OnEntityCreate(int entityID) - { - foreach (var item in targets) item.OnEntityCreate(entityID); - } - } - [DebugColor(DebugColor.Orange)] - public sealed class EcsEntityDestroyRunner : EcsRunner, IEcsEntityDestroy - { - public void OnEntityDestroy(int entityID) - { - foreach (var item in targets) item.OnEntityDestroy(entityID); - } - } - } - - public interface IEcsWorldCreate : IEcsSystem - { - void OnWorldCreate(EcsWorld world); - } - public interface IEcsWorldDestroy : IEcsSystem - { - void OnWorldDestroy(EcsWorld world); - } - public interface IEcsWorldLifecycle : IEcsWorldCreate, IEcsWorldDestroy { } - - namespace Internal - { - [DebugColor(DebugColor.Orange)] - public sealed class EcsWorldCreateRunner : EcsRunner, IEcsWorldCreate - { - public void OnWorldCreate(EcsWorld world) - { - foreach (var item in targets) item.OnWorldCreate(world); - } - } - [DebugColor(DebugColor.Orange)] - public sealed class EcsWorldDestryRunner : EcsRunner, IEcsWorldDestroy - { - public void OnWorldDestroy(EcsWorld world) - { - foreach (var item in targets) item.OnWorldDestroy(world); - } - } - } -} diff --git a/src/Builtin/Worlds.cs b/src/Builtin/Worlds.cs index d92e45e..23f26cb 100644 --- a/src/Builtin/Worlds.cs +++ b/src/Builtin/Worlds.cs @@ -1,5 +1,9 @@ namespace DCFApixels.DragonECS { + internal sealed class EcsNullWorld : EcsWorld + { + public EcsNullWorld() : base(false) { } + } public sealed class EcsDefaultWorld : EcsWorld { } public sealed class EcsEventWorld : EcsWorld { } } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 752f3ab..6b0b631 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -1,16 +1,10 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using DCFApixels.DragonECS.Internal; namespace DCFApixels.DragonECS { - using Internal; - - internal sealed class EcsNullWorld : EcsWorld - { - public EcsNullWorld() : base(false) { } - } - public abstract class EcsWorld { private const short GEN_BITS = 0x7fff; @@ -19,6 +13,7 @@ namespace DCFApixels.DragonECS public static EcsWorld[] Worlds = new EcsWorld[8]; private static IntDispenser _worldIdDispenser = new IntDispenser(0); + public readonly short uniqueID; private int _worldTypeID; @@ -598,9 +593,6 @@ namespace DCFApixels.DragonECS void OnNewEntity(int entityID); void OnDelEntity(int entityID); } - #endregion - - #region Extensions internal static class WorldEventListExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] From ddb1eb1491dfdbe93c7850d689a140434a5075dc Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 04:25:09 +0800 Subject: [PATCH 3/8] refactoring --- src/Debug/EcsDebugUtility.cs | 9 ++-- src/EcsGroup.cs | 7 ++- src/EcsRunner.cs | 82 ++++++++++++++++-------------------- src/entlong.cs | 19 +++------ 4 files changed, 52 insertions(+), 65 deletions(-) diff --git a/src/Debug/EcsDebugUtility.cs b/src/Debug/EcsDebugUtility.cs index 5565e8b..341d969 100644 --- a/src/Debug/EcsDebugUtility.cs +++ b/src/Debug/EcsDebugUtility.cs @@ -5,11 +5,14 @@ namespace DCFApixels.DragonECS { public static class EcsDebugUtility { + public static string GetGenericTypeFullName(int maxDepth = 2) => GetGenericTypeFullName(typeof(T), maxDepth); + public static string GetGenericTypeFullName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, true); public static string GetGenericTypeName(int maxDepth = 2) => GetGenericTypeName(typeof(T), maxDepth); - public static string GetGenericTypeName(Type type, int maxDepth = 2) + public static string GetGenericTypeName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, false); + private static string GetGenericTypeNameInternal(Type type, int maxDepth, bool isFull) { #if (DEBUG && !DISABLE_DEBUG) - string friendlyName = type.Name; + string friendlyName = isFull ? type.FullName : type.Name; if (!type.IsGenericType || maxDepth == 0) return friendlyName; @@ -21,7 +24,7 @@ namespace DCFApixels.DragonECS Type[] typeParameters = type.GetGenericArguments(); for (int i = 0; i < typeParameters.Length; ++i) { - string typeParamName = GetGenericTypeName(typeParameters[i], maxDepth - 1); + string typeParamName = GetGenericTypeNameInternal(typeParameters[i], maxDepth - 1, false);//чтобы строка не была слишком длинной, используются сокращенные имена для типов аргументов friendlyName += (i == 0 ? typeParamName : "," + typeParamName); } friendlyName += ">"; diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 16a2159..0658ae1 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -1,13 +1,12 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +using static DCFApixels.DragonECS.EcsGroup.ThrowHalper; +#endif namespace DCFApixels.DragonECS { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - using static EcsGroup.ThrowHalper; -#endif - [StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)] public readonly ref struct EcsReadonlyGroup { diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index d657be1..7f732b2 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; +using static DCFApixels.DragonECS.EcsDebugUtility; namespace DCFApixels.DragonECS { @@ -31,21 +32,19 @@ namespace DCFApixels.DragonECS [EditorBrowsable(EditorBrowsableState.Never)] public interface IEcsRunner { - public EcsPipeline Source { get; } - public Type Interface { get; } - public IList Targets { get; } - public object Filter { get; } - public bool IsHasFilter { get; } - public bool IsDestroyed { get; } - public bool IsEmpty { get; } - - public void Destroy(); + EcsPipeline Source { get; } + Type Interface { get; } + IList Targets { get; } + object Filter { get; } + bool IsHasFilter { get; } + bool IsDestroyed { get; } + bool IsEmpty { get; } + void Destroy(); } internal static class EcsRunnerActivator { private static Dictionary _runnerHandlerTypes; //interface base type/Runner handler type pairs; - static EcsRunnerActivator() { List delayedExceptions = new List(); @@ -59,24 +58,22 @@ namespace DCFApixels.DragonECS } #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - for (int i = 0; i < runnerHandlerTypes.Count; i++) - { - var e = CheckRunnerValide(runnerHandlerTypes[i]); - if (e != null) + for (int i = 0; i < runnerHandlerTypes.Count; i++) { - runnerHandlerTypes.RemoveAt(i--); - delayedExceptions.Add(e); + var e = CheckRunnerValide(runnerHandlerTypes[i]); + if (e != null) + { + runnerHandlerTypes.RemoveAt(i--); + delayedExceptions.Add(e); + } } - } #endif _runnerHandlerTypes = new Dictionary(); foreach (var item in runnerHandlerTypes) { Type interfaceType = item.BaseType.GenericTypeArguments[0]; -// if(!_runnerHandlerTypes.ContainsKey(interfaceType.GUID))//TODO это кажется костыль, изначально все работало без этого ифа - _runnerHandlerTypes.Add(interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType, item); + _runnerHandlerTypes.Add(interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType, item); } - if (delayedExceptions.Count > 0) { foreach (var item in delayedExceptions) EcsDebug.Print(EcsConsts.DEBUG_ERROR_TAG, item.Message); @@ -91,24 +88,23 @@ namespace DCFApixels.DragonECS if (type.ReflectedType != null) { - return new EcsRunnerImplementationException($"{type.FullName}.ReflectedType must be Null, but equal to {type.ReflectedType.FullName}."); + return new EcsRunnerImplementationException($"{GetGenericTypeFullName(type, 1)}.ReflectedType must be Null, but equal to {GetGenericTypeFullName(type.ReflectedType, 1)}."); } if (!baseTypeArgument.IsInterface) { - return new EcsRunnerImplementationException($"Argument T of class EcsRunner, can only be an inetrface.The {baseTypeArgument.FullName} type is not an interface."); + return new EcsRunnerImplementationException($"Argument T of class EcsRunner, can only be an inetrface. The {GetGenericTypeFullName(baseTypeArgument, 1)} type is not an interface."); } var interfaces = type.GetInterfaces(); if (!interfaces.Any(o => o == baseTypeArgument)) { - return new EcsRunnerImplementationException($"Runner {type.FullName} does not implement interface {baseTypeArgument.FullName}."); + return new EcsRunnerImplementationException($"Runner {GetGenericTypeFullName(type, 1)} does not implement interface {GetGenericTypeFullName(baseTypeArgument, 1)}."); } return null; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void InitFor() where TInterface : IEcsSystem { @@ -116,7 +112,7 @@ namespace DCFApixels.DragonECS if (!_runnerHandlerTypes.TryGetValue(interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType, out Type runnerType)) { - throw new Exception(); + throw new EcsRunnerImplementationException($"There is no implementation of a runner for the {GetGenericTypeFullName(1)} interface."); } if (interfaceType.IsGenericType) { @@ -135,22 +131,22 @@ namespace DCFApixels.DragonECS internal static void Register(Type subclass) { #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - if (_subclass != null) - { - throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass"); - } + if (_subclass != null) + { + throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass"); + } - Type interfaceType = typeof(TInterface); + Type interfaceType = typeof(TInterface); - var interfaces = interfaceType.GetInterfaces(); - if (interfaceType.IsInterface == false) - { - throw new ArgumentException($"{typeof(TInterface).FullName} is not interface"); - } - if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsSystem)) - { - throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsSystem)} interface"); - } + var interfaces = interfaceType.GetInterfaces(); + if (interfaceType.IsInterface == false) + { + throw new ArgumentException($"{typeof(TInterface).FullName} is not interface"); + } + if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsSystem)) + { + throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsSystem)} interface"); + } #endif _subclass = subclass; } @@ -192,9 +188,7 @@ namespace DCFApixels.DragonECS #region Instantiate private static TInterface Instantiate(EcsPipeline source, TInterface[] targets, bool isHasFilter, object filter) { - if (_subclass == null) - EcsRunnerActivator.InitFor(); - + if (_subclass == null) EcsRunnerActivator.InitFor(); var instance = (EcsRunner)Activator.CreateInstance(_subclass); return (TInterface)(IEcsSystem)instance.Set(source, targets, isHasFilter, filter); } @@ -235,7 +229,6 @@ namespace DCFApixels.DragonECS OnSetup(); return this; } - internal void Rebuild() { if (_isHasFilter) @@ -243,7 +236,6 @@ namespace DCFApixels.DragonECS else Set(_source, FilterSystems(_source.AllSystems, _filter), _isHasFilter, _filter); } - public void Destroy() { _isDestroyed = true; @@ -254,11 +246,11 @@ namespace DCFApixels.DragonECS _filter = null; OnDestroy(); } - protected virtual void OnSetup() { } protected virtual void OnDestroy() { } } } + #region Extensions public static class EcsRunner { diff --git a/src/entlong.cs b/src/entlong.cs index cb1f37c..f2fd5ba 100644 --- a/src/entlong.cs +++ b/src/entlong.cs @@ -1,4 +1,5 @@ -using System; +#pragma warning disable IDE1006 +using System; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -6,9 +7,7 @@ using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { using static entlong.ThrowHalper; - // uniqueID - 32 bits - // gen - 16 bits - // world - 16 bits + // [ id 32 | gen 16 | world 16 ] /// Strong identifier/Permanent entity identifier [StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)] public readonly struct entlong : IEquatable, IEquatable @@ -34,12 +33,6 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get => this == NULL; } - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsNotNull - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => this != NULL; - } [EditorBrowsable(EditorBrowsableState.Never)] public int ID @@ -135,7 +128,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => unchecked((int)full) ^ (int)(full >> 32); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override string ToString() => $"entity(id:{id} g:{gen} w:{world} {(IsAlive ? "alive" : "not alive")})"; + public override string ToString() => $"entity(id:{id} g:{gen} w:{world} {(IsNull ? "null" : IsAlive ? "alive" : "not alive")})"; [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object obj) => obj is entlong other && full == other.full; #endregion @@ -159,9 +152,9 @@ namespace DCFApixels.DragonECS public static void ThrowIsNotAlive(entlong entity) { if (entity.IsNull) - throw new EcsFrameworkException("The entity identifier is null."); + throw new EcsFrameworkException($"The {entity} is null."); else - throw new EcsFrameworkException("The entity is not alive."); + throw new EcsFrameworkException($"The {entity} is not alive."); } } #endregion From 1ad7fbabdb01d29929c7ff24f0316795c09996c4 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 04:31:31 +0800 Subject: [PATCH 4/8] refactoring --- src/EcsPipeline.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index 198bad8..f9cf623 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -1,4 +1,5 @@ -using DCFApixels.DragonECS.RunnersCore; +using DCFApixels.DragonECS.Internal; +using DCFApixels.DragonECS.RunnersCore; using System; using System.Collections; using System.Collections.Generic; @@ -144,7 +145,6 @@ namespace DCFApixels.DragonECS private HashSet _uniqueTypes; private readonly Dictionary> _systems; private readonly string _basicLayer; - public readonly LayerList Layers; public Builder() { @@ -182,10 +182,7 @@ namespace DCFApixels.DragonECS List list; if (!_systems.TryGetValue(layerName, out list)) { - list = new List - { - new SystemsBlockMarkerSystem(layerName.ToString()) - }; + list = new List { new SystemsBlockMarkerSystem(layerName.ToString()) }; _systems.Add(layerName, list); } if ((_uniqueTypes.Add(system.GetType()) == false && isUnique)) @@ -204,8 +201,6 @@ namespace DCFApixels.DragonECS public EcsPipeline Build() { - //EcsDebug.Print(string.Join(", ", Layers)); - Add(new DeleteEmptyEntitesSystem(), EcsConsts.POST_END_LAYER); List result = new List(32); From 32429e5af8087221274b1142d04c09cd159a5055 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 05:13:11 +0800 Subject: [PATCH 5/8] refactoring rename directive to DISABLE_DRAGONECS_ASSERT_CHEKS --- src/Debug/EcsDebug.cs | 22 ++++++++----------- src/EcsGroup.cs | 26 +++++++++++------------ src/EcsPipeline.cs | 6 +++--- src/EcsRunner.cs | 4 ++-- src/EcsSubject.cs | 4 ++-- src/EcsWorld.cs | 6 +++--- src/Executors/EcsJoinAttachExecutor.cs | 14 ++++++------ src/Executors/EcsJoinHierarchyExecutor.cs | 14 ++++++------ src/Executors/EcsWhereExecutor.cs | 4 ++-- src/Pools/EcsAttachPool.cs | 16 +++++++------- src/Pools/EcsPool.cs | 12 +++++------ src/Pools/EcsSinglePool.cs | 12 +++++------ src/Pools/EcsTagPool.cs | 16 +++++++------- src/entlong.cs | 8 +++---- 14 files changed, 80 insertions(+), 84 deletions(-) diff --git a/src/Debug/EcsDebug.cs b/src/Debug/EcsDebug.cs index 8646a5a..798f56f 100644 --- a/src/Debug/EcsDebug.cs +++ b/src/Debug/EcsDebug.cs @@ -19,16 +19,13 @@ namespace DCFApixels.DragonECS public readonly ref struct AutoScope { - private readonly int id; + private readonly int _id; public AutoScope(int id) { - this.id = id; + _id = id; EcsDebug.ProfileMarkBegin(id); } - public void Dispose() - { - EcsDebug.ProfileMarkEnd(id); - } + public void Dispose() => EcsDebug.ProfileMarkEnd(_id); } } @@ -37,20 +34,19 @@ namespace DCFApixels.DragonECS public static void Set() where T : DebugService, new() => DebugService.Set(); public static void Set(DebugService service) => DebugService.Set(service); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Print(object v) => DebugService.Instance.Print(v); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Print(string tag, object v) { -#if !DISABLE_DRAGONECS_DEBUG +#if !DISABLE_DRAGONECS_DEBUGGER DebugService.Instance.Print(tag, v); #endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int RegisterMark(string name) { -#if !DISABLE_DRAGONECS_DEBUG +#if !DISABLE_DRAGONECS_DEBUGGER return DebugService.Instance.RegisterMark(name); #else return 0; @@ -59,21 +55,21 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void DeleteMark(string name) { -#if !DISABLE_DRAGONECS_DEBUG +#if !DISABLE_DRAGONECS_DEBUGGER DebugService.Instance.DeleteMark(name); #endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ProfileMarkBegin(int id) { -#if !DISABLE_DRAGONECS_DEBUG +#if !DISABLE_DRAGONECS_DEBUGGER DebugService.Instance.ProfileMarkBegin(id); #endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ProfileMarkEnd(int id) { -#if !DISABLE_DRAGONECS_DEBUG +#if !DISABLE_DRAGONECS_DEBUGGER DebugService.Instance.ProfileMarkEnd(id); #endif } @@ -145,7 +141,7 @@ namespace DCFApixels.DragonECS public DefaultDebugService() { -#if !DISABLE_DRAGONECS_DEBUG +#if !DISABLE_DRAGONECS_DEBUGGER _stopwatchs = new Stopwatch[64]; _stopwatchsNames= new string[64]; #endif diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 0658ae1..c7126d9 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS using static DCFApixels.DragonECS.EcsGroup.ThrowHalper; #endif @@ -130,7 +130,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (index < 0 || index >= Count) ThrowArgumentOutOfRange(); #endif return _dense[index]; @@ -183,7 +183,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void AddInternal(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (Has(entityID)) ThrowAlreadyContains(entityID); #endif if (++_count >= _dense.Length) @@ -201,7 +201,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void RemoveInternal(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowDoesNotContain(entityID); #endif _dense[_sparse[entityID]] = _dense[_count]; @@ -235,7 +235,7 @@ namespace DCFApixels.DragonECS public void CopyFrom(EcsReadonlyGroup group) => CopyFrom(group.GetGroupInternal()); public void CopyFrom(EcsGroup group) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (group.World != _source) throw new ArgumentException("groupFilter.WorldIndex != WorldIndex"); #endif if(_count > 0) @@ -258,7 +258,7 @@ namespace DCFApixels.DragonECS /// as Union sets public void UnionWith(EcsGroup group) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex"); #endif foreach (var item in group) @@ -272,7 +272,7 @@ namespace DCFApixels.DragonECS /// as Except sets public void ExceptWith(EcsGroup group) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex"); #endif foreach (var item in this) @@ -286,7 +286,7 @@ namespace DCFApixels.DragonECS /// as Intersect sets public void AndWith(EcsGroup group) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (World != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex"); #endif foreach (var item in this) @@ -300,7 +300,7 @@ namespace DCFApixels.DragonECS /// as Symmetric Except sets public void XorWith(EcsGroup group) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex"); #endif foreach (var item in group) @@ -316,7 +316,7 @@ namespace DCFApixels.DragonECS /// new group from pool public static EcsGroup Except(EcsGroup a, EcsGroup b) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex"); #endif EcsGroup result = a._source.GetGroupFromPool(); @@ -330,7 +330,7 @@ namespace DCFApixels.DragonECS /// new group from pool public static EcsGroup And(EcsGroup a, EcsGroup b) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex"); #endif EcsGroup result = a._source.GetGroupFromPool(); @@ -344,7 +344,7 @@ namespace DCFApixels.DragonECS /// new group from pool public static EcsGroup Union(EcsGroup a, EcsGroup b) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex"); #endif EcsGroup result = a._source.GetGroupFromPool(); @@ -461,7 +461,7 @@ namespace DCFApixels.DragonECS #endregion #region ThrowHalper -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS internal static class ThrowHalper { [MethodImpl(MethodImplOptions.NoInlining)] diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index f9cf623..2d51e6e 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -90,7 +90,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Run() { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS CheckBeforeInitForMethod(nameof(Run)); CheckAfterDestroyForMethod(nameof(Run)); #endif @@ -101,7 +101,7 @@ namespace DCFApixels.DragonECS if (_isEmptyDummy) return; -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS CheckBeforeInitForMethod(nameof(Run)); #endif if (_isDestoryed == true) @@ -115,7 +115,7 @@ namespace DCFApixels.DragonECS #endregion #region StateChecks -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS private void CheckBeforeInitForMethod(string methodName) { if (!_isInit) diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index 7f732b2..7fe8745 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -57,7 +57,7 @@ namespace DCFApixels.DragonECS .Where(type => type.BaseType != null && type.BaseType.IsGenericType && runnerBaseType == type.BaseType.GetGenericTypeDefinition())); } -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS for (int i = 0; i < runnerHandlerTypes.Count; i++) { var e = CheckRunnerValide(runnerHandlerTypes[i]); @@ -130,7 +130,7 @@ namespace DCFApixels.DragonECS private static Type _subclass; internal static void Register(Type subclass) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (_subclass != null) { throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass"); diff --git a/src/EcsSubject.cs b/src/EcsSubject.cs index 3dd86f5..9e096ed 100644 --- a/src/EcsSubject.cs +++ b/src/EcsSubject.cs @@ -83,7 +83,7 @@ namespace DCFApixels.DragonECS public void IncludeImplicit() { int id = _world.GetComponentID(); -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{typeof(TComponent).Name} already in constraints list."); #endif _inc.Add(_world.GetComponentID()); @@ -91,7 +91,7 @@ namespace DCFApixels.DragonECS public void ExcludeImplicit() { int id = _world.GetComponentID(); -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{typeof(TComponent).Name} already in constraints list."); #endif _exc.Add(_world.GetComponentID()); diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 6b0b631..7c88a0a 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -255,7 +255,7 @@ namespace DCFApixels.DragonECS #region IsMatchesMask public bool IsMatchesMask(EcsMask mask, int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (mask._worldType != Archetype) throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TTableArhetype)"); #endif @@ -384,7 +384,7 @@ namespace DCFApixels.DragonECS { var count = --_componentCounts[entityID]; if(count == 0 && _allEntites.Has(entityID)) DelEntity(entityID); -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (count < 0) throw new EcsFrameworkException("нарушен баланс инкремента/декремента компонентов"); #endif } @@ -402,7 +402,7 @@ namespace DCFApixels.DragonECS } internal void ReleaseGroup(EcsGroup group) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (group.World != this) throw new ArgumentException("groupFilter.WorldIndex != this"); #endif diff --git a/src/Executors/EcsJoinAttachExecutor.cs b/src/Executors/EcsJoinAttachExecutor.cs index d0d5acf..a307e1f 100644 --- a/src/Executors/EcsJoinAttachExecutor.cs +++ b/src/Executors/EcsJoinAttachExecutor.cs @@ -45,12 +45,12 @@ namespace DCFApixels.DragonECS { _executeJoin.Begin(); var world = _subject.World; -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения. #endif if (!_isInitTargetWorld) InitTargetWorlds(sourceGroup.World); -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS else if (_targetWorld != sourceGroup.World) throw new System.ArgumentException();//TODO составить текст исключения. это проверка на то что пользователь использует правильный мир #endif @@ -151,35 +151,35 @@ namespace DCFApixels.DragonECS public bool Has(int attachedEnttiyID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. #endif return _executer.Has(attachedEnttiyID); } public EntityLinkedList.EnumerableSpan GetNodes(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. #endif return _executer.GetNodes(entityID); } public int GetNode(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. #endif return _executer.GetNode(entityID); } public int GetNodesCount(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. #endif return _executer.GetNodesCount(entityID); } public bool HasNode(int entityID, int attachedEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. #endif return _executer.HasNode(entityID, attachedEntityID); diff --git a/src/Executors/EcsJoinHierarchyExecutor.cs b/src/Executors/EcsJoinHierarchyExecutor.cs index 34ff289..9e989b6 100644 --- a/src/Executors/EcsJoinHierarchyExecutor.cs +++ b/src/Executors/EcsJoinHierarchyExecutor.cs @@ -47,12 +47,12 @@ namespace DCFApixels.DragonECS { var world = _subject.World; _executeJoin.Begin(); -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (sourceGroup.IsNull) throw new ArgumentNullException();//TODO составить текст исключения. #endif if (!_isInitTargetWorld) InitTargetWorlds(sourceGroup.World); -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS else if (_targetWorld != sourceGroup.World) throw new ArgumentException();//TODO составить текст исключения. это проверка на то что пользователь использует правильный мир #endif @@ -160,35 +160,35 @@ namespace DCFApixels.DragonECS public bool Has(int attachedEnttiyID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. #endif return _executer.Has(attachedEnttiyID); } public EntityLinkedList.EnumerableSpan GetNodes(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. #endif return _executer.GetNodes(entityID); } public int GetNode(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. #endif return _executer.GetNode(entityID); } public int GetNodesCount(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. #endif return _executer.GetNodesCount(entityID); } public bool HasNode(int entityID, int attachedEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. #endif return _executer.HasNode(entityID, attachedEntityID); diff --git a/src/Executors/EcsWhereExecutor.cs b/src/Executors/EcsWhereExecutor.cs index c3121d4..b15bfff 100644 --- a/src/Executors/EcsWhereExecutor.cs +++ b/src/Executors/EcsWhereExecutor.cs @@ -30,7 +30,7 @@ namespace DCFApixels.DragonECS { using (_executeWhere.Auto()) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения. #endif _subject.GetIteratorFor(sourceGroup).CopyTo(_filteredGroup); @@ -62,7 +62,7 @@ namespace DCFApixels.DragonECS } public EcsGroup.Enumerator GetEnumerator() { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. #endif return group.GetEnumerator(); diff --git a/src/Pools/EcsAttachPool.cs b/src/Pools/EcsAttachPool.cs index cf58bcd..3348174 100644 --- a/src/Pools/EcsAttachPool.cs +++ b/src/Pools/EcsAttachPool.cs @@ -30,7 +30,7 @@ namespace DCFApixels.DragonECS } } -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS private short _sanitizeTargetWorld = -1; #endif @@ -61,7 +61,7 @@ namespace DCFApixels.DragonECS #region Methods public void Add(int entityID, entlong target) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (_sanitizeTargetWorld > 0 && target.world != _sanitizeTargetWorld) ThrowWorldDifferent(entityID); _sanitizeTargetWorld = target.world; if (Has(entityID)) ThrowAlreadyHasComponent(entityID); @@ -80,7 +80,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Set(int entityID, entlong target) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) ThrowWorldDifferent(entityID); _sanitizeTargetWorld = target.world; @@ -98,7 +98,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref readonly T Read(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif return ref _items[entityID]; @@ -110,7 +110,7 @@ namespace DCFApixels.DragonECS } public void Del(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif _entities.Remove(entityID); @@ -125,7 +125,7 @@ namespace DCFApixels.DragonECS } public void Copy(int fromEntityID, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif if (Has(toEntityID)) @@ -135,7 +135,7 @@ namespace DCFApixels.DragonECS } public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif if (Has(toEntityID)) @@ -168,7 +168,7 @@ namespace DCFApixels.DragonECS } ref T IEcsPool.Write(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif return ref _items[entityID]; diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 0f04f13..23bbbd8 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -59,7 +59,7 @@ namespace DCFApixels.DragonECS // using (_addMark.Auto()) // { ref int itemIndex = ref _mapping[entityID]; -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (itemIndex > 0) ThrowAlreadyHasComponent(entityID); #endif if (_recycledItemsCount > 0) @@ -82,7 +82,7 @@ namespace DCFApixels.DragonECS public ref T Write(int entityID) { // using (_writeMark.Auto()) -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif _listeners.InvokeOnWrite(entityID); @@ -92,7 +92,7 @@ namespace DCFApixels.DragonECS public ref readonly T Read(int entityID) { // using (_readMark.Auto()) -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif return ref _items[_mapping[entityID]]; @@ -126,7 +126,7 @@ namespace DCFApixels.DragonECS } public void Del(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif ref int itemIndex = ref _mapping[entityID]; @@ -145,14 +145,14 @@ namespace DCFApixels.DragonECS } public void Copy(int fromEntityID, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif _componentCopyHandler.Copy(ref Write(fromEntityID), ref TryAddOrWrite(toEntityID)); } public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif _componentCopyHandler.Copy(ref Write(fromEntityID), ref toWorld.GetPool().TryAddOrWrite(toEntityID)); diff --git a/src/Pools/EcsSinglePool.cs b/src/Pools/EcsSinglePool.cs index e829af6..8359d66 100644 --- a/src/Pools/EcsSinglePool.cs +++ b/src/Pools/EcsSinglePool.cs @@ -47,7 +47,7 @@ namespace DCFApixels.DragonECS #region Methods public ref T Add(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (Has(entityID)) ThrowAlreadyHasComponent(entityID); #endif _mapping[entityID] = ++_count; @@ -58,7 +58,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T Write(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif _listeners.InvokeOnWrite(entityID); @@ -74,7 +74,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref readonly T Read(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif return ref _component; @@ -86,7 +86,7 @@ namespace DCFApixels.DragonECS } public void Del(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif _mapping[entityID] = 0; @@ -100,14 +100,14 @@ namespace DCFApixels.DragonECS } public void Copy(int fromEntityID, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif TryAddOrWrite(toEntityID); } public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif toWorld.GetPool().TryAddOrWrite(toEntityID); diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 13270d8..bf36ebb 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -43,7 +43,7 @@ namespace DCFApixels.DragonECS #region Method public void Add(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (Has(entityID)) ThrowAlreadyHasComponent(entityID); #endif _count++; @@ -68,7 +68,7 @@ namespace DCFApixels.DragonECS } public void Del(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif _mapping[entityID] = false; @@ -82,14 +82,14 @@ namespace DCFApixels.DragonECS } public void Copy(int fromEntityID, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif TryAdd(toEntityID); } public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); #endif toWorld.GetPool().TryAdd(toEntityID); @@ -138,14 +138,14 @@ namespace DCFApixels.DragonECS } ref readonly T IEcsPool.Read(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif return ref _fakeComponent; } ref T IEcsPool.Write(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif return ref _fakeComponent; @@ -153,14 +153,14 @@ namespace DCFApixels.DragonECS void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID); object IEcsPool.GetRaw(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif return _fakeComponent; } void IEcsPool.SetRaw(int entityID, object dataRaw) { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!Has(entityID)) ThrowNotHaveComponent(entityID); #endif } diff --git a/src/entlong.cs b/src/entlong.cs index f2fd5ba..52841b1 100644 --- a/src/entlong.cs +++ b/src/entlong.cs @@ -40,7 +40,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsAlive) ThrowIsNotAlive(this); #endif return id; @@ -52,7 +52,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsAlive) ThrowIsNotAlive(this); #endif return gen; @@ -63,7 +63,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsAlive) ThrowIsNotAlive(this); #endif return EcsWorld.Worlds[world]; @@ -75,7 +75,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS if (!IsAlive) ThrowIsNotAlive(this); #endif return world; From 7cc02d00ba111690908a8b5cafa66f59abc4be2e Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 06:18:09 +0800 Subject: [PATCH 6/8] moving part of the API into a separate module --- src/Debug/EcsDebug.cs | 3 +- src/EcsWorld.cs | 94 ++------- src/Executors/EcsJoinAttachExecutor.cs | 189 ----------------- src/Executors/EcsJoinHierarchyExecutor.cs | 198 ------------------ src/Executors/EcsQueryExecutor.cs | 3 +- src/Executors/EcsWhereExecutor.cs | 2 +- src/Pools/EcsNotNullPool.cs | 140 ------------- src/Pools/EcsSinglePool.cs | 177 ---------------- src/Utils/ArrayUtility.cs | 2 +- src/Utils/IntDispenser.cs | 2 +- src/Utils/{Extensions.cs => IntExtensions.cs} | 2 +- src/Utils/SparseArray.cs | 2 +- src/Utils/SparseSet.cs | 2 +- 13 files changed, 28 insertions(+), 788 deletions(-) delete mode 100644 src/Executors/EcsJoinAttachExecutor.cs delete mode 100644 src/Executors/EcsJoinHierarchyExecutor.cs delete mode 100644 src/Pools/EcsNotNullPool.cs delete mode 100644 src/Pools/EcsSinglePool.cs rename src/Utils/{Extensions.cs => IntExtensions.cs} (83%) diff --git a/src/Debug/EcsDebug.cs b/src/Debug/EcsDebug.cs index 798f56f..1e29074 100644 --- a/src/Debug/EcsDebug.cs +++ b/src/Debug/EcsDebug.cs @@ -1,4 +1,5 @@ -using System; +using DCFApixels.DragonECS.Utils; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 7c88a0a..690a5d9 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -1,7 +1,8 @@ -using System; +using DCFApixels.DragonECS.Internal; +using DCFApixels.DragonECS.Utils; +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; -using DCFApixels.DragonECS.Internal; namespace DCFApixels.DragonECS { @@ -144,7 +145,7 @@ namespace DCFApixels.DragonECS } #endregion - #region Queries + #region Subjects public TSubject GetSubject() where TSubject : EcsSubject { int uniqueID = WorldMetaStorage.GetSubjectId(_worldTypeID); @@ -154,104 +155,45 @@ namespace DCFApixels.DragonECS _subjects[uniqueID] = EcsSubject.Builder.Build(this); return (TSubject)_subjects[uniqueID]; } - #region Iterate - public EcsSubjectIterator IterateFor(EcsReadonlyGroup sourceGroup, out TSubject subject) where TSubject : EcsSubject - { - - subject = GetSubject(); - return subject.GetIteratorFor(sourceGroup); - } - public EcsSubjectIterator IterateFor(EcsReadonlyGroup sourceGroup) where TSubject : EcsSubject - { - return GetSubject().GetIteratorFor(sourceGroup); - } - public EcsSubjectIterator Iterate(out TSubject subject) where TSubject : EcsSubject - { - subject = GetSubject(); - return subject.GetIterator(); - } - public EcsSubjectIterator Iterate() where TSubject : EcsSubject - { - return GetSubject().GetIterator(); - } #endregion - #region Where - private EcsWhereExecutor GetWhereExecutor() where TSubject : EcsSubject + #region Queries + public TExecutor GetExecutor(Func builder) where TExecutor: EcsQueryExecutor { - int id = WorldMetaStorage.GetExecutorId>(_worldTypeID); + int id = WorldMetaStorage.GetExecutorId(_worldTypeID); if (id >= _executors.Length) Array.Resize(ref _executors, _executors.Length << 1); if (_executors[id] == null) - _executors[id] = new EcsWhereExecutor(GetSubject()); - return (EcsWhereExecutor)_executors[id]; + _executors[id] = builder(this); + return (TExecutor)_executors[id]; + } + + private EcsWhereExecutor EcsWhereExecutorBuilder(EcsWorld world) where TSubject : EcsSubject + { + return new EcsWhereExecutor(world.GetSubject()); } public EcsWhereResult WhereFor(EcsReadonlyGroup sourceGroup, out TSubject subject) where TSubject : EcsSubject { - var executor = GetWhereExecutor(); + var executor = GetExecutor(EcsWhereExecutorBuilder); subject = executor.Subject; return executor.ExecuteFor(sourceGroup); } public EcsWhereResult WhereFor(EcsReadonlyGroup sourceGroup) where TSubject : EcsSubject { - return GetWhereExecutor().ExecuteFor(sourceGroup); + return GetExecutor(EcsWhereExecutorBuilder).ExecuteFor(sourceGroup); } public EcsWhereResult Where(out TSubject subject) where TSubject : EcsSubject { - var executor = GetWhereExecutor(); + var executor = GetExecutor(EcsWhereExecutorBuilder); subject = executor.Subject; return executor.Execute(); } public EcsWhereResult Where() where TSubject : EcsSubject { - return GetWhereExecutor().Execute(); + return GetExecutor(EcsWhereExecutorBuilder).Execute(); } #endregion - #region Join - private EcsJoinAttachExecutor GetJoinAttachExecutor() - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - int id = WorldMetaStorage.GetExecutorId>(_worldTypeID); - if (id >= _executors.Length) - Array.Resize(ref _executors, _executors.Length << 1); - if (_executors[id] == null) - _executors[id] = new EcsJoinAttachExecutor(GetSubject()); - return (EcsJoinAttachExecutor)_executors[id]; - } - public EcsJoinAttachResult JoinFor(EcsReadonlyGroup sourceGroup, out TSubject subject) - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - var executor = GetJoinAttachExecutor(); - subject = executor.Subject; - return executor.ExecuteFor(sourceGroup); - } - public EcsJoinAttachResult JoinFor(EcsReadonlyGroup sourceGroup) - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - return GetJoinAttachExecutor().ExecuteFor(sourceGroup); - } - public EcsJoinAttachResult Join(out TSubject subject) - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - var executor = GetJoinAttachExecutor(); - subject = executor.Subject; - return executor.Execute(); - } - public EcsJoinAttachResult Join() - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - return GetJoinAttachExecutor().Execute(); - } - #endregion - - #endregion - #region IsMatchesMask public bool IsMatchesMask(EcsMask mask, int entityID) { diff --git a/src/Executors/EcsJoinAttachExecutor.cs b/src/Executors/EcsJoinAttachExecutor.cs deleted file mode 100644 index a307e1f..0000000 --- a/src/Executors/EcsJoinAttachExecutor.cs +++ /dev/null @@ -1,189 +0,0 @@ -using Unity.Profiling; - -namespace DCFApixels.DragonECS -{ - public sealed class EcsJoinAttachExecutor : EcsQueryExecutor - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - private readonly TSubject _subject; - internal readonly EcsGroup _filteredGroup; - private EcsWorld _targetWorld; - - private EcsAttachPool _targetPool; - - private int _targetWorldCapacity = -1; - private int _targetPoolCapacity = -1; - - private int[] _mapping; - private int[] _counts; - private EntityLinkedList _linkedBasket; - - private bool _isInitTargetWorld = false; - - private ProfilerMarker _executeJoin = new ProfilerMarker("JoinAttachQuery.Join"); - - private long _executeVersion; - - #region Properties - public TSubject Subject => _subject; - internal long ExecuteVersion => _executeVersion; - #endregion - - #region Constructors - public EcsJoinAttachExecutor(TSubject subject) - { - _subject = subject; - _filteredGroup = EcsGroup.New(subject.World); - _targetPool = subject.World.GetPool(); - } - #endregion - - #region Methods - public EcsJoinAttachResult Execute() => ExecuteFor(_targetPool.Entities); - public EcsJoinAttachResult ExecuteFor(EcsReadonlyGroup sourceGroup) - { - _executeJoin.Begin(); - var world = _subject.World; -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения. -#endif - if (!_isInitTargetWorld) - InitTargetWorlds(sourceGroup.World); -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - else - if (_targetWorld != sourceGroup.World) throw new System.ArgumentException();//TODO составить текст исключения. это проверка на то что пользователь использует правильный мир -#endif - - //Подготовка массивов - if (_targetWorldCapacity < _targetWorld.Capacity) - { - _targetWorldCapacity = _targetWorld.Capacity; - _mapping = new int[_targetWorldCapacity]; - _counts = new int[_targetWorldCapacity]; - } - else - { - ArrayUtility.Fill(_counts, 0); - ArrayUtility.Fill(_mapping, 0); - } - if (_targetPoolCapacity < _targetPool.Capacity) - { - _targetPoolCapacity = _targetPool.Capacity; - _linkedBasket.Resize(_targetPoolCapacity); - } - _linkedBasket.Clear(); - //Конец подготовки массивов - - var iterator = new EcsSubjectIterator(_subject, sourceGroup); - foreach (var attachID in iterator) - { - entlong attachTarget = _targetPool.Read(attachID).Target; - if (!attachTarget.IsAlive) - { - //_targetPool.Del(attachID); - continue; - } - int attachTargetID = attachTarget.id; - //if (!CheckMaskInternal(targetWorldWhereQuery.query.mask, attachTargetID)) continue; //TODO проверить что все работает //исчключить все аттачи, цели которых не входят в targetWorldWhereQuery - - ref int nodeIndex = ref _mapping[attachTargetID]; - if (nodeIndex <= 0) - nodeIndex = _linkedBasket.Add(attachID); - else - _linkedBasket.Insert(nodeIndex, attachID); - _counts[attachTargetID]++; - } - - _executeVersion++; - _executeJoin.End(); - - return new EcsJoinAttachResult(_subject, this , _executeVersion); - } - private void InitTargetWorlds(EcsWorld targetWorld) - { - _targetWorld = targetWorld; - - _targetWorldCapacity = _targetWorld.Capacity; - _mapping = new int[_targetWorldCapacity]; - _counts = new int[_targetWorldCapacity]; - - _targetPoolCapacity = _targetPool.Capacity; - _linkedBasket = new EntityLinkedList(_targetPoolCapacity); - _isInitTargetWorld = true; - } - internal sealed override void Destroy() - { - _filteredGroup.Release(); - _targetWorld = null; - _mapping = null; - _counts = null; - _linkedBasket = null; - } - #endregion - - #region Internal result methods - internal bool Has(int attachedEnttiyID) => _filteredGroup.Has(attachedEnttiyID); - internal EntityLinkedList.EnumerableSpan GetNodes(int entityID) => _linkedBasket.Span(_mapping[entityID], _counts[entityID]); - internal int GetNode(int entityID) => _counts[entityID] > 0 ? _linkedBasket.Get(_mapping[entityID]) : 0; - internal int GetNodesCount(int entityID) => _counts[entityID]; - internal bool HasNode(int entityID, int attachedEntityID) => _filteredGroup.Has(attachedEntityID) && _targetPool.Read(attachedEntityID).Target.id == entityID; - #endregion - } - - #region JoinAttachExecuter Results - public readonly ref struct EcsJoinAttachResult - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - public readonly TSubject s; - private readonly EcsJoinAttachExecutor _executer; - private readonly long _verison; - - public bool IsRelevant => _verison == _executer.ExecuteVersion; - - public EcsJoinAttachResult(TSubject s, EcsJoinAttachExecutor executer, long version) - { - this.s = s; - _executer = executer; - _verison = version; - } - - public bool Has(int attachedEnttiyID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.Has(attachedEnttiyID); - } - public EntityLinkedList.EnumerableSpan GetNodes(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.GetNodes(entityID); - } - public int GetNode(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.GetNode(entityID); - } - public int GetNodesCount(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.GetNodesCount(entityID); - } - public bool HasNode(int entityID, int attachedEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.HasNode(entityID, attachedEntityID); - } - } - #endregion -} diff --git a/src/Executors/EcsJoinHierarchyExecutor.cs b/src/Executors/EcsJoinHierarchyExecutor.cs deleted file mode 100644 index 9e989b6..0000000 --- a/src/Executors/EcsJoinHierarchyExecutor.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System; -using Unity.Profiling; - -namespace DCFApixels.DragonECS -{ - public sealed class EcsJoinHierarchyExecutor : EcsQueryExecutor - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - private readonly TSubject _subject; - internal readonly EcsGroup _filteredGroup; - private EcsWorld _targetWorld; - - private EcsAttachPool _targetPool; - - private int _targetWorldCapacity = -1; - private int _targetPoolCapacity = -1; - - private int[] _mapping; - private int[] _counts; - private EntityLinkedList _linkedBasket; - - private bool _isInitTargetWorld = false; - - private ProfilerMarker _executeWhere = new ProfilerMarker("JoinAttachQuery.Where"); - private ProfilerMarker _executeJoin = new ProfilerMarker("JoinAttachQuery.Join"); - - private long _executeVersion; - - #region Properties - public TSubject Subject => _subject; - internal long ExecuteVersion => _executeVersion; - #endregion - - #region Constructors - public EcsJoinHierarchyExecutor(TSubject subject) - { - _subject = subject; - _filteredGroup = EcsGroup.New(subject.World); - _targetPool = subject.World.GetPool(); - } - #endregion - - #region Methods - public EcsJoinHierarchyResult Execute() => ExecuteFor(_targetPool.Entities); - public EcsJoinHierarchyResult ExecuteFor(EcsReadonlyGroup sourceGroup) - { - var world = _subject.World; - _executeJoin.Begin(); -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (sourceGroup.IsNull) throw new ArgumentNullException();//TODO составить текст исключения. -#endif - if (!_isInitTargetWorld) - InitTargetWorlds(sourceGroup.World); -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - else - if (_targetWorld != sourceGroup.World) throw new ArgumentException();//TODO составить текст исключения. это проверка на то что пользователь использует правильный мир -#endif - - //Подготовка массивов - if (_targetWorldCapacity < _targetWorld.Capacity) - { - _targetWorldCapacity = _targetWorld.Capacity; - _mapping = new int[_targetWorldCapacity]; - _counts = new int[_targetWorldCapacity]; - } - else - { - ArrayUtility.Fill(_counts, 0); - ArrayUtility.Fill(_mapping, 0); - } - if (_targetPoolCapacity < _targetPool.Capacity) - { - _targetPoolCapacity = _targetPool.Capacity; - _linkedBasket.Resize(_targetPoolCapacity); - } - _linkedBasket.Clear(); - //Конец подготовки массивов - - var iterator = new EcsSubjectIterator(_subject, sourceGroup); - foreach (var attachID in iterator) - { - entlong attachTarget = _targetPool.Read(attachID).Target; - if (!attachTarget.IsAlive) - { - //_targetPool.Del(attachID); - continue; - } - int attachTargetID = attachTarget.id; - //if (!CheckMaskInternal(targetWorldWhereQuery.query.mask, attachTargetID)) continue; //TODO проверить что все работает //исчключить все аттачи, цели которых не входят в targetWorldWhereQuery - - ref int nodeIndex = ref _mapping[attachTargetID]; - if (nodeIndex <= 0) - nodeIndex = _linkedBasket.Add(attachID); - else - _linkedBasket.Insert(nodeIndex, attachID); - _counts[attachTargetID]++; - } - - _executeVersion++; - _executeJoin.End(); - - return new EcsJoinHierarchyResult(_subject, this , _executeVersion); - } - private void InitTargetWorlds(EcsWorld targetWorld) - { - _targetWorld = targetWorld; - - _targetWorldCapacity = _targetWorld.Capacity; - _mapping = new int[_targetWorldCapacity]; - _counts = new int[_targetWorldCapacity]; - - _targetPoolCapacity = _targetPool.Capacity; - _linkedBasket = new EntityLinkedList(_targetPoolCapacity); - _isInitTargetWorld = true; - } - internal sealed override void Destroy() - { - _filteredGroup.Release(); - _targetWorld = null; - _mapping = null; - _counts = null; - _linkedBasket = null; - } - #endregion - - #region Internal result methods - internal bool Has(int attachedEnttiyID) => _filteredGroup.Has(attachedEnttiyID); - - internal EntityLinkedList.EnumerableSpan GetNodes(int entityID) => _linkedBasket.Span(_mapping[entityID], _counts[entityID]); - internal int GetNode(int entityID) => _counts[entityID] > 0 ? _linkedBasket.Get(_mapping[entityID]) : 0; - internal int GetNodesCount(int entityID) => _counts[entityID]; - internal bool HasNode(int entityID, int attachedEntityID) => _filteredGroup.Has(attachedEntityID) && _targetPool.Read(attachedEntityID).Target.id == entityID; - - - internal EntityLinkedList.EnumerableSpan GetSubNodes(int entityID) => throw new NotImplementedException(); - internal int GetSubNode(int entityID) => throw new NotImplementedException(); - internal bool GetSubNodesCount(int entityID, int attachedEntityID) => throw new NotImplementedException(); - internal bool HasSubNode(int entityID, int attachedEntityID) => throw new NotImplementedException(); - #endregion - } - - #region JoinAttachExecuter Results - public readonly ref struct EcsJoinHierarchyResult - where TSubject : EcsSubject - where TAttachComponent : struct, IEcsAttachComponent - { - public readonly TSubject s; - private readonly EcsJoinHierarchyExecutor _executer; - private readonly long _verison; - - public bool IsRelevant => _verison == _executer.ExecuteVersion; - - public EcsJoinHierarchyResult(TSubject s, EcsJoinHierarchyExecutor executer, long version) - { - this.s = s; - _executer = executer; - _verison = version; - } - - public bool Has(int attachedEnttiyID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.Has(attachedEnttiyID); - } - public EntityLinkedList.EnumerableSpan GetNodes(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.GetNodes(entityID); - } - public int GetNode(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.GetNode(entityID); - } - public int GetNodesCount(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.GetNodesCount(entityID); - } - public bool HasNode(int entityID, int attachedEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения. -#endif - return _executer.HasNode(entityID, attachedEntityID); - } - } - #endregion -} diff --git a/src/Executors/EcsQueryExecutor.cs b/src/Executors/EcsQueryExecutor.cs index 1a15dc1..8b8534e 100644 --- a/src/Executors/EcsQueryExecutor.cs +++ b/src/Executors/EcsQueryExecutor.cs @@ -2,6 +2,7 @@ { public abstract class EcsQueryExecutor { - internal abstract void Destroy(); + internal void Destroy() => OnDestroy(); + protected abstract void OnDestroy(); } } diff --git a/src/Executors/EcsWhereExecutor.cs b/src/Executors/EcsWhereExecutor.cs index b15bfff..c7ccc97 100644 --- a/src/Executors/EcsWhereExecutor.cs +++ b/src/Executors/EcsWhereExecutor.cs @@ -37,7 +37,7 @@ namespace DCFApixels.DragonECS return new EcsWhereResult(this, _filteredGroup.Readonly); } } - internal sealed override void Destroy() + protected sealed override void OnDestroy() { _filteredGroup.Release(); } diff --git a/src/Pools/EcsNotNullPool.cs b/src/Pools/EcsNotNullPool.cs deleted file mode 100644 index 7e482d9..0000000 --- a/src/Pools/EcsNotNullPool.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace DCFApixels.DragonECS -{ - // - /// Pool for IEcsNotNullComponent components - public sealed class EcsNotNullPool : IEcsPoolImplementation, IEnumerable //IntelliSense hack - where T : struct, IEcsNotNullComponent - { - private EcsWorld _source; - private int _id; - - private T[] _items; //sparse - private int _count; - - private IEcsComponentReset _componentResetHandler; - private IEcsComponentCopy _componentCopyHandler; - - private List _listeners; - - #region Properites - public int Count => _count; - public int Capacity => _items.Length; - public int ComponentID => _id; - public Type ComponentType => typeof(T); - public EcsWorld World => _source; - #endregion - - #region Init - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) - { - _source = world; - _id = componentID; - - _items = new T[world.Capacity]; - _count = 0; - - _listeners = new List(); - - _componentResetHandler = EcsComponentResetHandler.instance; - _componentCopyHandler = EcsComponentCopyHandler.instance; - } - #endregion - - #region Methods - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref T Write(int entityID) - { - _listeners.InvokeOnWrite(entityID); - return ref _items[entityID]; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly T Read(int entityID) - { - return ref _items[entityID]; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(int entityID) - { - return true; - } - public void Copy(int fromEntityID, int toEntityID) - { - _componentCopyHandler.Copy(ref Write(fromEntityID), ref Write(toEntityID)); - } - public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) - { - _componentCopyHandler.Copy(ref Write(fromEntityID), ref toWorld.GetPool().Write(toEntityID)); - } - #endregion - - #region Callbacks - void IEcsPoolImplementation.OnWorldResize(int newSize) - { - Array.Resize(ref _items, newSize); - } - void IEcsPoolImplementation.OnWorldDestroy() { } - void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) - { - foreach (var entityID in buffer) - _componentResetHandler.Reset(ref _items[entityID]); - } - #endregion - - #region Other - ref T IEcsPool.Add(int entityID) => ref Write(entityID); - ref readonly T IEcsPool.Read(int entityID) => ref Read(entityID); - ref T IEcsPool.Write(int entityID) => ref Write(entityID); - void IEcsPool.Del(int entityID) { } - void IEcsPool.AddRaw(int entityID, object dataRaw) => Write(entityID) = (T)dataRaw; - object IEcsPool.GetRaw(int entityID) => Write(entityID); - void IEcsPool.SetRaw(int entityID, object dataRaw) => Write(entityID) = (T)dataRaw; - #endregion - - #region Listeners - public void AddListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Add(listener); - } - public void RemoveListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Remove(listener); - } - #endregion - - #region IEnumerator - IntelliSense hack - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - #endregion - } - /// - /// Not null component. Is present on all entities, without explicit addition and cannot be deleted - /// - public interface IEcsNotNullComponent { } - public static class EcsNotNullPoolExt - { - public static EcsNotNullPool GetPool(this EcsWorld self) where TNotNullComponent : struct, IEcsNotNullComponent - { - return self.GetPool>(); - } - - public static EcsNotNullPool Include(this EcsSubjectBuilderBase self) where TNotNullComponent : struct, IEcsNotNullComponent - { - return self.Include>(); - } - public static EcsNotNullPool Exclude(this EcsSubjectBuilderBase self) where TNotNullComponent : struct, IEcsNotNullComponent - { - return self.Exclude>(); - } - public static EcsNotNullPool Optional(this EcsSubjectBuilderBase self) where TNotNullComponent : struct, IEcsNotNullComponent - { - return self.Optional>(); - } - } -} diff --git a/src/Pools/EcsSinglePool.cs b/src/Pools/EcsSinglePool.cs deleted file mode 100644 index 8359d66..0000000 --- a/src/Pools/EcsSinglePool.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace DCFApixels.DragonECS -{ - using static EcsPoolThrowHalper; - public sealed class EcsSinglePool : IEcsPoolImplementation, IEnumerable //IntelliSense hack - where T : struct, IEcsSingleComponent - { - private EcsWorld _source; - private int _id; - - private int[] _mapping; - - private int _count; - private T _component; - - private List _listeners; - - #region Properites - public ref T Instance - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref _component; - } - public int Count => _count; - int IEcsPool.Capacity => -1; - public int ComponentID => _id; - public Type ComponentType => typeof(T); - public EcsWorld World => _source; - #endregion - - #region Init - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) - { - _source = world; - _id = componentID; - - _mapping = new int[world.Capacity]; - _count = 0; - _listeners = new List(); - } - #endregion - - #region Methods - public ref T Add(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (Has(entityID)) ThrowAlreadyHasComponent(entityID); -#endif - _mapping[entityID] = ++_count; - this.IncrementEntityComponentCount(entityID); - _listeners.InvokeOnAddAndWrite(entityID); - return ref _component; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref T Write(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowNotHaveComponent(entityID); -#endif - _listeners.InvokeOnWrite(entityID); - return ref _component; - } - public ref T TryAddOrWrite(int entityID) - { - if (!Has(entityID)) - return ref Add(entityID); - return ref Write(entityID); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly T Read(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowNotHaveComponent(entityID); -#endif - return ref _component; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(int entityID) - { - return _mapping[entityID] > 0; - } - public void Del(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowNotHaveComponent(entityID); -#endif - _mapping[entityID] = 0; - _count--; - this.DecrementEntityComponentCount(entityID); - _listeners.InvokeOnDel(entityID); - } - public void TryDel(int entityID) - { - if (Has(entityID)) Del(entityID); - } - public void Copy(int fromEntityID, int toEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); -#endif - TryAddOrWrite(toEntityID); - } - public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); -#endif - toWorld.GetPool().TryAddOrWrite(toEntityID); - } - #endregion - - #region Callbacks - void IEcsPoolImplementation.OnWorldResize(int newSize) - { - Array.Resize(ref _mapping, newSize); - } - void IEcsPoolImplementation.OnWorldDestroy() { } - void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) - { - foreach (var entityID in buffer) - TryDel(entityID); - } - #endregion - - #region Other - void IEcsPool.AddRaw(int entityID, object dataRaw) => Instance = (T)dataRaw; - object IEcsPool.GetRaw(int entityID) => Instance; - void IEcsPool.SetRaw(int entityID, object dataRaw) => Instance = (T)dataRaw; - #endregion - - #region Listeners - public void AddListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Add(listener); - } - public void RemoveListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Remove(listener); - } - #endregion - - #region IEnumerator - IntelliSense hack - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - #endregion - } - /// Singleton component - public interface IEcsSingleComponent { } - public static class EcsSinglePoolExt - { - public static EcsSinglePool GetPool(this EcsWorld self) - where TSingleComponent : struct, IEcsSingleComponent - { - return self.GetPool>(); - } - - public static EcsSinglePool Include(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent - { - return self.Include>(); - } - public static EcsSinglePool Exclude(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent - { - return self.Exclude>(); - } - public static EcsSinglePool Optional(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent - { - return self.Optional>(); - } - } -} diff --git a/src/Utils/ArrayUtility.cs b/src/Utils/ArrayUtility.cs index e5e72b6..fe8b188 100644 --- a/src/Utils/ArrayUtility.cs +++ b/src/Utils/ArrayUtility.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace DCFApixels.DragonECS +namespace DCFApixels.DragonECS.Utils { internal static class ArrayUtility { diff --git a/src/Utils/IntDispenser.cs b/src/Utils/IntDispenser.cs index c0b0b25..96fb120 100644 --- a/src/Utils/IntDispenser.cs +++ b/src/Utils/IntDispenser.cs @@ -1,7 +1,7 @@ using System.Collections.Concurrent; using System.Threading; -namespace DCFApixels.DragonECS +namespace DCFApixels.DragonECS.Utils { internal sealed class IntDispenser { diff --git a/src/Utils/Extensions.cs b/src/Utils/IntExtensions.cs similarity index 83% rename from src/Utils/Extensions.cs rename to src/Utils/IntExtensions.cs index 2e1fd6e..2c42f57 100644 --- a/src/Utils/Extensions.cs +++ b/src/Utils/IntExtensions.cs @@ -1,6 +1,6 @@ namespace DCFApixels.DragonECS { - public static class Extensions + public static class IntExtensions { public static entlong ToEntityLong(this int self, EcsWorld world) { diff --git a/src/Utils/SparseArray.cs b/src/Utils/SparseArray.cs index 493eac7..8d9dccb 100644 --- a/src/Utils/SparseArray.cs +++ b/src/Utils/SparseArray.cs @@ -6,7 +6,7 @@ using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -namespace DCFApixels.DragonECS +namespace DCFApixels.DragonECS.Utils { public class SparseArray { diff --git a/src/Utils/SparseSet.cs b/src/Utils/SparseSet.cs index 79f0636..9bc7b4d 100644 --- a/src/Utils/SparseSet.cs +++ b/src/Utils/SparseSet.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Text; -namespace DCFApixels.DragonECS +namespace DCFApixels.DragonECS.Utils { public class SparseSet : IEnumerable, ICollection, IReadOnlyCollection { From d230afdeb7f57c08e208665daee8d862ba6d5f90 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 06:22:33 +0800 Subject: [PATCH 7/8] remove useless --- src/Utils/ArrayUtility.cs | 35 +--- src/Utils/SparseArray.cs | 259 ------------------------ src/Utils/SparseSet.cs | 409 -------------------------------------- 3 files changed, 1 insertion(+), 702 deletions(-) delete mode 100644 src/Utils/SparseArray.cs delete mode 100644 src/Utils/SparseSet.cs diff --git a/src/Utils/ArrayUtility.cs b/src/Utils/ArrayUtility.cs index fe8b188..9eab0b6 100644 --- a/src/Utils/ArrayUtility.cs +++ b/src/Utils/ArrayUtility.cs @@ -1,7 +1,4 @@ -using System; -using System.Runtime.InteropServices; - -namespace DCFApixels.DragonECS.Utils +namespace DCFApixels.DragonECS.Utils { internal static class ArrayUtility { @@ -15,34 +12,4 @@ namespace DCFApixels.DragonECS.Utils array[i] = value; } } - - internal static unsafe class UnmanagedArrayUtility - { - public static void* New(int elementCount) where T : struct - { - return Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)) * elementCount).ToPointer(); - } - - public static void* NewAndInit(int elementCount) where T : struct - { - int newSizeInBytes = Marshal.SizeOf(typeof(T)) * elementCount; - byte* newArrayPointer = (byte*)Marshal.AllocHGlobal(newSizeInBytes).ToPointer(); - - for (int i = 0; i < newSizeInBytes; i++) - *(newArrayPointer + i) = 0; - - return newArrayPointer; - } - - public static void Free(void* pointerToUnmanagedMemory) - { - Marshal.FreeHGlobal(new IntPtr(pointerToUnmanagedMemory)); - } - - public static void* Resize(void* oldPointer, int newElementCount) where T : struct - { - return (Marshal.ReAllocHGlobal(new IntPtr(oldPointer), - new IntPtr(Marshal.SizeOf(typeof(T)) * newElementCount))).ToPointer(); - } - } } diff --git a/src/Utils/SparseArray.cs b/src/Utils/SparseArray.cs deleted file mode 100644 index 8d9dccb..0000000 --- a/src/Utils/SparseArray.cs +++ /dev/null @@ -1,259 +0,0 @@ -//SparseArray. Analogous to Dictionary, but faster. -//Benchmark result of indexer.get speed test with 300 elements: -//[Dictinary: 5.786us] [SparseArray: 2.047us]. -using System; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace DCFApixels.DragonECS.Utils -{ - public class SparseArray - { - public const int MIN_CAPACITY_BITS_OFFSET = 4; - public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET; - private const int EMPTY = -1; - - private int[] _buckets = Array.Empty(); - private Entry[] _entries = Array.Empty(); - private int[] _dense; - - private int _count; - - private int _freeList; - private int _freeCount; - - private int _modBitMask; - - #region Properties - public ref TValue this[int key] - { - get => ref _entries[FindEntry(key)].value; - //set => Insert(key, value); - } - - public int Count => _count; - #endregion - - #region Constructors - public SparseArray(int minCapacity = MIN_CAPACITY) - { - minCapacity = NormalizeCapacity(minCapacity); - _buckets = new int[minCapacity]; - for (int i = 0; i < minCapacity; i++) - _buckets[i] = EMPTY; - _entries = new Entry[minCapacity]; - _modBitMask = (minCapacity - 1) & 0x7FFFFFFF; - } - #endregion - - #region Add - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Add(int key, TValue value) - { -#if DEBUG - if (Contains(key)) - throw new ArgumentException("Contains(hashKey) is true"); -#endif - Insert(key, value); - } - #endregion - - #region Find/Insert/Remove - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int FindEntry(int key) - { - for (int i = _buckets[key & _modBitMask]; i >= 0; i = _entries[i].next) - if (_entries[i].hashKey == key) return i; - return -1; - } - private void Insert(int key, TValue value) - { - int targetBucket = key & _modBitMask; - - for (int i = _buckets[targetBucket]; i >= 0; i = _entries[i].next) - { - if (_entries[i].hashKey == key) - { - _entries[i].value = value; - return; - } - } - - int index; - if (_freeCount > 0) - { - index = _freeList; - _freeList = _entries[index].next; - _freeCount--; - } - else - { - if (_count == _entries.Length) - { - Resize(); - targetBucket = key & _modBitMask; - } - index = _count++; - } - - _entries[index].next = _buckets[targetBucket]; - _entries[index].hashKey = key; - _entries[index].value = value; - _buckets[targetBucket] = index; - } - public bool Remove(int key) - { - int bucket = key & _modBitMask; - int last = -1; - for (int i = _buckets[bucket]; i >= 0; last = i, i = _entries[i].next) - { - if (_entries[i].hashKey == key) - { - if (last < 0) - { - _buckets[bucket] = _entries[i].next; - } - else - { - _entries[last].next = _entries[i].next; - } - _entries[i].next = _freeList; - _entries[i].hashKey = -1; - _entries[i].value = default; - _freeList = i; - _freeCount++; - return true; - } - } - return false; - } - #endregion - - #region TryGetValue - public bool TryGetValue(int key, out TValue value) - { - int index = FindEntry(key); - if (index < 0) - { - value = default; - return false; - } - value = _entries[index].value; - return true; - } - #endregion - - #region Contains - public bool Contains(int key) - { - return FindEntry(key) >= 0; - } - #endregion - - #region Clear - public void Clear() - { - if (_count > 0) - { - for (int i = 0; i < _buckets.Length; i++) - { - _buckets[i] = -1; - } - Array.Clear(_entries, 0, _count); - _count = 0; - } - } - #endregion - - #region Resize - private void Resize() - { - int newSize = _buckets.Length << 1; - _modBitMask = (newSize - 1) & 0x7FFFFFFF; - - Contract.Assert(newSize >= _entries.Length); - int[] newBuckets = new int[newSize]; - for (int i = 0; i < newBuckets.Length; i++) - newBuckets[i] = EMPTY; - - Entry[] newEntries = new Entry[newSize]; - Array.Copy(_entries, 0, newEntries, 0, _count); - for (int i = 0; i < _count; i++) - { - if (newEntries[i].hashKey >= 0) - { - int bucket = newEntries[i].hashKey % newSize; - newEntries[i].next = newBuckets[bucket]; - newBuckets[bucket] = i; - } - } - _buckets = newBuckets; - _entries = newEntries; - } - - private int NormalizeCapacity(int capacity) - { - int result = MIN_CAPACITY; - while (result < capacity) result <<= 1; - return result; - } - #endregion - - - //#region Enumerator - // public Enumerator GetEnumerator() => new Enumerator(this); - // public struct Enumerator - // { - // private SparseArray _source; - // private int index; - // private int curretnItmeIndex; - // - // public ref readonly TValue Current - // { - // get - // { - // return ref _source._entries[curretnItmeIndex].value; - // } - // } - // - // public Enumerator(SparseArray source) - // { - // _source = source; - // index = 0; - // curretnItmeIndex = 0; - // } - // - // public bool MoveNext() - // { - // // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. - // // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue - // while ((uint)index < (uint)_source.count) - // { - // if (dictionary.entries[index].hashCode >= 0) - // { - // current = new KeyValuePair(dictionary.entries[index].key, dictionary.entries[index].value); - // index++; - // return true; - // } - // index++; - // } - // - // index = dictionary.count + 1; - // current = new KeyValuePair(); - // return false; - // } - // } - // #endregion - - #region Utils - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct Entry - { - public int next; // Index of next entry, -1 if last - public int hashKey; - public TValue value; - } - #endregion - } -} \ No newline at end of file diff --git a/src/Utils/SparseSet.cs b/src/Utils/SparseSet.cs deleted file mode 100644 index 9bc7b4d..0000000 --- a/src/Utils/SparseSet.cs +++ /dev/null @@ -1,409 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Text; - -namespace DCFApixels.DragonECS.Utils -{ - public class SparseSet : IEnumerable, ICollection, IReadOnlyCollection - { - public const int DEFAULT_DENSE_CAPACITY = 8; - public const int DEFAULT_SPARSE_CAPACITY = 16; - - public const int MIN_CAPACITY = 4; - - public const int MAX_CAPACITY = int.MaxValue; - - private int[] _dense; - private int[] _sparse; - - private int _count; - - #region Properties - public int Count - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _count; - } - public int CapacityDense - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _dense.Length; - } - public int CapacitySparse - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _sparse.Length; - } - - public int this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { -#if DEBUG - ThrowHalper.CheckOutOfRange(this, index); -#endif - return _dense[index]; - } - } - #endregion - - #region Constructors - public SparseSet() : this(DEFAULT_DENSE_CAPACITY, DEFAULT_SPARSE_CAPACITY) { } - public SparseSet(int denseCapacity, int sparseCapacity) - { - denseCapacity = denseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(denseCapacity); - sparseCapacity = sparseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(sparseCapacity); - - _dense = new int[denseCapacity]; - _sparse = new int[sparseCapacity]; - - Reset(); - } - #endregion - - #region Add/AddRange - public void Add(int value, ref T[] normalizedArray) - { - Add(value); - Normalize(ref normalizedArray); - } - - public void Add(int value) - { -#if DEBUG - ThrowHalper.CheckValueIsPositive(value); - ThrowHalper.CheckValueNotContained(this, value); -#endif - if (_count >= _dense.Length) - Array.Resize(ref _dense, _dense.Length << 1); - - if (value >= _sparse.Length) - { - int neadedSpace = _sparse.Length; - while (value >= neadedSpace) - neadedSpace <<= 1; - int i = _sparse.Length; - Array.Resize(ref _sparse, neadedSpace); - //loop unwinding - for (; i < neadedSpace;) - { - _sparse[i++] = -1; - _sparse[i++] = -1; - _sparse[i++] = -1; - _sparse[i++] = -1; - } - } - - _dense[_count] = value; - _sparse[value] = _count++; - } - - public bool TryAdd(int value, ref T[] normalizedArray) - { - if (Contains(value)) return false; - Add(value); - Normalize(ref normalizedArray); - return true; - } - public bool TryAdd(int value) - { - if (Contains(value)) return false; - Add(value); - return true; - } - - public void AddRange(IEnumerable range, ref T[] normalizedArray) - { - AddRange(range); - Normalize(ref normalizedArray); - } - public void AddRange(IEnumerable range) - { - foreach (var item in range) - { - if (Contains(item)) continue; - Add(item); - } - } - #endregion - - #region Contains - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(int value) - { - return value >= 0 && value < CapacitySparse && _sparse[value] >= 0; - } - #endregion - - #region Remove - public void Remove(int value) - { -#if DEBUG - ThrowHalper.CheckValueContained(this, value); -#endif - _dense[_sparse[value]] = _dense[--_count]; - _sparse[_dense[_count]] = _sparse[value]; - _sparse[value] = -1; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryRemove(int value) - { - if (!Contains(value)) return false; - Remove(value); - return true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RemoveAt(int index) - { -#if DEBUG - ThrowHalper.CheckOutOfRange(this, index); -#endif - Remove(_dense[index]); - } - #endregion - - #region Other - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Normalize(ref T[] array) - { - if (array.Length < CapacityDense) Array.Resize(ref array, CapacityDense); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int IndexOf(int value) - { - if (value < 0 || !Contains(value)) return -1; - return _sparse[value]; - } - - public void Sort() - { - int increment = 0; - for (int i = 0; i < CapacitySparse; i++) - { - if (_sparse[i] < _count) - { - _sparse[i] = increment; - _dense[increment++] = i; - } - } - } - - public void HardSort() - { - int inc = 0; - int inc2 = _count; - for (int i = 0; i < CapacitySparse; i++) - { - if (_sparse[i] >= 0) - { - _sparse[i] = inc; - _dense[inc++] = i; - } - else - { - _dense[inc2++] = i; - } - } - } - - public void CopyTo(SparseSet other) - { - other._count = _count; - if (CapacitySparse != other.CapacitySparse) - Array.Resize(ref other._sparse, CapacitySparse); - if (CapacityDense != other.CapacityDense) - Array.Resize(ref other._dense, CapacityDense); - _sparse.CopyTo(other._sparse, 0); - _dense.CopyTo(other._dense, 0); - } - - public void CopyTo(int[] array, int arrayIndex) - { -#if DEBUG - if (arrayIndex < 0) throw new ArgumentException("arrayIndex is less than 0"); - if (arrayIndex + _count >= array.Length) throw new ArgumentException("The number of elements in the source List is greater than the available space from arrayIndex to the end of the destination array."); -#endif - for (int i = 0; i < _count; i++, arrayIndex++) - { - array[arrayIndex] = this[i]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int NormalizeCapacity(int value) - { - return value + (MIN_CAPACITY - (value % MIN_CAPACITY)); - } - #endregion - - #region Clear/Reset - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Clear() => _count = 0; - public void Reset() - { - Clear(); - //loop unwinding - for (int i = 0; i < _sparse.Length;) - { - _sparse[i++] = -1; - _sparse[i++] = -1; - _sparse[i++] = -1; - _sparse[i++] = -1; - } - } - - public void Reset(int newDenseCapacity, int newSparseCapacity) - { - newDenseCapacity = newDenseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(newDenseCapacity); - newSparseCapacity = newSparseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(newSparseCapacity); - - if (CapacitySparse != newSparseCapacity) - Array.Resize(ref _sparse, newSparseCapacity); - if (CapacityDense != newDenseCapacity) - Array.Resize(ref _dense, newDenseCapacity); - Reset(); - } - #endregion - - #region Enumerator - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RefEnumerator GetEnumerator() => new RefEnumerator(_dense, _count); - - public ref struct RefEnumerator - { - private readonly int[] _dense; - private readonly int _count; - private int _index; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RefEnumerator(int[] values, int count) - { - _dense = values; - _count = count; - _index = -1; - } - - public int Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _dense[_index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() { } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() => ++_index < _count; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reset() => _index = -1; - } - - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(_dense, _count); - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(_dense, _count); - public struct Enumerator : IEnumerator //to implement the IEnumerable interface and use the ref structure, 2 Enumerators were created. - { - private readonly int[] _dense; - private readonly int _count; - private int _index; - public Enumerator(int[] values, int count) - { - _dense = values; - _count = count; - _index = -1; - } - public int Current => _dense[_index]; - object IEnumerator.Current => _dense[_index]; - public void Dispose() { } - public bool MoveNext() => ++_index < _count; - public void Reset() => _index = -1; - } - #endregion - - #region ICollection - bool ICollection.IsReadOnly => false; - - bool ICollection.Remove(int value) => TryRemove(value); - #endregion - - #region Debug - public string Log() - { - StringBuilder logbuild = new StringBuilder(); - for (int i = 0; i < CapacityDense; i++) - { - logbuild.Append(_dense[i] + ", "); - } - logbuild.Append("\n\r"); - for (int i = 0; i < CapacitySparse; i++) - { - logbuild.Append(_sparse[i] + ", "); - } - logbuild.Append("\n\r --------------------------"); - logbuild.Append("\n\r"); - for (int i = 0; i < CapacityDense; i++) - { - logbuild.Append((i < _count ? _dense[i].ToString() : "_") + ", "); - } - logbuild.Append("\n\r"); - for (int i = 0; i < CapacitySparse; i++) - { - logbuild.Append((_sparse[i] >= 0 ? _sparse[i].ToString() : "_") + ", "); - } - logbuild.Append("\n\r Count: " + _count); - logbuild.Append("\n\r Capacity: " + CapacitySparse); - logbuild.Append("\n\r IsValide: " + IsValide_Debug()); - - logbuild.Append("\n\r"); - return logbuild.ToString(); - } - - public bool IsValide_Debug() - { - bool isPass = true; - for (int index = 0; index < _count; index++) - { - int value = _dense[index]; - isPass = isPass && _sparse[value] == index; - } - return isPass; - } - -#if DEBUG - private static class ThrowHalper - { - public static void CheckCapacity(int capacity) - { - if (capacity < 0) - throw new ArgumentException("Capacity cannot be a negative number"); - } - public static void CheckValueIsPositive(int value) - { - if (value < 0) - throw new ArgumentException("The SparseSet can only contain positive numbers"); - } - public static void CheckValueContained(SparseSet source, int value) - { - if (!source.Contains(value)) - throw new ArgumentException($"Value {value} is not contained"); - } - public static void CheckValueNotContained(SparseSet source, int value) - { - if (source.Contains(value)) - throw new ArgumentException($"Value {value} is already contained"); - } - public static void CheckOutOfRange(SparseSet source, int index) - { - if (index < 0 || index >= source.Count) - throw new ArgumentOutOfRangeException($"Index {index} was out of range. Must be non-negative and less than the size of the collection."); - } - } -#endif - #endregion - } -} \ No newline at end of file From 55f68434517f0804f2161d7e46bd442c481b64aa Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 May 2023 06:37:15 +0800 Subject: [PATCH 8/8] moving part of the API into a separate module --- src/Builtin/Components.cs | 72 ----------- src/Builtin/Subjects.cs | 11 -- src/Pools/EcsAttachPool.cs | 224 ---------------------------------- src/Pools/EcsPool.cs | 2 +- src/Pools/EcsTagPool.cs | 2 +- src/Utils/EntityLinkedList.cs | 6 +- 6 files changed, 5 insertions(+), 312 deletions(-) delete mode 100644 src/Builtin/Components.cs delete mode 100644 src/Builtin/Subjects.cs delete mode 100644 src/Pools/EcsAttachPool.cs diff --git a/src/Builtin/Components.cs b/src/Builtin/Components.cs deleted file mode 100644 index 6cea199..0000000 --- a/src/Builtin/Components.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace DCFApixels.DragonECS -{ - [DebugColor(DebugColor.White)] - public struct Parent : IEcsAttachComponent - { - public entlong entity; - - [EditorBrowsable(EditorBrowsableState.Never)] - public entlong Target - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => entity; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set => entity = value; - } - } - - public static class ParentUtility - { - // public static int GetRootOrSelf(this HierarchySubject s, int entityID) => s.parents.GetRootOrSelf(entityID); - public static int GetRootOrSelf(this EcsAttachPool parents, int entityID) - { - while (parents.Has(entityID) && parents.Read(entityID).entity.TryGetID(out int child)) - entityID = child; - return entityID; - } - // public static bool IsRoot(this HierarchySubject s, int entityID) => s.parents.IsRoot(entityID); - public static bool IsRoot(this EcsAttachPool parents, int entityID) - { - return !(parents.Has(entityID) && parents.Read(entityID).entity.IsAlive); - } - - // public static bool TryGetRoot(this HierarchySubject s, int entityID, out int rootEntityID) => TryGetRoot(s.parents, entityID, out rootEntityID); - public static bool TryGetRoot(this EcsAttachPool parents, EcsSubject conditionSubject, int entityID, out int rootEntityID) - { - rootEntityID = entityID; - while (parents.Has(rootEntityID) && parents.Read(rootEntityID).entity.TryGetID(out int child) && !conditionSubject.IsMatches(child)) - rootEntityID = child; - return rootEntityID != entityID; - } - public static bool TryGetRoot(this EcsAttachPool parents, int entityID, out int rootEntityID) - { - rootEntityID = entityID; - while (parents.Has(rootEntityID) && parents.Read(rootEntityID).entity.TryGetID(out int child)) - rootEntityID = child; - return rootEntityID != entityID; - } - - public static bool TryFindParentWithSubject(this EcsAttachPool parents, EcsSubject conditionSubject, int entityID, out int resultEntityID) - { - resultEntityID = entityID; - while (parents.Has(resultEntityID) && parents.Read(resultEntityID).entity.TryGetID(out int child) && !conditionSubject.IsMatches(resultEntityID)) - resultEntityID = child; - return conditionSubject.IsMatches(resultEntityID); - } - public static bool TryFindParentWith(this EcsAttachPool parents, int entityID, out int resultEntityID) where TComponent : struct - { - var pool = parents.World.AllPools[parents.World.GetComponentID()]; - resultEntityID = entityID; - while (!pool.Has(resultEntityID) && - parents.Has(resultEntityID) && - parents.Read(resultEntityID).entity.TryGetID(out int child)) - { - resultEntityID = child; - } - return pool.Has(resultEntityID); - } - } -} diff --git a/src/Builtin/Subjects.cs b/src/Builtin/Subjects.cs deleted file mode 100644 index 8c3b369..0000000 --- a/src/Builtin/Subjects.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace DCFApixels.DragonECS -{ - public sealed class HierarchySubject : EcsSubject - { - public readonly EcsAttachPool parents; - public HierarchySubject(Builder b) - { - parents = b.Include(); - } - } -} diff --git a/src/Pools/EcsAttachPool.cs b/src/Pools/EcsAttachPool.cs deleted file mode 100644 index 3348174..0000000 --- a/src/Pools/EcsAttachPool.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace DCFApixels.DragonECS -{ - using static EcsPoolThrowHalper; - // - /// Pool for IEcsAttachComponent components - public sealed class EcsAttachPool : IEcsPoolImplementation, IEnumerable //IntelliSense hack - where T : struct, IEcsAttachComponent - { - private EcsWorld _source; - private int _id; - - private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID - private T[] _items; //sparse - private int _count; - - private List _listeners; - - private EcsGroup _entities; - public EcsReadonlyGroup Entities - { - get - { - _entities.RemoveUnusedEntityIDs(); - return _entities.Readonly; - } - } - -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - private short _sanitizeTargetWorld = -1; -#endif - - #region Properites - public int Count => _count; - public int Capacity => _items.Length; - public int ComponentID => _id; - public Type ComponentType => typeof(T); - public EcsWorld World => _source; - #endregion - - #region Init - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) - { - _source = world; - _id = componentID; - - _listeners = new List(); - - _entities = EcsGroup.New(world); - - _entityFlags = new bool[world.Capacity]; - _items = new T[world.Capacity]; - _count = 0; - } - #endregion - - #region Methods - public void Add(int entityID, entlong target) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (_sanitizeTargetWorld > 0 && target.world != _sanitizeTargetWorld) ThrowWorldDifferent(entityID); - _sanitizeTargetWorld = target.world; - if (Has(entityID)) ThrowAlreadyHasComponent(entityID); -#endif - ref bool entityFlag = ref _entityFlags[entityID]; - if (entityFlag == false) - { - entityFlag = true; - _count++; - _entities.Add(entityID); - foreach (var item in _listeners) item.OnAdd(entityID); - } - foreach (var item in _listeners) item.OnWrite(entityID); - _items[entityID].Target = target; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Set(int entityID, entlong target) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowNotHaveComponent(entityID); - if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) ThrowWorldDifferent(entityID); - _sanitizeTargetWorld = target.world; -#endif - _listeners.InvokeOnWrite(entityID); - _items[entityID].Target = target; - } - public void AddOrSet(int entityID, entlong target) - { - if (Has(entityID)) - Set(entityID, target); - else - Add(entityID, target); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly T Read(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowNotHaveComponent(entityID); -#endif - return ref _items[entityID]; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(int entityID) - { - return _entityFlags[entityID]; - } - public void Del(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowNotHaveComponent(entityID); -#endif - _entities.Remove(entityID); - _entityFlags[entityID] = false; - _count--; - _listeners.InvokeOnDel(entityID); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void TryDel(int entityID) - { - if (Has(entityID)) Del(entityID); - } - public void Copy(int fromEntityID, int toEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); -#endif - if (Has(toEntityID)) - Set(toEntityID, Read(fromEntityID).Target); - else - Add(toEntityID, Read(fromEntityID).Target); - } - public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(fromEntityID)) ThrowNotHaveComponent(fromEntityID); -#endif - if (Has(toEntityID)) - toWorld.GetPool().Set(toEntityID, Read(fromEntityID).Target); - else - toWorld.GetPool().Add(toEntityID, Read(fromEntityID).Target); - } - #endregion - - #region WorldCallbacks - void IEcsPoolImplementation.OnWorldResize(int newSize) - { - Array.Resize(ref _entityFlags, newSize); - Array.Resize(ref _items, newSize); - } - void IEcsPoolImplementation.OnWorldDestroy() { } - void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) - { - foreach (var item in buffer) - TryDel(item); - } - #endregion - - #region Other - ref T IEcsPool.Add(int entityID) - { - if (!Has(entityID)) - Add(entityID, entlong.NULL); - return ref _items[entityID]; - } - ref T IEcsPool.Write(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowNotHaveComponent(entityID); -#endif - return ref _items[entityID]; - } - void IEcsPool.AddRaw(int entityID, object dataRaw) => ((IEcsPool)this).Add(entityID) = (T)dataRaw; - object IEcsPool.GetRaw(int entityID) => Read(entityID); - void IEcsPool.SetRaw(int entityID, object dataRaw) => ((IEcsPool)this).Write(entityID) = (T)dataRaw; - #endregion - - #region Listeners - public void AddListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Add(listener); - } - public void RemoveListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Remove(listener); - } - #endregion - - #region IEnumerator - IntelliSense hack - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - #endregion - } - - public interface IEcsAttachComponent - { - public entlong Target { get; set; } - } - public static class EcsAttachComponentPoolExt - { - public static EcsAttachPool GetPool(this EcsWorld self) where TAttachComponent : struct, IEcsAttachComponent - { - return self.GetPool>(); - } - - public static EcsAttachPool Include(this EcsSubjectBuilderBase self) where TAttachComponent : struct, IEcsAttachComponent - { - return self.Include>(); - } - public static EcsAttachPool Exclude(this EcsSubjectBuilderBase self) where TAttachComponent : struct, IEcsAttachComponent - { - return self.Exclude>(); - } - public static EcsAttachPool Optional(this EcsSubjectBuilderBase self) where TAttachComponent : struct, IEcsAttachComponent - { - return self.Optional>(); - } - } -} diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 23bbbd8..366af85 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -7,7 +7,7 @@ namespace DCFApixels.DragonECS { using static EcsPoolThrowHalper; /// Pool for IEcsComponent components - public sealed class EcsPool : IEcsPoolImplementation, IEnumerable //IntelliSense hack + public sealed class EcsPool : IEcsPoolImplementation, IEnumerable //IEnumerable - IntelliSense hack where T : struct, IEcsComponent { private EcsWorld _source; diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index bf36ebb..0f3cf8b 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -6,7 +6,7 @@ using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { using static EcsPoolThrowHalper; - public sealed class EcsTagPool : IEcsPoolImplementation, IEnumerable //IntelliSense hack + public sealed class EcsTagPool : IEcsPoolImplementation, IEnumerable //IEnumerable - IntelliSense hack where T : struct, IEcsTagComponent { private EcsWorld _source; diff --git a/src/Utils/EntityLinkedList.cs b/src/Utils/EntityLinkedList.cs index 7ff22ec..bafe85f 100644 --- a/src/Utils/EntityLinkedList.cs +++ b/src/Utils/EntityLinkedList.cs @@ -5,7 +5,7 @@ namespace DCFApixels.DragonECS { public class EntityLinkedList { - public const int Enter = 0; + private const int ENTER = 0; private Node[] _nodes; private int _count; @@ -35,7 +35,7 @@ namespace DCFApixels.DragonECS //ArrayUtility.Fill(_nodes, Node.Empty); for (int i = 0; i < _nodes.Length; i++) _nodes[i].next = 0; - _lastNodeIndex = Enter; + _lastNodeIndex = ENTER; _count = 0; } @@ -82,7 +82,7 @@ namespace DCFApixels.DragonECS { _nodes = nodes; _index = -1; - _next = Enter; + _next = ENTER; } public int Current => _nodes[_index].entityID; public bool MoveNext()