diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index f780df4..5a40e05 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -61,7 +61,7 @@ namespace DCFApixels.DragonECS { Array.Resize(ref _delayedOps, _delayedOps.Length << 1); } - ref DelayedOp delayedOd = ref _delayedOps[_delayedOpsCount]; + ref DelayedOp delayedOd = ref _delayedOps[_delayedOpsCount++]; delayedOd.Entity = entityID; delayedOd.Added = isAdd; } @@ -108,6 +108,7 @@ namespace DCFApixels.DragonECS Remove(op.Entity); } } + _delayedOpsCount = 0; } } public Enumerator GetEnumerator() diff --git a/src/EcsPool.cs b/src/EcsPool.cs index f7d47d3..3964482 100644 --- a/src/EcsPool.cs +++ b/src/EcsPool.cs @@ -23,6 +23,23 @@ namespace DCFApixels.DragonECS public ref readonly T Read(int entity); public new ref T Write(int entity); } + + public class EcsNullPool : IEcsPool + { + private readonly IEcsWorld _source; + + public EcsNullPool(IEcsWorld source) + { + _source = source; + } + + public IEcsWorld World => _source; + public int ID => -1; + public void Del(int index) { } + public bool Has(int index) => false; + public void Write(int index) { } + } + public class EcsPool : IEcsPool where T : struct { @@ -37,9 +54,10 @@ namespace DCFApixels.DragonECS #endregion #region Constructors - public EcsPool(IEcsWorld source, int capacity) + public EcsPool(IEcsWorld source, int id, int capacity) { _source = source; + _id = id; _sparseSet = new SparseSet(capacity, capacity); _denseItems =new T[capacity]; @@ -50,28 +68,29 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref readonly T Read(int entity) { - return ref _denseItems[_sparseSet[entity]]; + return ref _denseItems[_sparseSet.IndexOf(entity)]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T Write(int entity) { if (_sparseSet.Contains(entity)) { - return ref _denseItems[_sparseSet[entity]]; + return ref _denseItems[_sparseSet.IndexOf(entity)]; } else { _sparseSet.Add(entity); _sparseSet.Normalize(ref _denseItems); _source.OnEntityComponentAdded(entity, _id); - return ref _denseItems[_sparseSet.IndexOf(entity)]; + int indexof = _sparseSet.IndexOf(entity); + return ref _denseItems[indexof]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Has(int entity) { - return _sparseSet.IndexOf(entity) > 0; + return _sparseSet.IndexOf(entity) >= 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Del(int entity) @@ -81,7 +100,7 @@ namespace DCFApixels.DragonECS } #endregion - #region IEcsFieldPool + #region IEcsPool void IEcsPool.Write(int index) { Write(index); diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 8be10df..8a917fe 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Runtime.CompilerServices; using System.Text; -using System.Threading.Tasks; namespace DCFApixels.DragonECS { @@ -24,6 +24,7 @@ namespace DCFApixels.DragonECS public EcsFilter GetFilter() where TInc : struct, IInc; public EcsFilter GetFilter() where TInc : struct, IInc where TExc : struct, IExc; public ent NewEntity(); + public void DelEntity(int entityID); public void Destroy(); public bool IsMaskCompatible(EcsMask mask, int entity); @@ -33,6 +34,14 @@ namespace DCFApixels.DragonECS internal void OnEntityComponentRemoved(int entityID, int changedPoolID); } + public static class IEcsWorldExt + { + public static void DelEntity(this IEcsWorld self, ent entity) + { + self.DelEntity(entity.id); + } + } + public abstract class EcsWorld { @@ -58,6 +67,7 @@ namespace DCFApixels.DragonECS private short[] _componentCounts; private IEcsPool[] _pools; + private EcsNullPool _nullPool; private List[] _filtersByIncludedComponents; private List[] _filtersByExcludedComponents; @@ -74,7 +84,9 @@ namespace DCFApixels.DragonECS public EcsWorld() { _entityDispenser = new IntDispenser(); + _nullPool = new EcsNullPool(this); _pools = new IEcsPool[512]; + Array.Fill(_pools, _nullPool); _gens = new short[512]; _filters = new EcsFilter[64]; _entities = new EcsGroup(this, 512); @@ -90,17 +102,21 @@ namespace DCFApixels.DragonECS if (uniqueID >= _pools.Length) { + int oldCapacity = _pools.Length; Array.Resize(ref _pools, ComponentType.Capacity); + Array.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length); + Array.Resize(ref _filtersByIncludedComponents, ComponentType.Capacity); Array.Resize(ref _filtersByExcludedComponents, ComponentType.Capacity); } - if (_pools[uniqueID] == null) + if (_pools[uniqueID] == _nullPool) { - _pools[uniqueID] = new EcsPool(this, 512); + _pools[uniqueID] = new EcsPool(this, ComponentType.uniqueID, 512); } return (EcsPool)_pools[uniqueID]; } + #endregion #region GetFilter @@ -124,33 +140,42 @@ namespace DCFApixels.DragonECS private EcsFilter NewFilter(EcsMask mask, int capacirty = 512) { - var newFilter = new EcsFilter(this, mask, capacirty); + var filter = new EcsFilter(this, mask, capacirty); for (int i = 0; i < mask.IncCount; i++) { - int poolid = mask.Inc[i]; - var list = _filtersByIncludedComponents[poolid]; + int componentID = mask.Inc[i]; + var list = _filtersByIncludedComponents[componentID]; if (list == null) { list = new List(8); - _filtersByIncludedComponents[poolid] = list; + _filtersByIncludedComponents[componentID] = list; } - list.Add(newFilter); + list.Add(filter); } for (int i = 0; i < mask.ExcCount; i++) { - int poolid = mask.Exc[i]; - var list = _filtersByExcludedComponents[poolid]; + int componentID = mask.Exc[i]; + var list = _filtersByExcludedComponents[componentID]; if (list == null) { list = new List(8); - _filtersByExcludedComponents[poolid] = list; + _filtersByExcludedComponents[componentID] = list; + } + list.Add(filter); + } + // scan exist entities for compatibility with new filter. + foreach (var item in _entities) + { + if (IsMaskCompatible(mask, item.id)) + { + filter.Add(item.id); } - list.Add(newFilter); } - return newFilter; + + return filter; } #endregion @@ -164,21 +189,17 @@ namespace DCFApixels.DragonECS for (int i = 0, iMax = mask.IncCount; i < iMax; i++) { if (!_pools[mask.Inc[i]].Has(entity)) - { return false; - } } for (int i = 0, iMax = mask.ExcCount; i < iMax; i++) { if (_pools[mask.Exc[i]].Has(entity)) - { return false; - } } return true; } - public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherPoolID) + public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherComponentID) { #if DEBUG || !DCFAECS_NO_SANITIZE_CHECKS if (mask.WorldArchetypeType != typeof(TArchetype)) @@ -186,29 +207,25 @@ namespace DCFApixels.DragonECS #endif for (int i = 0, iMax = mask.IncCount; i < iMax; i++) { - int poolID = mask.Inc[i]; - if (poolID == otherPoolID || !_pools[poolID].Has(entity)) - { + int componentID = mask.Inc[i]; + if (componentID == otherComponentID || !_pools[componentID].Has(entity)) return false; - } } for (int i = 0, iMax = mask.ExcCount; i < iMax; i++) { int poolID = mask.Exc[i]; - if (poolID != otherPoolID && _pools[poolID].Has(entity)) - { + if (poolID != otherComponentID && _pools[poolID].Has(entity)) return false; - } } return true; } #endregion #region EntityChangedReact - void IEcsWorld.OnEntityComponentAdded(int entityID, int changedPoolID) + void IEcsWorld.OnEntityComponentAdded(int entityID, int componentID) { - var includeList = _filtersByIncludedComponents[changedPoolID]; - var excludeList = _filtersByExcludedComponents[changedPoolID]; + var includeList = _filtersByIncludedComponents[componentID]; + var excludeList = _filtersByExcludedComponents[componentID]; if (includeList != null) { @@ -224,7 +241,7 @@ namespace DCFApixels.DragonECS { foreach (var filter in excludeList) { - if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID)) + if (IsMaskCompatibleWithout(filter.Mask, entityID, componentID)) { filter.Remove(entityID); } @@ -260,13 +277,19 @@ namespace DCFApixels.DragonECS } #endregion - #region NewEntity + #region NewEntity/DelEntity public ent NewEntity() { int entid = _entityDispenser.GetFree(); - if(_gens.Length < entid) Array.Resize(ref _gens, _gens.Length << 1); + _entities.Add(entid); + if (_gens.Length < entid) Array.Resize(ref _gens, _gens.Length << 1); return new ent(entid, _gens[entid]++, id); } + public void DelEntity(int entityID) + { + _entityDispenser.Release(entityID); + _entities.Remove(entityID); + } #endregion #region Destroy diff --git a/test/SharedData.cs b/test/SharedData.cs index 3fc449e..ba64396 100644 --- a/test/SharedData.cs +++ b/test/SharedData.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; namespace DCFApixels.DragonECS diff --git a/test/TestSystem.cs b/test/TestSystem.cs index 149a958..fedd9e9 100644 --- a/test/TestSystem.cs +++ b/test/TestSystem.cs @@ -14,33 +14,41 @@ namespace DCFApixels.DragonECS public void Init(EcsSession session) { - var x1 = _world.GetFilter>(); - var x2 = _world.GetFilter>(); - var x3 = _world.GetFilter>(); - var x4 = _world.GetFilter>(); - var x5 = _world.GetFilter>(); - - int has1 = x1.GetHashCode(); - int has2 = x2.GetHashCode(); - int has3 = x3.GetHashCode(); - int has4 = x4.GetHashCode(); - int has5 = x5.GetHashCode(); - - Debug.Log("1 " + has1); - Debug.Log("2 " + has2); - Debug.Log("3 " + has3); - Debug.Log("4 " + has4); - Debug.Log("5 " + has5); + //var x1 = _world.GetFilter>(); + //var x2 = _world.GetFilter>(); + //var x3 = _world.GetFilter>(); + //var x4 = _world.GetFilter>(); + //var x5 = _world.GetFilter>(); + // + //int has1 = x1.GetHashCode(); + //int has2 = x2.GetHashCode(); + //int has3 = x3.GetHashCode(); + //int has4 = x4.GetHashCode(); + //int has5 = x5.GetHashCode(); + // + //Debug.Log("1 " + has1); + //Debug.Log("2 " + has2); + //Debug.Log("3 " + has3); + //Debug.Log("4 " + has4); + //Debug.Log("5 " + has5); var e = _world.NewEntity(); e.Write().position = Vector3.zero; + e.Write().value = Vector3.one; e.Write().Ref = _sharedData.view1; e.Write(); - e = _world.NewEntity(); - e.Write().position = Vector3.zero; - e.Write().value = Vector3.one; - e.Write().Ref = _sharedData.view2; - e.Write(); + var e2 = _world.NewEntity(); + e2.Write().position = Vector3.zero; + e2.Write().value = Vector3.zero; + e2.Write().Ref = _sharedData.view2; + e2.Write(); + + var x1 = _world.GetFilter>(); + + bool bb = _world.IsMaskCompatible(x1.Mask, e.id); + //has1 = x1.GetHashCode(); + + } } } diff --git a/test/VelocitySystem.cs b/test/VelocitySystem.cs index ebd3b23..d129cf8 100644 --- a/test/VelocitySystem.cs +++ b/test/VelocitySystem.cs @@ -12,6 +12,7 @@ namespace DCFApixels.DragonECS public void Run(EcsSession session) { + var x = _world.GetFilter>(); foreach (var item in _world.GetFilter>().Entities) { item.Write().position += item.Read().value * Time.deltaTime;