diff --git a/src/EcsQuery.cs b/src/EcsQuery.cs index 8935b5e..6c454e4 100644 --- a/src/EcsQuery.cs +++ b/src/EcsQuery.cs @@ -50,19 +50,19 @@ namespace DCFApixels.DragonECS return (TQuery)(object)newQuery; } - public override inc_ Include() where TComponent : struct + public sealed override TPool Include() { _inc.Add(_world.GetComponentID()); - return new inc_(_world.GetPool>()); + return _world.GetPool(); } - public override exc_ Exclude() where TComponent : struct + public sealed override TPool Exclude() { _exc.Add(_world.GetComponentID()); - return new exc_(_world.GetPool>()); + return _world.GetPool(); } - public override opt_ Optional() where TComponent : struct + public sealed override TPool Optional() { - return new opt_(_world.GetPool>()); + return _world.GetPool(); } private void End(out EcsQueryMask mask) @@ -77,20 +77,11 @@ namespace DCFApixels.DragonECS } #endregion } - public abstract class EcsHierarchyQuery : EcsQueryBase + public abstract class EcsJoinAttachQuery : EcsQueryBase { - private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsHierarchyQuery.Execute"); + // private EcsPool attachPool; - protected override void OnBuildAfter() { } - public override void Execute() - { - } - } - public abstract class EcsGraphQuery : EcsQueryBase - { - private EcsPool attachPool; - - private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsGraphQuery.Execute"); + private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsJoinAttachQuery.Execute"); protected sealed override void OnBuildAfter() { throw new NotImplementedException(); @@ -108,6 +99,28 @@ namespace DCFApixels.DragonECS return groupFilter.GetEnumerator(); } } + public abstract class EcsJoinRelationQuery : EcsQueryBase + { + // private EcsPool attachPool; + + private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsJoinAttachQuery.Execute"); + protected sealed override void OnBuildAfter() + { + throw new NotImplementedException(); + // attachPool = World.GetPool(); + } + public sealed override void Execute() + { + using (_getEnumerator.Auto()) + { + throw new NotImplementedException(); + } + } + public EcsGroup.Enumerator GetEnumerator() + { + return groupFilter.GetEnumerator(); + } + } public abstract class EcsQuery : EcsQueryBase { @@ -156,8 +169,8 @@ namespace DCFApixels.DragonECS } public abstract class EcsQueryBuilderBase { - public abstract inc_ Include() where TComponent : struct; - public abstract exc_ Exclude() where TComponent : struct; - public abstract opt_ Optional() where TComponent : struct; + 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/EcsQueryMember.cs b/src/EcsQueryMember.cs deleted file mode 100644 index ccdd985..0000000 --- a/src/EcsQueryMember.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace DCFApixels.DragonECS -{ - public interface IEcsQueryMember { } - public interface IEcsQueryReadonlyField : IEcsQueryMember - { - public ref readonly TComponent Read(ent entityID); - public bool Has(ent entityID); - } - public interface IEcsQueryField : IEcsQueryReadonlyField - where TComponent : struct - { - public ref TComponent Add(ent entityID); - public ref TComponent Write(ent entityID); - public void Del(ent entityID); - } - - #region select - [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 8)] - public readonly struct inc_ : IEcsQueryField - where TComponent : struct - { - internal readonly EcsPool pool; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal inc_(EcsPool pool) => this.pool = pool; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TComponent Add(ent entityID) => ref pool.Add(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TComponent Write(ent entityID) => ref pool.Write(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly TComponent Read(ent entityID) => ref pool.Read(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(ent entityID) => pool.Has(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Del(ent entityID) => pool.Del(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator inc_(EcsQueryBuilderBase buider) => buider.Include(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 8)] - public readonly struct exc_ : IEcsQueryField - where TComponent : struct - { - internal readonly EcsPool pool; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal exc_(EcsPool pool) => this.pool = pool; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TComponent Add(ent entityID) => ref pool.Add(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TComponent Write(ent entityID) => ref pool.Write(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly TComponent Read(ent entityID) => ref pool.Read(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(ent entityID) => pool.Has(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Del(ent entityID) => pool.Del(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator exc_(EcsQueryBuilderBase buider) => buider.Exclude(); - } - - [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 8)] - public readonly struct opt_ : IEcsQueryField - where TComponent : struct - { - internal readonly EcsPool pool; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal opt_(EcsPool pool) => this.pool = pool; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TComponent Add(ent entityID) => ref pool.Add(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref TComponent Write(ent entityID) => ref pool.Write(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly TComponent Read(ent entityID) => ref pool.Read(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(ent entityID) => pool.Has(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Del(ent entityID) => pool.Del(entityID.id); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator opt_(EcsQueryBuilderBase buider) => buider.Optional(); - } - #endregion -} diff --git a/src/Exceptions/EcsRelationsException.cs b/src/Exceptions/EcsRelationsException.cs new file mode 100644 index 0000000..685af1b --- /dev/null +++ b/src/Exceptions/EcsRelationsException.cs @@ -0,0 +1,15 @@ +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 90a807b..f96956c 100644 --- a/src/Interfaces/IEcsTable.cs +++ b/src/Interfaces/IEcsTable.cs @@ -17,8 +17,9 @@ namespace DCFApixels.DragonECS public int GetComponentID(); public TPool GetPool() where TComponent : struct where TPool : EcsPoolBase, new(); public ReadOnlySpan GetAllPools(); - public TQuery Where(out TQuery query) where TQuery : EcsQueryBase; public TQuery Select() where TQuery : EcsQueryBase; + public TQuery Where(out TQuery query) where TQuery : EcsQuery; + public TQuery Join(out TQuery query) where TQuery : EcsJoinAttachQuery; public bool IsMaskCompatible(EcsComponentMask mask, int entityID); diff --git a/src/Pools/EcsAttachPool.cs b/src/Pools/EcsAttachPool.cs new file mode 100644 index 0000000..1004520 --- /dev/null +++ b/src/Pools/EcsAttachPool.cs @@ -0,0 +1,127 @@ +using System; +using System.Runtime.CompilerServices; +using Unity.Profiling; + +namespace DCFApixels.DragonECS +{ + public sealed class EcsAttachPool : EcsPoolBase + where T : struct, IEcsAttachComponent + { + private EcsWorld _source; + + private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID + private T[] _items; //sparse + private int _count; + + private PoolRunners _poolRunners; + +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS + private int _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 + protected override void Init(EcsWorld world) + { + _source = world; + + _entityFlags = new bool[world.Capacity]; + _items = new T[world.Capacity]; + _count = 0; + + _poolRunners = new PoolRunners(world.Pipeline); + } + #endregion + + #region Write/Read/Has/Del + private ProfilerMarker _addMark = new ProfilerMarker("EcsPoo.Add"); + private ProfilerMarker _writeMark = new ProfilerMarker("EcsPoo.Write"); + private ProfilerMarker _readMark = new ProfilerMarker("EcsPoo.Read"); + private ProfilerMarker _hasMark = new ProfilerMarker("EcsPoo.Has"); + private ProfilerMarker _delMark = new ProfilerMarker("EcsPoo.Del"); + public void Add(int entityID, EcsEntity target) + { +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS + if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) + { + throw new EcsRelationsException(); + } +#endif + // using (_addMark.Auto()) + // { + ref bool entityFlag = ref _entityFlags[entityID]; + if (entityFlag == false) + { + entityFlag = true; + _count++; + _poolRunners.add.OnComponentAdd(entityID); + } + _poolRunners.write.OnComponentWrite(entityID); + _items[entityID].Target = target; + // } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Set(int entityID, EcsEntity target) + { +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS + if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) + { + throw new EcsRelationsException(); + } +#endif + // using (_writeMark.Auto()) + _poolRunners.write.OnComponentWrite(entityID); + _items[entityID].Target = target; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref readonly T Read(int entityID) + { + // using (_readMark.Auto()) + return ref _items[entityID]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public sealed override bool Has(int entityID) + { + // using (_hasMark.Auto()) + return _entityFlags[entityID]; + } + public void Del(int entityID) + { + // using (_delMark.Auto()) + // { + _entityFlags[entityID] = false; + _count--; + _poolRunners.del.OnComponentDel(entityID); + // } + } + #endregion + + #region WorldCallbacks + protected override void OnWorldResize(int newSize) + { + Array.Resize(ref _entityFlags, newSize); + Array.Resize(ref _items, newSize); + } + protected override void OnDestroy() { } + #endregion + } + + public interface IEcsAttachComponent + { + public EcsEntity Target { get; set; } + } + public static class EcsAttachComponentPoolExt + { + public static EcsAttachPool GetPool(this EcsWorld self) + where TAttachComponent : struct, IEcsAttachComponent + { + return self.GetPool>(); + } + } +} diff --git a/src/Pools/EcsNotNullPool.cs b/src/Pools/EcsNotNullPool.cs index 028b764..d20fc86 100644 --- a/src/Pools/EcsNotNullPool.cs +++ b/src/Pools/EcsNotNullPool.cs @@ -5,11 +5,10 @@ using Unity.Profiling; namespace DCFApixels.DragonECS { public sealed class EcsNotNullPool : EcsPoolBase - where T : struct + where T : struct, INotNullComponent { private EcsWorld _source; - private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID private T[] _items; //sparse private int _count; @@ -28,7 +27,6 @@ namespace DCFApixels.DragonECS { _source = world; - _entityFlags = new bool[world.Capacity]; _items = new T[world.Capacity]; _count = 0; @@ -37,27 +35,12 @@ namespace DCFApixels.DragonECS } #endregion - #region Write/Read/Has/Del + #region Write/Read/Has private ProfilerMarker _addMark = new ProfilerMarker("EcsPoo.Add"); private ProfilerMarker _writeMark = new ProfilerMarker("EcsPoo.Write"); private ProfilerMarker _readMark = new ProfilerMarker("EcsPoo.Read"); private ProfilerMarker _hasMark = new ProfilerMarker("EcsPoo.Has"); private ProfilerMarker _delMark = new ProfilerMarker("EcsPoo.Del"); - public ref T Add(int entityID) - { - // using (_addMark.Auto()) - // { - ref bool entityFlag = ref _entityFlags[entityID]; - if (entityFlag == false) - { - entityFlag = true; - _count++; - _poolRunners.add.OnComponentAdd(entityID); - } - _poolRunners.write.OnComponentWrite(entityID); - return ref _items[entityID]; - // } - } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T Write(int entityID) { @@ -75,24 +58,13 @@ namespace DCFApixels.DragonECS public sealed override bool Has(int entityID) { // using (_hasMark.Auto()) - return _entityFlags[entityID]; - } - public void Del(int entityID) - { - // using (_delMark.Auto()) - // { - _componentResetHandler.Reset(ref _items[entityID]); - _entityFlags[entityID] = false; - _count--; - _poolRunners.del.OnComponentDel(entityID); - // } + return true; } #endregion #region WorldCallbacks protected override void OnWorldResize(int newSize) { - Array.Resize(ref _entityFlags, newSize); Array.Resize(ref _items, newSize); } protected override void OnDestroy() { } @@ -102,10 +74,10 @@ namespace DCFApixels.DragonECS public interface INotNullComponent { } public static class EcsNotNullPoolExt { - public static EcsNotNullPool GetPool(this EcsWorld self) - where TComponent : struct, INotNullComponent + public static EcsNotNullPool GetPool(this EcsWorld self) + where TNotNullComponent : struct, INotNullComponent { - return self.GetPool>(); + return self.GetPool>(); } } } diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index f31c92d..3846b98 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -50,7 +50,7 @@ namespace DCFApixels.DragonECS } public sealed class EcsPool : EcsPoolBase - where T : struct + where T : struct, IEcsComponent { private EcsWorld _source; diff --git a/src/Pools/EcsRelationPool.cs b/src/Pools/EcsRelationPool.cs new file mode 100644 index 0000000..164a3d0 --- /dev/null +++ b/src/Pools/EcsRelationPool.cs @@ -0,0 +1,134 @@ +using System; +using System.Runtime.CompilerServices; +using Unity.Profiling; + +namespace DCFApixels.DragonECS +{ + public sealed class EcsRelationPool : EcsPoolBase + where T : struct, IEcsRelationComponent + { + private EcsWorld _source; + + private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID + private T[] _items; //sparse + private int _count; + + private PoolRunners _poolRunners; + +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS + private int _sanitizeFirstWorld = -1; + private int _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 + protected override void Init(EcsWorld world) + { + _source = world; + + _entityFlags = new bool[world.Capacity]; + _items = new T[world.Capacity]; + _count = 0; + + _poolRunners = new PoolRunners(world.Pipeline); + } + #endregion + + #region Write/Read/Has/Del + private ProfilerMarker _addMark = new ProfilerMarker("EcsPoo.Add"); + private ProfilerMarker _writeMark = new ProfilerMarker("EcsPoo.Write"); + private ProfilerMarker _readMark = new ProfilerMarker("EcsPoo.Read"); + private ProfilerMarker _hasMark = new ProfilerMarker("EcsPoo.Has"); + private ProfilerMarker _delMark = new ProfilerMarker("EcsPoo.Del"); + public void Add(int entityID, EcsEntity first, EcsEntity second) + { +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS + if((_sanitizeFirstWorld >= 0 && first.world != _sanitizeFirstWorld) && + (_sanitizeSecondWorld >= 0 && second.world != _sanitizeSecondWorld)) + { + throw new EcsRelationsException(); + } +#endif + // using (_addMark.Auto()) + // { + ref bool entityFlag = ref _entityFlags[entityID]; + if (entityFlag == false) + { + entityFlag = true; + _count++; + _poolRunners.add.OnComponentAdd(entityID); + } + _poolRunners.write.OnComponentWrite(entityID); + _items[entityID].Set(first, second); + // } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Set(int entityID, EcsEntity first, EcsEntity second) + { +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS + if ((_sanitizeFirstWorld >= 0 && first.world != _sanitizeFirstWorld) && + (_sanitizeSecondWorld >= 0 && second.world != _sanitizeSecondWorld)) + { + throw new EcsRelationsException(); + } +#endif + // using (_writeMark.Auto()) + //{ + _poolRunners.write.OnComponentWrite(entityID); + _items[entityID].Set(first, second); + //} + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref readonly T Read(int entityID) + { + // using (_readMark.Auto()) + return ref _items[entityID]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public sealed override bool Has(int entityID) + { + // using (_hasMark.Auto()) + return _entityFlags[entityID]; + } + public void Del(int entityID) + { + // using (_delMark.Auto()) + // { + _entityFlags[entityID] = false; + _count--; + _poolRunners.del.OnComponentDel(entityID); + // } + } + #endregion + + #region WorldCallbacks + protected override void OnWorldResize(int newSize) + { + Array.Resize(ref _entityFlags, newSize); + Array.Resize(ref _items, newSize); + } + protected override void OnDestroy() { } + #endregion + } + + public interface IEcsRelationComponent + { + public EcsEntity First { get; set; } + public EcsEntity Second { get; set; } + public void Set(EcsEntity first, EcsEntity second); + } + public static class EcsRelationPoolExt + { + public static EcsRelationPool GetPool(this EcsWorld self) + where TRelationComponent : struct, IEcsRelationComponent + { + return self.GetPool>(); + } + } +} diff --git a/src/Pools/EcsSinglePool.cs b/src/Pools/EcsSinglePool.cs index 7590b98..3f58361 100644 --- a/src/Pools/EcsSinglePool.cs +++ b/src/Pools/EcsSinglePool.cs @@ -5,7 +5,7 @@ using Unity.Profiling; namespace DCFApixels.DragonECS { public sealed class EcsSinglePool : EcsPoolBase - where T : struct + where T : struct, IEcsSingleComponent { private EcsWorld _source; @@ -93,11 +93,11 @@ namespace DCFApixels.DragonECS #endregion } - public interface ISingleComponent { } + public interface IEcsSingleComponent { } public static class EcsSinglePoolExt { public static EcsSinglePool GetPool(this EcsWorld self) - where TSingleComponent : struct, ISingleComponent + where TSingleComponent : struct, IEcsSingleComponent { return self.GetPool>(); } diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 07698dd..6e93734 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -5,11 +5,11 @@ using Unity.Profiling; namespace DCFApixels.DragonECS { public sealed class EcsTagPool : EcsPoolBase - where T : struct + where T : struct, IEcsTagComponent { private EcsWorld _source; - private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID + private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID private int _count; private PoolRunners _poolRunners; @@ -25,7 +25,7 @@ namespace DCFApixels.DragonECS { _source = world; - _mapping = new int[world.Capacity]; + _mapping = new bool[world.Capacity]; _count = 0; _poolRunners = new PoolRunners(world.Pipeline); @@ -40,9 +40,10 @@ namespace DCFApixels.DragonECS { // using (_addMark.Auto()) // { - if (_mapping[entityID] <= 0) + if (_mapping[entityID] == false) { - _mapping[entityID] = ++_count; + _count++; + _mapping[entityID] = true; _poolRunners.add.OnComponentAdd(entityID); } // } @@ -51,13 +52,13 @@ namespace DCFApixels.DragonECS public sealed override bool Has(int entityID) { // using (_hasMark.Auto()) - return _mapping[entityID] > 0; + return _mapping[entityID]; } public void Del(int entityID) { // using (_delMark.Auto()) // { - _mapping[entityID] = 0; + _mapping[entityID] = false; _count--; _poolRunners.del.OnComponentDel(entityID); // }