diff --git a/src/Builtin/Components.cs b/src/Builtin/Components.cs index 1c9d67c..46ec954 100644 --- a/src/Builtin/Components.cs +++ b/src/Builtin/Components.cs @@ -7,18 +7,18 @@ namespace DCFApixels.DragonECS /// Используется для реализации отношений. traget - это сущьность к которой крепится эта сущьность. other - это сущьность с которой traget образует связь /// [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 16)] - public readonly struct Attach + public readonly struct Edge { [FieldOffset(0), MarshalAs(UnmanagedType.U8)] - public readonly EcsEntity target; + public readonly EcsEntity origin; [FieldOffset(1), MarshalAs(UnmanagedType.U8)] public readonly EcsEntity other; - /// alias for "target" + /// alias for "origin" public EcsEntity left { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => target; + get => origin; } /// alias for "other" public EcsEntity right diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 1097010..5a303e1 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -141,7 +141,7 @@ namespace DCFApixels.DragonECS _source = world; _source.RegisterGroup(this); _dense = new int[denseCapacity]; - _sparse = new int[world.EntitesCapacity]; + _sparse = new int[world.Capacity]; _delayedOps = new delayedOp[delayedOpsCapacity]; @@ -435,7 +435,7 @@ namespace DCFApixels.DragonECS public ent Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => (ent)_dense[_index]; + get => new ent(_dense[_index]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() => ++_index <= _count && _count<_dense.Length; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны diff --git a/src/EcsMask.cs b/src/EcsMask.cs index 5de79e2..0d6a637 100644 --- a/src/EcsMask.cs +++ b/src/EcsMask.cs @@ -389,11 +389,11 @@ namespace DCFApixels.DragonECS // return; // } // - // var id = _count++; + // var uniqueID = _count++; // if (_count >= _capacity) // _capacity <<= 1; // - // instance = new EcsMask(typeof(TWorldArchetype), id, inc_, exc_); + // instance = new EcsMask(typeof(TWorldArchetype), uniqueID, inc_, exc_); } public readonly static EcsMask instance; diff --git a/src/EcsPool.cs b/src/EcsPool.cs index e46d52a..5040d3e 100644 --- a/src/EcsPool.cs +++ b/src/EcsPool.cs @@ -87,7 +87,7 @@ namespace DCFApixels.DragonECS _source = source; _componentID = id; - _mapping = new int[source.EntitesCapacity]; + _mapping = new int[source.Capacity]; _recycledItems = new int[128]; _recycledItemsCount = 0; _items = new T[capacity]; diff --git a/src/EcsQuery.cs b/src/EcsQuery.cs index 7bb9e1d..b8405c9 100644 --- a/src/EcsQuery.cs +++ b/src/EcsQuery.cs @@ -14,7 +14,7 @@ namespace DCFApixels.DragonECS #region Builder protected virtual void Init(Builder b) { } - protected abstract void OnBuilt(); + protected abstract void OnBuildAfter(); public abstract void Execute(); public sealed class Builder : EcsQueryBuilderBase { @@ -46,7 +46,7 @@ namespace DCFApixels.DragonECS newQuery.groupFilter = EcsGroup.New(world); newQuery.source = world; builder.End(out newQuery.mask); - newQuery.OnBuilt(); + newQuery.OnBuildAfter(); return (TQuery)(object)newQuery; } @@ -80,12 +80,12 @@ namespace DCFApixels.DragonECS public abstract class EcsJoinQuery : EcsQueryBase { - private EcsPool attachPool; + private EcsPool attachPool; private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsQuery.Execute"); - protected sealed override void OnBuilt() + protected sealed override void OnBuildAfter() { - attachPool = World.GetPool(); + attachPool = World.GetPool(); } public sealed override void Execute() { @@ -103,7 +103,7 @@ namespace DCFApixels.DragonECS public abstract class EcsQuery : EcsQueryBase { private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsQuery.Execute"); - protected sealed override void OnBuilt() { } + protected sealed override void OnBuildAfter() { } public sealed override void Execute() { using (_getEnumerator.Auto()) diff --git a/src/EcsQueryMember.cs b/src/EcsQueryMember.cs index d2f5922..e466903 100644 --- a/src/EcsQueryMember.cs +++ b/src/EcsQueryMember.cs @@ -91,9 +91,9 @@ namespace DCFApixels.DragonECS // [MethodImpl(MethodImplOptions.AggressiveInlining)] // internal inc_readonly_(EcsPool pool) => this.pool = pool; // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ref TComponent Read(ent entityID) => ref pool.Read(entityID.id); + // public ref TComponent Read(ent entityID) => ref pool.Read(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Has(ent entityID) => pool.Has(entityID.id); + // public bool Has(ent entityID) => pool.Has(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] // // public static implicit operator inc_readonly_(EcsQueryBuilderBase buider) => buider.Include(); @@ -108,9 +108,9 @@ namespace DCFApixels.DragonECS // [MethodImpl(MethodImplOptions.AggressiveInlining)] // internal exc_readonly_(EcsPool pool) => this.pool = pool; // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ref TComponent Read(ent entityID) => ref pool.Read(entityID.id); + // public ref TComponent Read(ent entityID) => ref pool.Read(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Has(ent entityID) => pool.Has(entityID.id); + // public bool Has(ent entityID) => pool.Has(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] // // public static implicit operator exc_readonly_(EcsQueryBuilderBase buider) => buider.Exclude(); @@ -125,9 +125,9 @@ namespace DCFApixels.DragonECS // [MethodImpl(MethodImplOptions.AggressiveInlining)] // internal opt_readonly_(EcsPool pool) => this.pool = pool; // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ref TComponent Read(ent entityID) => ref pool.Read(entityID.id); + // public ref TComponent Read(ent entityID) => ref pool.Read(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Has(ent entityID) => pool.Has(entityID.id); + // public bool Has(ent entityID) => pool.Has(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] // // public static implicit operator opt_readonly_(EcsQueryBuilderBase buider) => buider.Optional(); @@ -137,24 +137,24 @@ namespace DCFApixels.DragonECS // // #region join // [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 8)] - // public readonly struct attach : IEcsQueryField + // public readonly struct attach : IEcsQueryField // { - // internal readonly EcsPool pool; + // internal readonly EcsPool pool; // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // internal attach(EcsPool pool) => this.pool = pool; + // internal attach(EcsPool pool) => this.pool = pool; // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ref Attach Add(ent entityID) => ref pool.Add(entityID.id); + // public ref Edge Add(ent entityID) => ref pool.Add(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ref Attach Write(ent entityID) => ref pool.Write(entityID.id); + // public ref Edge Write(ent entityID) => ref pool.Write(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public ref Attach Read(ent entityID) => ref pool.Read(entityID.id); + // public ref Edge Read(ent entityID) => ref pool.Read(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public bool Has(ent entityID) => pool.Has(entityID.id); + // public bool Has(ent entityID) => pool.Has(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public void Del(ent entityID) => pool.Del(entityID.id); + // public void Del(ent entityID) => pool.Del(entityID.uniqueID); // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static implicit operator attach(EcsQueryBuilderBase buider) => buider.Include(); - // public static implicit operator attach(inc_ o) => new attach(o.pool); + // public static implicit operator attach(EcsQueryBuilderBase buider) => buider.Include(); + // public static implicit operator attach(inc_ o) => new attach(o.pool); // } // #endregion } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 2ced962..c89b682 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -6,14 +6,11 @@ using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { - public interface IEcsWorld : IEcsReadonlyTable + public interface IEcsWorld : IEcsTable { #region Properties - //private float _timeScale;//TODO реализовать собсвенныйтайм склей для разных миров - public int ID { get; } + public int UniqueID { get; } public EcsPipeline Pipeline { get; } - public int EntitesCount { get; } - public int EntitesCapacity { get; } public EcsReadonlyGroup Entities => default; #endregion @@ -21,7 +18,7 @@ namespace DCFApixels.DragonECS public EcsEntity NewEntity(); public void DelEntity(EcsEntity entity); public bool EntityIsAlive(int entityID, short gen); - public EcsEntity GetEntity(int entityID); + public EcsEntity GetEcsEntity(int entityID); public void Destroy(); #endregion @@ -36,41 +33,35 @@ namespace DCFApixels.DragonECS public static IEcsWorld[] Worlds = new IEcsWorld[8]; private static IntDispenser _worldIdDispenser = new IntDispenser(0); - public readonly short id; + public readonly short uniqueID; - protected EcsWorld(bool isIndexable) + protected EcsWorld() { - if(isIndexable == true) - { - id = (short)_worldIdDispenser.GetFree(); - if (id >= Worlds.Length) - Array.Resize(ref Worlds, Worlds.Length << 1); - Worlds[id] = (IEcsWorld)this; - } - else - { - id = -1; - } + uniqueID = (short)_worldIdDispenser.GetFree(); + if (uniqueID >= Worlds.Length) + Array.Resize(ref Worlds, Worlds.Length << 1); + Worlds[uniqueID] = (IEcsWorld)this; } protected void Realeze() { - Worlds[id] = null; - _worldIdDispenser.Release(id); + Worlds[uniqueID] = null; + _worldIdDispenser.Release(uniqueID); } } public abstract class EcsWorld : EcsWorld, IEcsWorld where TWorldArchetype : EcsWorld { + private readonly int _worldArchetypeID = ComponentIndexer.GetWorldId(); + private IntDispenser _entityDispenser; - private int[] _denseEntities; private int _entitiesCount; + private int _entitesCapacity; private short[] _gens; //старший бит указывает на то жива ли сущьность. - private EcsGroup _allEntites; - //private short[] _componentCounts; //TODO + private EcsPool[] _pools; private EcsNullPool _nullPool; @@ -79,36 +70,11 @@ namespace DCFApixels.DragonECS private EcsPipeline _pipeline; private List> _groups; + private Stack _groupsPool = new Stack(64); - public IEcsRealationTable[] _relationTables; - - private readonly int _worldArchetypeID = ComponentIndexer.GetWorldId(); - - #region RelationTables - public IEcsRealationTable GetRelationTalbe(TWorldArhetype targetWorld) - where TWorldArhetype : EcsWorld - { - int targetID = targetWorld.ID; - if (targetID <= 0) - throw new ArgumentException("targetWorld.ID <= 0"); - - if(_relationTables.Length <= targetID) - Array.Resize(ref _relationTables, targetID + 8); - - if (_relationTables[targetID] == null) - { - // _relationTables[targetID]= new EcsRelationTable - } - - throw new NotImplementedException(); - } - #endregion - - #region RunnersCache private PoolRunnres _poolRunnres; private IEcsEntityCreate _entityCreate; private IEcsEntityDestroy _entityDestry; - #endregion #region GetterMethods public ReadOnlySpan GetAllPools() => new ReadOnlySpan(_pools); @@ -116,25 +82,18 @@ namespace DCFApixels.DragonECS #endregion - #region Internal Properties - int IEcsReadonlyTable.Count => _entitiesCount; - int IEcsReadonlyTable.Capacity => _denseEntities.Length; - #endregion - #region Properties public Type ArchetypeType => typeof(TWorldArchetype); - public int ID => id; + public int UniqueID => uniqueID; + public int Count => _entitiesCount; + public int Capacity => _entitesCapacity; //_denseEntities.Length; public EcsPipeline Pipeline => _pipeline; - - public int EntitesCount => _entitiesCount; - public int EntitesCapacity => _denseEntities.Length; public EcsReadonlyGroup Entities => _allEntites.Readonly; #endregion #region Constructors - public EcsWorld(EcsPipeline pipline = null) : this(pipline, true) { } - internal EcsWorld(EcsPipeline pipline, bool isIndexable) : base(isIndexable) - { + public EcsWorld(EcsPipeline pipline = null) + { _pipeline = pipline ?? EcsPipeline.Empty; if (!_pipeline.IsInit) pipline.Init(); _entityDispenser = new IntDispenser(0); @@ -143,11 +102,11 @@ namespace DCFApixels.DragonECS ArrayUtility.Fill(_pools, _nullPool); _gens = new short[512]; + _entitesCapacity = _gens.Length; + _queries = new EcsQuery[QueryType.capacity]; _groups = new List>(); - _denseEntities = new int[512]; - _poolRunnres = new PoolRunnres(_pipeline); _entityCreate = _pipeline.GetRunner(); _entityDestry = _pipeline.GetRunner(); @@ -162,7 +121,6 @@ namespace DCFApixels.DragonECS #region GetPool public EcsPool GetPool() where T : struct { - //int uniqueID = ComponentType.uniqueID; int uniqueID = ComponentIndexer.GetComponentId(_worldArchetypeID); if (uniqueID >= _pools.Length) @@ -178,7 +136,6 @@ namespace DCFApixels.DragonECS } return (EcsPool)_pools[uniqueID]; } - //public EcsPool UncheckedGetPool() where T : struct => (EcsPool)_pools[ComponentType.uniqueID]; #endregion #region Query @@ -225,13 +182,12 @@ namespace DCFApixels.DragonECS public EcsEntity NewEntity() { int entityID = _entityDispenser.GetFree(); - if (_entityDispenser.LastInt >= _denseEntities.Length) - Array.Resize(ref _denseEntities, _denseEntities.Length << 1); - _denseEntities[_entitiesCount++] = entityID; + _entitiesCount++; if (_gens.Length <= entityID) { Array.Resize(ref _gens, _gens.Length << 1); + _entitesCapacity = _gens.Length; for (int i = 0; i < _groups.Count; i++) { if (_groups[i].TryGetTarget(out EcsGroup group)) @@ -249,7 +205,7 @@ namespace DCFApixels.DragonECS item.OnWorldResize(_gens.Length); } _gens[entityID] |= short.MinValue; - EcsEntity entity = new EcsEntity(entityID, _gens[entityID]++, id); + EcsEntity entity = new EcsEntity(entityID, _gens[entityID]++, uniqueID); _entityCreate.OnEntityCreate(entity); _allEntites.Add(entityID); return entity; @@ -264,9 +220,9 @@ namespace DCFApixels.DragonECS } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public EcsEntity GetEntity(int entityID) + public EcsEntity GetEcsEntity(int entityID) { - return new EcsEntity(entityID, _gens[entityID], id); + return new EcsEntity(entityID, _gens[entityID], uniqueID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool EntityIsAlive(int entityID, short gen) @@ -279,7 +235,7 @@ namespace DCFApixels.DragonECS public void Destroy() { _entityDispenser = null; - _denseEntities = null; + //_denseEntities = null; _gens = null; _pools = null; _nullPool = null; @@ -293,11 +249,27 @@ namespace DCFApixels.DragonECS } #endregion - #region Other - void IEcsReadonlyTable.RegisterGroup(EcsGroup group) + #region Groups + void IEcsTable.RegisterGroup(EcsGroup group) { _groups.Add(new WeakReference(group)); } + EcsGroup IEcsWorld.GetGroupFromPool() => GetGroupFromPool(); + internal EcsGroup GetGroupFromPool() + { + if (_groupsPool.Count <= 0) + return new EcsGroup(this); + return _groupsPool.Pop(); + } + void IEcsWorld.ReleaseGroup(EcsGroup group) + { +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS + if (group.World != this) + throw new ArgumentException("groupFilter.World != this"); +#endif + group.Clear(); + _groupsPool.Push(group); + } #endregion #region Utils @@ -316,58 +288,10 @@ namespace DCFApixels.DragonECS QueryType.capacity <<= 1; } } - /* internal static class ComponentType - { - internal static int increment = 1; - internal static int Capacity - { - get => types.Length; - } - internal static Type[] types = new Type[64]; - } - internal static class ComponentType - { - internal static int uniqueID; - - static ComponentType() - { - uniqueID = ComponentType.increment++; -#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - if (ComponentType.increment + 1 > ushort.MaxValue) - { - throw new EcsFrameworkException($"No more room for new component for this {typeof(TWorldArchetype).FullName} IWorldArchetype"); - } -#endif - if (uniqueID >= ComponentType.types.Length) - { - Array.Resize(ref ComponentType.types, ComponentType.types.Length << 1); - } - ComponentType.types[uniqueID] = typeof(T); - } - }*/ - #endregion - - #region GroupsPool - private Stack _pool = new Stack(64); - EcsGroup IEcsWorld.GetGroupFromPool() => GetGroupFromPool(); - internal EcsGroup GetGroupFromPool() - { - if (_pool.Count <= 0) - return new EcsGroup(this); - return _pool.Pop(); - } - void IEcsWorld.ReleaseGroup(EcsGroup group) - { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - if (group.World != this) - throw new ArgumentException("groupFilter.World != this"); -#endif - group.Clear(); - _pool.Push(group); - } #endregion } + #region Utils [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 24)] internal readonly struct PoolRunnres { @@ -382,9 +306,6 @@ namespace DCFApixels.DragonECS del = pipeline.GetRunner(); } } - - - public static class ComponentIndexer { private static List resizer = new List(); @@ -434,4 +355,5 @@ namespace DCFApixels.DragonECS } } } + #endregion } diff --git a/src/Entities/EcsEntity.cs b/src/Entities/EcsEntity.cs index 3e5b476..6cae0a6 100644 --- a/src/Entities/EcsEntity.cs +++ b/src/Entities/EcsEntity.cs @@ -4,14 +4,14 @@ using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { + // uniqueID - 32 bits + // gen - 16 bits + // world - 16 bits /// Strong identifier/Permanent entity identifier [StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)] public readonly partial struct EcsEntity : IEquatable, IEquatable { public static readonly EcsEntity NULL = default; - // uniqueID - 32 bits - // gen - 16 bits - // world - 16 bits [FieldOffset(0)] internal readonly long full; //Union [FieldOffset(3)] @@ -21,11 +21,8 @@ namespace DCFApixels.DragonECS [FieldOffset(0)] public readonly short world; - public ent Ent - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new ent(id); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ent ToEnt() => EcsWorld.Worlds[world].EntityIsAlive(id, gen) ? new ent(id) : default; #region Constructors [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -53,7 +50,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} gen:{gen} world:{world})"; + public override string ToString() => $"Entity(uniqueID:{id} gen:{gen} world:{world})"; [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object obj) => obj is EcsEntity other && full == other.full; #endregion @@ -66,7 +63,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator long(in EcsEntity a) => a.full; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator ent(in EcsEntity a) => a.Ent; + public static explicit operator ent(in EcsEntity a) => a.ToEnt(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator EcsEntity(in long a) => new EcsEntity(a); #endregion diff --git a/src/Entities/ent.cs b/src/Entities/ent.cs index 160744a..87f5f80 100644 --- a/src/Entities/ent.cs +++ b/src/Entities/ent.cs @@ -13,7 +13,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ent(int id) => this.id = id; - public static explicit operator ent(int id) => new ent(id); + //public static explicit operator ent(int uniqueID) => new ent(uniqueID); public static explicit operator int(ent entityID) => entityID.id; public static bool operator ==(ent a, ent b) => a.id == b.id; @@ -27,6 +27,6 @@ namespace DCFApixels.DragonECS public struct Null { } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public EcsEntity ToStrong(IEcsWorld world) => world.GetEntity(id); + public EcsEntity ToStrong(IEcsWorld world) => world.GetEcsEntity(id); } } diff --git a/src/Interfaces/IEcsReadonlyTable.cs b/src/Interfaces/IEcsTable.cs similarity index 87% rename from src/Interfaces/IEcsReadonlyTable.cs rename to src/Interfaces/IEcsTable.cs index fcb7a24..552921a 100644 --- a/src/Interfaces/IEcsReadonlyTable.cs +++ b/src/Interfaces/IEcsTable.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { - public interface IEcsReadonlyTable + public interface IEcsTable { #region Properties /// Table Archetype @@ -30,7 +30,7 @@ namespace DCFApixels.DragonECS public static class IEcsReadonlyTableExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsMaskCompatible(this IEcsReadonlyTable self, int entityID) where TInc : struct, IInc + public static bool IsMaskCompatible(this IEcsTable self, int entityID) where TInc : struct, IInc { return self.IsMaskCompatible(entityID); }