diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 9e300a1..b046358 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -5,6 +5,8 @@ using delayedOp = System.Int32; namespace DCFApixels.DragonECS { + + [StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)] public readonly ref struct EcsReadonlyGroup { @@ -242,7 +244,7 @@ namespace DCFApixels.DragonECS private readonly EcsGroup _source; private readonly int[] _dense; private readonly int _count; - private int _pointer; + private int _index; [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator(EcsGroup group) @@ -250,26 +252,22 @@ namespace DCFApixels.DragonECS _source = group; _dense = group._dense; _count = group.Count; - _pointer = 0; + _index = 0; } - public ent Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _source.World.GetEntity(_dense[_pointer]); + get => _source.World.GetEntity(_dense[_index]); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { - return ++_pointer <= _count && _count < _dense.Length; //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны + // <= потму что отсчет начинается с индекса 1 + return ++_index <= _count && _count < _dense.Length; //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - _source.Unlock(); - } + public void Dispose() => _source.Unlock(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Reset() { } diff --git a/src/EcsPool.cs b/src/EcsPool.cs index c45c98e..68cfc4b 100644 --- a/src/EcsPool.cs +++ b/src/EcsPool.cs @@ -1,60 +1,51 @@ using System; -using System.Linq; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using Unity.Profiling; namespace DCFApixels.DragonECS { public interface IEcsPool { - public int EntitiesCount { get; } - public int Capacity { get; } - + public Type ComponentType { get; } + public int ComponentID { get; } public IEcsWorld World { get; } - public Type DataType { get; } - public int ID { get; } + public int Count { get; } + public int Capacity { get; } public bool Has(int entityID); public void Write(int entityID); public void Del(int entityID); - internal void OnWorldResize(int newSize); } - - public interface IEcsPool : IEcsPool - where T : struct + public interface IEcsPool : IEcsPool where T : struct { public ref readonly T Read(int entity); public new ref T Write(int entity); } - public class EcsNullPool : IEcsPool + public struct NullComponent { } + public sealed class EcsNullPool : IEcsPool { + public static EcsNullPool instance => new EcsNullPool(null); private readonly IEcsWorld _source; - - public EcsNullPool(IEcsWorld source) - { - _source = source; - } - + private EcsNullPool(IEcsWorld source) => _source = source; + private NullComponent fakeComponent; + public Type ComponentType => typeof(NullComponent); + public int ComponentID => -1; public IEcsWorld World => _source; - public Type DataType => typeof(void); - public int ID => -1; - - public int EntitiesCount => 0; + public int Count => 0; public int Capacity => 1; - public void Del(int index) { } public bool Has(int index) => false; - public void Write(int index) { } - + void IEcsPool.Write(int entityID) { } + public ref readonly NullComponent Read(int entity) => ref fakeComponent; + public ref NullComponent Write(int entity) => ref fakeComponent; void IEcsPool.OnWorldResize(int newSize) { } } - public class EcsPool : IEcsPool + public sealed class EcsPool : IEcsPool where T : struct { - private readonly int _id; + private readonly int _componentID; private readonly IEcsWorld _source; private int[] _mapping;// index = entity / value = itemIndex;/ value = 0 = no entity @@ -68,19 +59,18 @@ namespace DCFApixels.DragonECS private PoolRunnres _poolRunnres; #region Properites - public int EntitiesCount => _itemsCount; + public int Count => _itemsCount; public int Capacity => _items.Length; - public IEcsWorld World => _source; - public Type DataType => typeof(T); - public int ID => _id; + public Type ComponentType => typeof(T); + public int ComponentID => _componentID; #endregion #region Constructors internal EcsPool(IEcsWorld source, int id, int capacity, PoolRunnres poolRunnres) { _source = source; - _id = id; + _componentID = id; _mapping = new int[source.EntitesCapacity]; _recycledItems = new int[128]; @@ -94,7 +84,6 @@ namespace DCFApixels.DragonECS #endregion #region Write/Read/Has/Del - private ProfilerMarker _writeMark = new ProfilerMarker("EcsPoo.Write"); private ProfilerMarker _readMark = new ProfilerMarker("EcsPoo.Read"); private ProfilerMarker _hasMark = new ProfilerMarker("EcsPoo.Has"); @@ -119,7 +108,7 @@ namespace DCFApixels.DragonECS } _mapping[entityID] = itemIndex; _componentResetHandler.Reset(ref _items[itemIndex]); - _source.OnEntityComponentAdded(entityID, _id); + _source.OnEntityComponentAdded(entityID, _componentID); _poolRunnres.add.OnComponentAdd(entityID); } @@ -148,7 +137,7 @@ namespace DCFApixels.DragonECS _recycledItems[_recycledItemsCount++] = _mapping[entityID]; _mapping[entityID] = 0; _itemsCount--; - _source.OnEntityComponentRemoved(entityID, _id); + _source.OnEntityComponentRemoved(entityID, _componentID); _poolRunnres.del.OnComponentDel(entityID); // } } @@ -161,17 +150,16 @@ namespace DCFApixels.DragonECS } #endregion - #region Equals/GetHashCode - public override bool Equals(object obj) - { - return base.Equals(obj); - } - public override int GetHashCode() => _source.GetHashCode() + ID; + #region Object + public override bool Equals(object obj) => base.Equals(obj); + public override int GetHashCode() => _source.GetHashCode() + ~ComponentID; #endregion + #region Internal void IEcsPool.OnWorldResize(int newSize) { Array.Resize(ref _mapping, newSize); } + #endregion } } diff --git a/src/EcsRelationTable.cs b/src/EcsRelationTable.cs index 457980c..069b817 100644 --- a/src/EcsRelationTable.cs +++ b/src/EcsRelationTable.cs @@ -1,46 +1,51 @@ using DCFApixels.DragonECS; +using DCFApixels.DragonECS.Internal; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEditorInternal; -namespace DCFApixels.Assets.DragonECS.src +namespace DCFApixels.DragonECS { - public class EcsRelationTable + /* public interface IEcsRealationTable : IEcsReadonlyTable + { + public EcsFilter Relations() where TComponent : struct; + + } + public sealed class EcsRelationTable : IEcsRealationTable + where TArchetype : EcsRelationTableArchetypeBase { public readonly IEcsWorld leftWorld; public readonly IEcsWorld rightWorld; - - private int[] _relationEntities; //dense + private int[] _relations; //dense private int[] _leftMapping; private int[] _rgihtMapping; private int _relationsCount; + private IEcsPool[] _pools; + private EcsNullPool _nullPool; #region Properties - public int RelationsCount - { - get => _relationsCount; - } + public Type ArchetypeType => typeof(TArchetype); + public int EntitesCount => _relationsCount; + public int EntitesCapacity => _relations.Length; #endregion - + #region Constructors internal EcsRelationTable(IEcsWorld leftWorld, IEcsWorld rightWorld) { this.leftWorld = leftWorld; this.rightWorld = rightWorld; - _relationEntities = new int[512]; + _relations = new int[512]; _leftMapping = new int[512]; _rgihtMapping = new int[512]; _relationsCount = 0; } + #endregion + #region RealtionControls public void AddRelation(int leftEnttiyID, int rightEntityID) { @@ -53,5 +58,80 @@ namespace DCFApixels.Assets.DragonECS.src { } - } + #endregion + + public ReadOnlySpan GetAllPools() + { + throw new NotImplementedException(); + } + + public int GetComponentID() + { + throw new NotImplementedException(); + } + + public EcsPool GetPool() where T : struct + { + throw new NotImplementedException(); + } + + public EcsPool UncheckedGetPool() where T : struct + { + throw new NotImplementedException(); + } + + public EcsFilter Entities() where TComponent : struct + { + throw new NotImplementedException(); + } + + public EcsFilter Filter() where TInc : struct, IInc + { + throw new NotImplementedException(); + } + + public EcsFilter Filter() + where TInc : struct, IInc + where TExc : struct, IExc + { + throw new NotImplementedException(); + } + + public bool IsMaskCompatible(int entity) where TInc : struct, IInc + { + throw new NotImplementedException(); + } + + public bool IsMaskCompatible(int entity) + where TInc : struct, IInc + where TExc : struct, IExc + { + throw new NotImplementedException(); + } + + public bool IsMaskCompatible(EcsMask mask, int entity) + { + throw new NotImplementedException(); + } + + public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherPoolID) + { + throw new NotImplementedException(); + } + + void IEcsReadonlyTable.OnEntityComponentAdded(int entityID, int changedPoolID) + { + throw new NotImplementedException(); + } + + void IEcsReadonlyTable.OnEntityComponentRemoved(int entityID, int changedPoolID) + { + throw new NotImplementedException(); + } + + void IEcsReadonlyTable.RegisterGroup(EcsGroup group) + { + throw new NotImplementedException(); + } + }*/ } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index d6742ba..bad403f 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -1,52 +1,29 @@ -using System; +using DCFApixels.DragonECS.Internal; +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { - public interface IEcsWorld + public interface IEcsWorld : IEcsReadonlyTable { #region Properties //private float _timeScale;//TODO реализовать собсвенныйтайм склей для разных миров - public bool IsEmpty { get; } - public Type ArchetypeType { get; } public int ID { get; } public EcsPipeline Pipeline { get; } public int EntitesCount { get; } public int EntitesCapacity { get; } #endregion - #region GetterMethods - public ReadOnlySpan GetAllPools(); - - #endregion - - #region Methods - public EcsPool GetPool() where T : struct; - public EcsPool UncheckedGetPool() where T : struct; + #region Entities public EcsFilter Entities() where TComponent : struct; - public EcsFilter Filter() where TInc : struct, IInc; - public EcsFilter Filter() where TInc : struct, IInc where TExc : struct, IExc; + public ent NewEntity(); public void DelEntity(ent entity); public bool EntityIsAlive(int entityID, short gen); public ent GetEntity(int entityID); public void Destroy(); - - public bool IsMaskCompatible(int entity) where TInc : struct, IInc; - public bool IsMaskCompatible(int entity) where TInc : struct, IInc where TExc : struct, IExc; - - - public bool IsMaskCompatible(EcsMask mask, int entity); - public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherPoolID); - - internal void OnEntityComponentAdded(int entityID, int changedPoolID); - internal void OnEntityComponentRemoved(int entityID, int changedPoolID); - - public int GetComponentID(); - - internal void RegisterGroup(EcsGroup group); #endregion } @@ -57,12 +34,19 @@ namespace DCFApixels.DragonECS public readonly short id; - public EcsWorld() + protected EcsWorld(bool isIndexed) { - id = (short)_worldIdDispenser.GetFree(); - if(id >= Worlds.Length) - Array.Resize(ref Worlds, Worlds.Length << 1); - Worlds[id] = (IEcsWorld)this; + if(isIndexed == true) + { + id = (short)_worldIdDispenser.GetFree(); + if (id >= Worlds.Length) + Array.Resize(ref Worlds, Worlds.Length << 1); + Worlds[id] = (IEcsWorld)this; + } + else + { + id = -1; + } } protected void Realeze() @@ -106,8 +90,12 @@ namespace DCFApixels.DragonECS #endregion + #region Internal Properties + int IEcsReadonlyTable.Count => _entitiesCount; + int IEcsReadonlyTable.Capacity => _denseEntities.Length; + #endregion + #region Properties - public bool IsEmpty => _entitiesCount < 0; public Type ArchetypeType => typeof(TArchetype); public int ID => id; public EcsPipeline Pipeline => _pipeline; @@ -117,12 +105,12 @@ namespace DCFApixels.DragonECS #endregion #region Constructors - public EcsWorld(EcsPipeline pipline = null) + public EcsWorld(EcsPipeline pipline = null) : base(true) { _pipeline = pipline ?? EcsPipeline.Empty; if (!_pipeline.IsInit) pipline.Init(); _entityDispenser = new IntDispenser(1); - _nullPool = new EcsNullPool(this); + _nullPool = EcsNullPool.instance; _pools = new IEcsPool[512]; FillArray(_pools, _nullPool); @@ -154,7 +142,6 @@ namespace DCFApixels.DragonECS int oldCapacity = _pools.Length; Array.Resize(ref _pools, ComponentType.Capacity); FillArray(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length); - //Array.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length); //TODO Fix it Array.Resize(ref _filtersByIncludedComponents, ComponentType.Capacity); Array.Resize(ref _filtersByExcludedComponents, ComponentType.Capacity); @@ -285,7 +272,7 @@ namespace DCFApixels.DragonECS #region EntityChangedReact - void IEcsWorld.OnEntityComponentAdded(int entityID, int componentID) + void IEcsReadonlyTable.OnEntityComponentAdded(int entityID, int componentID) { var includeList = _filtersByIncludedComponents[componentID]; var excludeList = _filtersByExcludedComponents[componentID]; @@ -316,7 +303,7 @@ namespace DCFApixels.DragonECS // if (excludeList != null) foreach (var filter in excludeList) filter.entities.Remove(entityID); } - void IEcsWorld.OnEntityComponentRemoved(int entityID, int componentID) + void IEcsReadonlyTable.OnEntityComponentRemoved(int entityID, int componentID) { var includeList = _filtersByIncludedComponents[componentID]; var excludeList = _filtersByExcludedComponents[componentID]; @@ -458,7 +445,7 @@ namespace DCFApixels.DragonECS #endregion #region Other - void IEcsWorld.RegisterGroup(EcsGroup group) + void IEcsReadonlyTable.RegisterGroup(EcsGroup group) { _groups.Add(group); } diff --git a/src/Interfaces/IEcsEntityComponentTable.cs b/src/Interfaces/IEcsReadonlyTable.cs similarity index 71% rename from src/Interfaces/IEcsEntityComponentTable.cs rename to src/Interfaces/IEcsReadonlyTable.cs index d119050..266f5e9 100644 --- a/src/Interfaces/IEcsEntityComponentTable.cs +++ b/src/Interfaces/IEcsReadonlyTable.cs @@ -6,45 +6,46 @@ using System.Threading.Tasks; namespace DCFApixels.DragonECS { - public interface IEcsEntityComponentTable + public interface IEcsReadonlyTable { #region Properties - public bool IsEmpty { get; } + /// Table Archetype public Type ArchetypeType { get; } - //public int ID { get; } - public int EntitesCount { get; } - public int EntitesCapacity { get; } - #endregion - - #region GetterMethods - public ReadOnlySpan GetAllPools(); - #endregion #region Methods + public ReadOnlySpan GetAllPools(); + public int GetComponentID(); + public EcsPool GetPool() where T : struct; public EcsPool UncheckedGetPool() where T : struct; - public EcsFilter Entities() where TComponent : struct; public EcsFilter Filter() where TInc : struct, IInc; public EcsFilter Filter() where TInc : struct, IInc where TExc : struct, IExc; - public ent NewEntity(); - public void DelEntity(ent entity); - public bool EntityIsAlive(int entityID, short gen); - public ent GetEntity(int entityID); - public void Destroy(); - public bool IsMaskCompatible(int entity) where TInc : struct, IInc; public bool IsMaskCompatible(int entity) where TInc : struct, IInc where TExc : struct, IExc; public bool IsMaskCompatible(EcsMask mask, int entity); public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherPoolID); + #endregion + #region Properties + internal int Count { get; } + internal int Capacity { get; } + #endregion + + #region Internal Methods internal void OnEntityComponentAdded(int entityID, int changedPoolID); internal void OnEntityComponentRemoved(int entityID, int changedPoolID); - - public int GetComponentID(); internal void RegisterGroup(EcsGroup group); #endregion } + + public static class IEcsReadonlyEntityComponentTableExtensions + { + public static bool IsNullOrEmpty(this IEcsReadonlyTable self) + { + return self == null || self.Count <= 0; + } + } } diff --git a/src/Interfaces/INullDummy.cs b/src/Interfaces/INullDummy.cs new file mode 100644 index 0000000..2ff6c3b --- /dev/null +++ b/src/Interfaces/INullDummy.cs @@ -0,0 +1,7 @@ +namespace DCFApixels.DragonECS +{ + public interface INullDummy + { + public bool IsDummy { get; } + } +} diff --git a/src/Utils/EcsRelationTableArchetype.cs b/src/Utils/EcsRelationTableArchetype.cs new file mode 100644 index 0000000..33ab50f --- /dev/null +++ b/src/Utils/EcsRelationTableArchetype.cs @@ -0,0 +1,16 @@ +using System; + +namespace DCFApixels.DragonECS.Internal +{ + public abstract class EcsRelationTableArchetypeBase + { + public EcsRelationTableArchetypeBase() + { + throw new TypeAccessException("Сreating instances of EcsRelationTableArchetype class is not available."); + } + } + public sealed class EcsRelationTableArchetype : EcsRelationTableArchetypeBase + where TLeftWorld : EcsWorld + where TRightWorld : EcsWorld + { } +} diff --git a/src/Utils/ITabelRecord.cs b/src/Utils/ITabelRecord.cs new file mode 100644 index 0000000..e7006d6 --- /dev/null +++ b/src/Utils/ITabelRecord.cs @@ -0,0 +1,8 @@ +namespace DCFApixels.DragonECS +{ + public interface ITabelRecord + { + //TODO rename to index; Так ent по определению станет идентификатором + public int Id { get; } + } +} diff --git a/src/ent.cs b/src/ent.cs index 3b3ecd5..97b746b 100644 --- a/src/ent.cs +++ b/src/ent.cs @@ -5,16 +5,26 @@ using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { + public interface IEntityRecord : ITabelRecord + { + public bool IsSpecific { get; } + internal long Full { get; } + public short Gen { get; } + public short World { get; } + } // id - 32 bits // gen - 16 bits // world - 16 bits [StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)] - public readonly struct ent : IEquatable, IEquatable + public readonly partial struct ent : + IEquatable, + IEquatable, + IEntityRecord { public static readonly ent NULL = default; [FieldOffset(0)] - private readonly long _full; + internal readonly long full; //Union [FieldOffset(3)] public readonly int id; [FieldOffset(1)] @@ -22,44 +32,41 @@ namespace DCFApixels.DragonECS [FieldOffset(0)] public readonly short world; + #region IEntityRecord + bool IEntityRecord.IsSpecific => false; + long IEntityRecord.Full => full; + int ITabelRecord.Id => id; + short IEntityRecord.Gen => gen; + short IEntityRecord.World => world; + #endregion + #region Constructors - [EditorBrowsable(EditorBrowsableState.Never)] - public ent(int id, short gen, short world): this() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ent(int id, short gen, short world) : this() { this.id = id; this.gen = gen; this.world = world; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ent(long full) : this() { - _full = full; + this.full = full; } #endregion #region GetHashCode [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override int GetHashCode() - { - return unchecked((int)(_full)) ^ (int)(_full >> 32); - } + public override int GetHashCode() => unchecked((int)(full)) ^ (int)(full >> 32); #endregion #region Equals [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override bool Equals(object obj) - { - return obj is ent other && _full == other._full; - } + public override bool Equals(object obj) => obj is ent other && full == other.full; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(ent other) - { - return _full == other._full; - } + public bool Equals(ent other) => full == other.full; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(long other) - { - return _full == other; - } + public bool Equals(long other) => full == other; #endregion #region ToString @@ -69,31 +76,72 @@ namespace DCFApixels.DragonECS #region operators [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(in ent a, in ent b) => a._full == b._full; - + public static bool operator ==(in ent a, in ent b) => a.full == b.full; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(in ent a, in ent b) => a._full != b._full; - + public static bool operator !=(in ent a, in ent b) => a.full != b.full; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator long(in ent a) => a._full; - + public static explicit operator long(in ent a) => a.full; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator int(in ent a) => a.id; - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator ent(in long a) => new ent(a); #endregion } - public static partial class entExtensions + public readonly partial struct ent { - private static EcsProfilerMarker _IsAliveMarker = new EcsProfilerMarker("ent.IsAlive"); private static EcsProfilerMarker _IsNullMarker = new EcsProfilerMarker("ent.IsNull"); private static EcsProfilerMarker _ReadMarker = new EcsProfilerMarker("ent.Read"); private static EcsProfilerMarker _WriteMarker = new EcsProfilerMarker("ent.Write"); private static EcsProfilerMarker _HasMarker = new EcsProfilerMarker("ent.Has"); private static EcsProfilerMarker _DelMarker = new EcsProfilerMarker("ent.Del"); + public bool IsNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + //using (_IsNullMarker.Auto()) + return this == NULL; + } + } + + public ref readonly T Read() + where T : struct + { + //using (_ReadMarker.Auto()) + return ref EcsWorld.Worlds[world].GetPool().Read(id); + } + public ref T Write() + where T : struct + { + //using (_WriteMarker.Auto()) + return ref EcsWorld.Worlds[world].GetPool().Write(id); + } + public bool Has() + where T : struct + { + //using (_HasMarker.Auto()) + return EcsWorld.Worlds[world].GetPool().Has(id); + } + public bool NotHas() + where T : struct + { + //using (_HasMarker.Auto()) + return EcsWorld.Worlds[world].GetPool().Has(id); + } + public void Del() + where T : struct + { + //using (_DelMarker.Auto()) + EcsWorld.Worlds[world].GetPool().Del(id); + } + } + + public static partial class entExtensions + { + private static EcsProfilerMarker _IsAliveMarker = new EcsProfilerMarker("ent.IsAlive"); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsAlive(this ref ent self) { @@ -104,43 +152,5 @@ namespace DCFApixels.DragonECS return result; //} } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsNull(this in ent self) - { - //using (_IsNullMarker.Auto()) - return self == ent.NULL; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref readonly T Read(this in ent self) - where T : struct - { - //using (_ReadMarker.Auto()) - return ref EcsWorld.Worlds[self.world].GetPool().Read(self.id); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref T Write(this in ent self) - where T : struct - { - //using (_WriteMarker.Auto()) - return ref EcsWorld.Worlds[self.world].GetPool().Write(self.id); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Has(this in ent self) - where T : struct - { - //using (_HasMarker.Auto()) - return EcsWorld.Worlds[self.world].GetPool().Has(self.id); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool NotHas(this in ent self) where T : struct => !Has(in self); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Del(this in ent self) - where T : struct - { - //using (_DelMarker.Auto()) - EcsWorld.Worlds[self.world].GetPool().Del(self.id); - } } } diff --git a/src/rel.cs b/src/rel.cs index be53451..580b1d8 100644 --- a/src/rel.cs +++ b/src/rel.cs @@ -16,14 +16,21 @@ namespace DCFApixels.DragonECS.TODO - // left entity id - 32 bits - // right entity id - 32 bits - [StructLayout(LayoutKind.Explicit, Pack = 4, Size = 8)] - public struct rel + [StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)] + public readonly ref partial struct rel { - [FieldOffset(0)] - public int l; - [FieldOffset(1)] - public int r; + public readonly int id; + public readonly short leftWorld; + public readonly short rightWorld; + + #region Constructors + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public rel(int id, short leftWorld, short rightWorld) + { + this.id = id; + this.leftWorld = leftWorld; + this.rightWorld = rightWorld; + } + #endregion } }