From 22ff801f15ad9f84fd9f8ff42518a04bdf4c4eeb Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Sat, 22 Apr 2023 23:40:09 +0800 Subject: [PATCH] Update --- src/Builtin/Components.cs | 17 +++ src/EcsJoinQuery.cs | 146 ++++++++++++++++++------ src/EcsQuery.cs | 63 +++++----- src/EcsWorld.cs | 4 +- src/Entities/EcsEntity.cs | 9 ++ src/Exceptions/EcsRelationException.cs | 15 +++ src/Exceptions/EcsRelationsException.cs | 15 --- src/Interfaces/IEcsTable.cs | 2 +- src/Interfaces/INullDummy.cs | 7 -- src/Pools/EcsAttachPool.cs | 17 ++- src/Pools/EcsNotNullPool.cs | 3 +- src/Pools/EcsPool.cs | 19 ++- src/Pools/EcsRelationPool.cs | 29 +++-- src/Pools/EcsSinglePool.cs | 3 +- src/Pools/EcsTagPool.cs | 3 +- 15 files changed, 244 insertions(+), 108 deletions(-) create mode 100644 src/Builtin/Components.cs create mode 100644 src/Exceptions/EcsRelationException.cs delete mode 100644 src/Exceptions/EcsRelationsException.cs delete mode 100644 src/Interfaces/INullDummy.cs diff --git a/src/Builtin/Components.cs b/src/Builtin/Components.cs new file mode 100644 index 0000000..3a47bfb --- /dev/null +++ b/src/Builtin/Components.cs @@ -0,0 +1,17 @@ +using System.Runtime.CompilerServices; + +namespace DCFApixels.DragonECS +{ + public struct Parent : IEcsAttachComponent + { + public EcsEntity entity; + + public EcsEntity Target + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => entity; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => entity = value; + } + } +} diff --git a/src/EcsJoinQuery.cs b/src/EcsJoinQuery.cs index c404d17..d639dc9 100644 --- a/src/EcsJoinQuery.cs +++ b/src/EcsJoinQuery.cs @@ -1,60 +1,83 @@ -using System; +using Mono.CompilerServices.SymbolWriter; +using System; +using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using Unity.Profiling; +using UnityEngine; +using UnityEngine.Jobs; namespace DCFApixels.DragonECS { public abstract class EcsJoinQueryBase : EcsQueryBase { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void ExecuteWhere() - { - var pools = World.GetAllPools(); - EcsReadonlyGroup all = World.Entities; - groupFilter.Clear(); - foreach (var e in all) - { - int entityID = e.id; - for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++) - { - if (!pools[mask.Inc[i]].Has(entityID)) - goto next; - } - for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++) - { - if (pools[mask.Exc[i]].Has(entityID)) - goto next; - } - groupFilter.AggressiveAdd(entityID); - next: continue; - } - groupFilter.Sort(); - } + public abstract void ExecuteJoin(); } public abstract class EcsJoinAttachQuery : EcsJoinQueryBase where TAttachComponent : struct, IEcsAttachComponent { private EcsWorld _targetWorld; private EcsAttachPool _targetPool; + public EcsAttachPool Attach => _targetPool; + + + private int[] _mapping = Array.Empty(); + //private LinkedList + + + private bool _isInitTargetWorlds = false; - private ProfilerMarker _execute = new ProfilerMarker("EcsJoinAttachQuery.Execute"); protected sealed override void OnBuild(Builder b) { _targetPool = b.Include(); } - public sealed override void Execute() + public sealed override void ExecuteWhere() { - using (_execute.Auto()) + ExecuteWhere(_targetPool.Entites, groupFilter); + } + + public sealed override void ExecuteJoin() + { + ExecuteWhere(_targetPool.Entites, groupFilter); + if (_isInitTargetWorlds == false) InitTargetWorlds(); + + if (source.Capacity != _mapping.Length) + _mapping = new int[World.Capacity]; + else + ArrayUtility.Fill(_mapping, 0); + + foreach (var e in groupFilter) { - ExecuteWhere(); + int entityID = e.id; + + } + } + + private void InitTargetWorlds() + { + foreach (var e in groupFilter) + { + ref readonly var rel = ref _targetPool.Read(e); + if (rel.Target.IsNotNull) + _targetWorld = EcsWorld.Worlds[rel.Target.world]; + + if (_targetWorld != null) + { + _isInitTargetWorlds = true; + break; + } } } public EcsGroup.Enumerator GetEnumerator() { return groupFilter.GetEnumerator(); } + + public NodesEnumrable GetNodes(int entityID) + { + throw new NotImplementedException(); + } } public abstract class EcsJoinRelationQuery : EcsJoinQueryBase where TRelationComponent : struct, IEcsRelationComponent @@ -62,22 +85,77 @@ namespace DCFApixels.DragonECS private EcsWorld _firstWorld; private EcsWorld _secondWorld; private EcsRelationPool _targetPool; + public EcsRelationPool Relation => _targetPool; + + private bool _isInitTargetWorlds = false; + - private ProfilerMarker _execute = new ProfilerMarker("EcsJoinRelationQuery.Execute"); protected sealed override void OnBuild(Builder b) { - _targetPool = source.GetPool(); + _targetPool = b.Include(); } - public sealed override void Execute() + public sealed override void ExecuteWhere() { - using (_execute.Auto()) + ExecuteWhere(_targetPool.Entites, groupFilter); + } + public sealed override void ExecuteJoin() + { + if (_isInitTargetWorlds == false) InitTargetWorlds(); + } + + private void InitTargetWorlds() + { + foreach (var e in groupFilter) { - ExecuteWhere(); + ref readonly var rel = ref _targetPool.Read(e); + if (rel.First.IsNotNull) + _firstWorld = EcsWorld.Worlds[rel.First.world]; + if (rel.Second.IsNotNull) + _secondWorld = EcsWorld.Worlds[rel.Second.world]; + if (_firstWorld != null && _secondWorld != null) + { + _isInitTargetWorlds = true; + break; + } } } public EcsGroup.Enumerator GetEnumerator() { return groupFilter.GetEnumerator(); } + + public NodesEnumrable GetNodes(int entityID) + { + throw new NotImplementedException(); + } + } + + public readonly ref struct NodesEnumrable + { + private readonly int[] _nodes; + private readonly int _start; + private readonly int _count; + public NodesEnumrable(int[] nodes, int start, int count) + { + _nodes = nodes; + _start = start; + _count = count; + } + public NodesEnumerator GetEnumerator() => new NodesEnumerator(_nodes, _start, _count); + } + public ref struct NodesEnumerator + { + private readonly int[] _nodes; + private readonly int _end; + private int _index; + public NodesEnumerator(int[] nodes, int start, int count) + { + _nodes = nodes; + int end = start + count; + _end = end < _nodes.Length ? end : _nodes.Length; + _index = start; + } + public ent Current => new ent(_nodes[_index]); + public bool MoveNext() => ++_index <= _end; } } diff --git a/src/EcsQuery.cs b/src/EcsQuery.cs index 9198ea8..994a102 100644 --- a/src/EcsQuery.cs +++ b/src/EcsQuery.cs @@ -15,13 +15,15 @@ namespace DCFApixels.DragonECS #region Builder protected virtual void Init(Builder b) { } protected abstract void OnBuild(Builder b); - public abstract void Execute(); + public abstract void ExecuteWhere(); public sealed class Builder : EcsQueryBuilderBase { private EcsWorld _world; private List _inc; private List _exc; + public EcsWorld World => _world; + private Builder(EcsWorld world) { _world = world; @@ -76,36 +78,45 @@ namespace DCFApixels.DragonECS } } #endregion + + protected void ExecuteWhere(EcsReadonlyGroup group, EcsGroup result) + { + var pools = World.GetAllPools(); + result.Clear(); + foreach (var e in group) + { + int entityID = e.id; + for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++) + { + if (!pools[mask.Inc[i]].Has(entityID)) + goto next; + } + for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++) + { + if (pools[mask.Exc[i]].Has(entityID)) + goto next; + } + result.AggressiveAdd(entityID); + next: continue; + } + result.Sort(); + } + protected void ExecuteWhereAndSort(EcsReadonlyGroup group, EcsGroup result) + { + ExecuteWhere(group, result); + result.Sort(); + } } public abstract class EcsQuery : EcsQueryBase { - private ProfilerMarker _execute = new ProfilerMarker("EcsQuery.Execute"); + private ProfilerMarker _execute = new ProfilerMarker("EcsQuery.ExecuteWhere"); protected sealed override void OnBuild(Builder b) { } - public sealed override void Execute() + public sealed override void ExecuteWhere() { using (_execute.Auto()) { - var pools = World.GetAllPools(); - EcsReadonlyGroup all = World.Entities; - groupFilter.Clear(); - foreach (var e in all) - { - int entityID = e.id; - for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++) - { - if (!pools[mask.Inc[i]].Has(entityID)) - goto next; - } - for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++) - { - if (pools[mask.Exc[i]].Has(entityID)) - goto next; - } - groupFilter.AggressiveAdd(entityID); - next: continue; - } - groupFilter.Sort(); + ExecuteWhereAndSort(World.Entities, groupFilter); } } public EcsGroup.Enumerator GetEnumerator() @@ -125,8 +136,8 @@ namespace DCFApixels.DragonECS } public abstract class EcsQueryBuilderBase { - public abstract TPool Include() where TComponent : struct where TPool : EcsPoolBase, new(); - public abstract TPool Exclude() where TComponent : struct where TPool : EcsPoolBase, new(); - public abstract TPool Optional() where TComponent : struct where TPool : EcsPoolBase, new(); + public abstract TPool Include() where TComponent : struct where TPool : EcsPoolBase, new(); + public abstract TPool Exclude() where TComponent : struct where TPool : EcsPoolBase, new(); + public abstract TPool Optional() where TComponent : struct where TPool : EcsPoolBase, new(); } } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index d5f49ae..3b4e8f4 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -121,7 +121,7 @@ namespace DCFApixels.DragonECS #endregion #region GetPool - public TPool GetPool() where TComponent : struct where TPool : EcsPoolBase, new() + public TPool GetPool() where TComponent : struct where TPool : EcsPoolBase, new() { int uniqueID = WorldMetaStorage.GetComponentId(_worldArchetypeID); @@ -149,7 +149,7 @@ namespace DCFApixels.DragonECS public TQuery Where(out TQuery query) where TQuery : EcsQuery { query = Select(); - query.Execute(); + query.ExecuteWhere(); return query; } public TQuery Select() where TQuery : EcsQueryBase diff --git a/src/Entities/EcsEntity.cs b/src/Entities/EcsEntity.cs index 91cfb51..17ea470 100644 --- a/src/Entities/EcsEntity.cs +++ b/src/Entities/EcsEntity.cs @@ -83,6 +83,15 @@ namespace DCFApixels.DragonECS return this == NULL; } } + public bool IsNotNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + //using (_IsNullMarker.Auto()) + return this != NULL; + } + } } public static partial class entExtensions diff --git a/src/Exceptions/EcsRelationException.cs b/src/Exceptions/EcsRelationException.cs new file mode 100644 index 0000000..0e1dff1 --- /dev/null +++ b/src/Exceptions/EcsRelationException.cs @@ -0,0 +1,15 @@ +using System; + +namespace DCFApixels.DragonECS +{ + [Serializable] + public class EcsRelationException : Exception + { + public EcsRelationException() { } + public EcsRelationException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { } + public EcsRelationException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { } + protected EcsRelationException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + } +} diff --git a/src/Exceptions/EcsRelationsException.cs b/src/Exceptions/EcsRelationsException.cs deleted file mode 100644 index 685af1b..0000000 --- a/src/Exceptions/EcsRelationsException.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace DCFApixels.DragonECS -{ - [Serializable] - public class EcsRelationsException : Exception - { - public EcsRelationsException() { } - public EcsRelationsException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { } - public EcsRelationsException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { } - protected EcsRelationsException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) : base(info, context) { } - } -} diff --git a/src/Interfaces/IEcsTable.cs b/src/Interfaces/IEcsTable.cs index e1ef7dd..3b5f1ef 100644 --- a/src/Interfaces/IEcsTable.cs +++ b/src/Interfaces/IEcsTable.cs @@ -15,7 +15,7 @@ namespace DCFApixels.DragonECS #region Methods public int GetComponentID(); - public TPool GetPool() where TComponent : struct where TPool : EcsPoolBase, new(); + public TPool GetPool() where TComponent : struct where TPool : EcsPoolBase, new(); public ReadOnlySpan GetAllPools(); public TQuery Select() where TQuery : EcsQueryBase; public TQuery Where(out TQuery query) where TQuery : EcsQuery; diff --git a/src/Interfaces/INullDummy.cs b/src/Interfaces/INullDummy.cs deleted file mode 100644 index 2ff6c3b..0000000 --- a/src/Interfaces/INullDummy.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace DCFApixels.DragonECS -{ - public interface INullDummy - { - public bool IsDummy { get; } - } -} diff --git a/src/Pools/EcsAttachPool.cs b/src/Pools/EcsAttachPool.cs index 77c7203..0a36df1 100644 --- a/src/Pools/EcsAttachPool.cs +++ b/src/Pools/EcsAttachPool.cs @@ -4,7 +4,7 @@ using Unity.Profiling; namespace DCFApixels.DragonECS { - public sealed class EcsAttachPool : EcsPoolBase + public sealed class EcsAttachPool : EcsPoolBase where T : struct, IEcsAttachComponent { private EcsWorld _source; @@ -12,18 +12,19 @@ namespace DCFApixels.DragonECS private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID private T[] _items; //sparse private int _count; - private PoolRunners _poolRunners; + private EcsGroup _entities; + public EcsReadonlyGroup Entites => _entities.Readonly; + #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - private int _sanitizeTargetWorld = -1; + private short _sanitizeTargetWorld = -1; #endif #region Properites public int Count => _count; public int Capacity => _items.Length; public sealed override EcsWorld World => _source; - public sealed override Type ComponentType => typeof(T); #endregion #region Init @@ -49,8 +50,9 @@ namespace DCFApixels.DragonECS #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) { - throw new EcsRelationsException(); + throw new EcsRelationException(); } + _sanitizeTargetWorld = target.world; #endif // using (_addMark.Auto()) // { @@ -59,6 +61,7 @@ namespace DCFApixels.DragonECS { entityFlag = true; _count++; + _entities.Add(entityID); _poolRunners.add.OnComponentAdd(entityID); } _poolRunners.write.OnComponentWrite(entityID); @@ -71,8 +74,9 @@ namespace DCFApixels.DragonECS #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) { - throw new EcsRelationsException(); + throw new EcsRelationException(); } + _sanitizeTargetWorld = target.world; #endif // using (_writeMark.Auto()) _poolRunners.write.OnComponentWrite(entityID); @@ -94,6 +98,7 @@ namespace DCFApixels.DragonECS { // using (_delMark.Auto()) // { + _entities.Remove(entityID); _entityFlags[entityID] = false; _count--; _poolRunners.del.OnComponentDel(entityID); diff --git a/src/Pools/EcsNotNullPool.cs b/src/Pools/EcsNotNullPool.cs index b0e7cd0..285c58e 100644 --- a/src/Pools/EcsNotNullPool.cs +++ b/src/Pools/EcsNotNullPool.cs @@ -4,7 +4,7 @@ using Unity.Profiling; namespace DCFApixels.DragonECS { - public sealed class EcsNotNullPool : EcsPoolBase + public sealed class EcsNotNullPool : EcsPoolBase where T : struct, INotNullComponent { private EcsWorld _source; @@ -19,7 +19,6 @@ namespace DCFApixels.DragonECS public int Count => _count; public int Capacity => _items.Length; public sealed override EcsWorld World => _source; - public sealed override Type ComponentType => typeof(T); #endregion #region Init diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index e1b2b83..fe7c7b4 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -1,4 +1,7 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.CompilerServices; using Unity.Profiling; @@ -25,6 +28,15 @@ namespace DCFApixels.DragonECS internal void InvokeOnDestroy() => OnDestroy(); #endregion } + public abstract class EcsPoolBase : EcsPoolBase, IEnumerable + { + public sealed override Type ComponentType => typeof(T); + //Ðåëàçèàöèÿ èíòåðôåéñà IEnumerator íå ðàáîòàåò, íóæíî òîëüêî ÷òîáû IntelliSense ïðåäëàãàëà íàçâàíèÿ íà îñíîâå T. Íå íàøåë äðóãîãî ñïîñîáà + #region IEnumerable + IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); + IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); + #endregion + } public struct NullComponent { } public sealed class EcsNullPool : EcsPoolBase @@ -48,10 +60,11 @@ namespace DCFApixels.DragonECS protected override void OnDestroy() { } #endregion } - - public sealed class EcsPool : EcsPoolBase + public sealed class EcsPool : EcsPoolBase where T : struct, IEcsComponent { + public static string name = typeof(T).Name; + private EcsWorld _source; private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID @@ -67,7 +80,6 @@ namespace DCFApixels.DragonECS public int Count => _itemsCount; public int Capacity => _items.Length; public sealed override EcsWorld World => _source; - public sealed override Type ComponentType => typeof(T); #endregion #region Init @@ -160,6 +172,7 @@ namespace DCFApixels.DragonECS Array.Resize(ref _mapping, newSize); } protected override void OnDestroy() { } + #endregion } diff --git a/src/Pools/EcsRelationPool.cs b/src/Pools/EcsRelationPool.cs index d7d77c3..9d6e265 100644 --- a/src/Pools/EcsRelationPool.cs +++ b/src/Pools/EcsRelationPool.cs @@ -1,10 +1,11 @@ using System; +using System.Diagnostics; using System.Runtime.CompilerServices; using Unity.Profiling; namespace DCFApixels.DragonECS { - public sealed class EcsRelationPool : EcsPoolBase + public sealed class EcsRelationPool : EcsPoolBase where T : struct, IEcsRelationComponent { private EcsWorld _source; @@ -12,19 +13,20 @@ namespace DCFApixels.DragonECS private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID private T[] _items; //sparse private int _count; - private PoolRunners _poolRunners; + private EcsGroup _entities; + public EcsReadonlyGroup Entites => _entities.Readonly; + #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - private int _sanitizeFirstWorld = -1; - private int _sanitizeSecondWorld = -1; + private short _sanitizeFirstWorld = -1; + private short _sanitizeSecondWorld = -1; #endif #region Properites public int Count => _count; public int Capacity => _items.Length; public sealed override EcsWorld World => _source; - public sealed override Type ComponentType => typeof(T); #endregion #region Init @@ -51,7 +53,7 @@ namespace DCFApixels.DragonECS if((_sanitizeFirstWorld >= 0 && first.world != _sanitizeFirstWorld) && (_sanitizeSecondWorld >= 0 && second.world != _sanitizeSecondWorld)) { - throw new EcsRelationsException(); + throw new EcsRelationException(); } #endif // using (_addMark.Auto()) @@ -61,6 +63,7 @@ namespace DCFApixels.DragonECS { entityFlag = true; _count++; + _entities.Add(entityID); _poolRunners.add.OnComponentAdd(entityID); } _poolRunners.write.OnComponentWrite(entityID); @@ -74,8 +77,10 @@ namespace DCFApixels.DragonECS if ((_sanitizeFirstWorld >= 0 && first.world != _sanitizeFirstWorld) && (_sanitizeSecondWorld >= 0 && second.world != _sanitizeSecondWorld)) { - throw new EcsRelationsException(); + throw new EcsRelationException(); } + _sanitizeFirstWorld = first.world; + _sanitizeSecondWorld = second.world; #endif // using (_writeMark.Auto()) //{ @@ -99,6 +104,7 @@ namespace DCFApixels.DragonECS { // using (_delMark.Auto()) // { + _entities.Remove(entityID); _entityFlags[entityID] = false; _count--; _poolRunners.del.OnComponentDel(entityID); @@ -120,7 +126,14 @@ namespace DCFApixels.DragonECS { public EcsEntity First { get; set; } public EcsEntity Second { get; set; } - public void Set(EcsEntity first, EcsEntity second); + } + public static class IEcsRelationComponentExt + { + public static void Set(this ref T self, EcsEntity first, EcsEntity second) where T : struct, IEcsRelationComponent + { + self.First = first; + self.Second = second; + } } public static class EcsRelationPoolExt { diff --git a/src/Pools/EcsSinglePool.cs b/src/Pools/EcsSinglePool.cs index d2bc247..c70a7b1 100644 --- a/src/Pools/EcsSinglePool.cs +++ b/src/Pools/EcsSinglePool.cs @@ -4,7 +4,7 @@ using Unity.Profiling; namespace DCFApixels.DragonECS { - public sealed class EcsSinglePool : EcsPoolBase + public sealed class EcsSinglePool : EcsPoolBase where T : struct, IEcsSingleComponent { private EcsWorld _source; @@ -23,7 +23,6 @@ namespace DCFApixels.DragonECS #region Properites public int Count => _count; public sealed override EcsWorld World => _source; - public sealed override Type ComponentType => typeof(T); #endregion #region Init diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index ce6004f..f8895dc 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -4,7 +4,7 @@ using Unity.Profiling; namespace DCFApixels.DragonECS { - public sealed class EcsTagPool : EcsPoolBase + public sealed class EcsTagPool : EcsPoolBase where T : struct, IEcsTagComponent { private EcsWorld _source; @@ -17,7 +17,6 @@ namespace DCFApixels.DragonECS #region Properites public int Count => _count; public sealed override EcsWorld World => _source; - public sealed override Type ComponentType => typeof(T); #endregion #region Init