mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
update
remove "pipeline" argument from base processes add PoolsMediator update component mask
This commit is contained in:
parent
cf18d104f8
commit
6e16e2962e
@ -7,19 +7,19 @@ namespace DCFApixels.DragonECS
|
||||
#region Interfaces
|
||||
public interface IEcsPreInitProcess : IEcsProcess
|
||||
{
|
||||
void PreInit(EcsPipeline pipeline);
|
||||
void PreInit();
|
||||
}
|
||||
public interface IEcsInitProcess : IEcsProcess
|
||||
{
|
||||
void Init(EcsPipeline pipeline);
|
||||
void Init();
|
||||
}
|
||||
public interface IEcsRunProcess : IEcsProcess
|
||||
{
|
||||
void Run(EcsPipeline pipeline);
|
||||
void Run();
|
||||
}
|
||||
public interface IEcsDestroyProcess : IEcsProcess
|
||||
{
|
||||
void Destroy(EcsPipeline pipeline);
|
||||
void Destroy();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -40,7 +40,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public void PreInit(EcsPipeline pipeline)
|
||||
public void PreInit()
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||
@ -48,7 +48,7 @@ namespace DCFApixels.DragonECS
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
targets[i].PreInit(pipeline);
|
||||
targets[i].PreInit();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -62,7 +62,7 @@ namespace DCFApixels.DragonECS
|
||||
#else
|
||||
foreach (var item in targets)
|
||||
{
|
||||
try { item.PreInit(pipeline); }
|
||||
try { item.PreInit(); }
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
@ -88,7 +88,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public void Init(EcsPipeline pipeline)
|
||||
public void Init()
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||
@ -96,7 +96,7 @@ namespace DCFApixels.DragonECS
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
targets[i].Init(pipeline);
|
||||
targets[i].Init();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -110,7 +110,7 @@ namespace DCFApixels.DragonECS
|
||||
#else
|
||||
foreach (var item in targets)
|
||||
{
|
||||
try { item.Init(pipeline); }
|
||||
try { item.Init(); }
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
@ -136,7 +136,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public void Run(EcsPipeline pipeline)
|
||||
public void Run()
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||
@ -144,7 +144,7 @@ namespace DCFApixels.DragonECS
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
targets[i].Run(pipeline);
|
||||
targets[i].Run();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -158,7 +158,7 @@ namespace DCFApixels.DragonECS
|
||||
#else
|
||||
foreach (var item in targets)
|
||||
{
|
||||
try { item.Run(pipeline); }
|
||||
try { item.Run(); }
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
@ -184,7 +184,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public void Destroy(EcsPipeline pipeline)
|
||||
public void Destroy()
|
||||
{
|
||||
#if DEBUG && !DISABLE_DEBUG
|
||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||
@ -192,7 +192,7 @@ namespace DCFApixels.DragonECS
|
||||
_markers[i].Begin();
|
||||
try
|
||||
{
|
||||
targets[i].Destroy(pipeline);
|
||||
targets[i].Destroy();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -206,7 +206,7 @@ namespace DCFApixels.DragonECS
|
||||
#else
|
||||
foreach (var item in targets)
|
||||
{
|
||||
try { item.Destroy(pipeline); }
|
||||
try { item.Destroy(); }
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DISABLE_CATH_EXCEPTIONS
|
||||
|
@ -102,32 +102,36 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public class InjectSystemBase { }
|
||||
[DebugHide, DebugColor(DebugColor.Gray)]
|
||||
public class InjectSystem<T> : InjectSystemBase, IEcsPreInitProcess, IEcsInject<PreInitInjectController>, IEcsPreInitInjectProcess
|
||||
public class InjectSystem<T> : InjectSystemBase, IEcsInject<EcsPipeline>, IEcsPreInitProcess, IEcsInject<PreInitInjectController>, IEcsPreInitInjectProcess
|
||||
{
|
||||
private T _injectedData;
|
||||
private EcsPipeline _pipeline;
|
||||
void IEcsInject<EcsPipeline>.Inject(EcsPipeline obj) => _pipeline = obj;
|
||||
private PreInitInjectController _injectController;
|
||||
void IEcsInject<PreInitInjectController>.Inject(PreInitInjectController obj) => _injectController = obj;
|
||||
|
||||
private T _injectedData;
|
||||
|
||||
public InjectSystem(T injectedData)
|
||||
{
|
||||
if (injectedData == null) Throw.ArgumentNull();
|
||||
_injectedData = injectedData;
|
||||
}
|
||||
public void PreInit(EcsPipeline pipeline)
|
||||
public void PreInit()
|
||||
{
|
||||
if (_injectedData == null) return;
|
||||
if (_injectController == null)
|
||||
{
|
||||
_injectController = new PreInitInjectController(pipeline);
|
||||
var injectMapRunner = pipeline.GetRunner<IEcsInject<PreInitInjectController>>();
|
||||
pipeline.GetRunner<IEcsPreInitInjectProcess>().OnPreInitInjectionBefore();
|
||||
_injectController = new PreInitInjectController(_pipeline);
|
||||
var injectMapRunner = _pipeline.GetRunner<IEcsInject<PreInitInjectController>>();
|
||||
_pipeline.GetRunner<IEcsPreInitInjectProcess>().OnPreInitInjectionBefore();
|
||||
injectMapRunner.Inject(_injectController);
|
||||
}
|
||||
var injectRunnerGeneric = pipeline.GetRunner<IEcsInject<T>>();
|
||||
var injectRunnerGeneric = _pipeline.GetRunner<IEcsInject<T>>();
|
||||
injectRunnerGeneric.Inject(_injectedData);
|
||||
if (_injectController.OnInject())
|
||||
{
|
||||
_injectController.Destroy();
|
||||
var injectCallbacksRunner = pipeline.GetRunner<IEcsPreInitInjectProcess>();
|
||||
var injectCallbacksRunner = _pipeline.GetRunner<IEcsPreInitInjectProcess>();
|
||||
injectCallbacksRunner.OnPreInitInjectionAfter();
|
||||
EcsRunner.Destroy(injectCallbacksRunner);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
|
||||
public void Inject(EcsWorld obj) => _worlds.Add(obj);
|
||||
public void Run(EcsPipeline pipeline)
|
||||
public void Run()
|
||||
{
|
||||
foreach (var world in _worlds)
|
||||
{
|
||||
@ -29,6 +29,7 @@ namespace DCFApixels.DragonECS
|
||||
public class DeleteOneFrameComponentSystem<TComponent> : IEcsRunProcess, IEcsInject<EcsWorld>
|
||||
where TComponent : struct, IEcsComponent
|
||||
{
|
||||
public EcsPipeline pipeline { get; set; }
|
||||
private sealed class Aspect : EcsAspect
|
||||
{
|
||||
public EcsPool<TComponent> pool;
|
||||
@ -36,7 +37,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
|
||||
public void Inject(EcsWorld obj) => _worlds.Add(obj);
|
||||
public void Run(EcsPipeline pipeline)
|
||||
public void Run()
|
||||
{
|
||||
for (int i = 0, iMax = _worlds.Count; i < iMax; i++)
|
||||
{
|
||||
|
@ -67,10 +67,10 @@ namespace DCFApixels.DragonECS
|
||||
ecsPipelineInjectRunner.Inject(this);
|
||||
EcsRunner.Destroy(ecsPipelineInjectRunner);
|
||||
var preInitRunner = GetRunner<IEcsPreInitProcess>();
|
||||
preInitRunner.PreInit(this);
|
||||
preInitRunner.PreInit();
|
||||
EcsRunner.Destroy(preInitRunner);
|
||||
var initRunner = GetRunner<IEcsInitProcess>();
|
||||
initRunner.Init(this);
|
||||
initRunner.Init();
|
||||
EcsRunner.Destroy(initRunner);
|
||||
|
||||
_runRunnerCache = GetRunner<IEcsRunProcess>();
|
||||
@ -85,7 +85,7 @@ namespace DCFApixels.DragonECS
|
||||
if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run));
|
||||
if (_isDestoryed) Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run));
|
||||
#endif
|
||||
_runRunnerCache.Run(this);
|
||||
_runRunnerCache.Run();
|
||||
}
|
||||
public void Destroy()
|
||||
{
|
||||
@ -98,7 +98,7 @@ namespace DCFApixels.DragonECS
|
||||
return;
|
||||
}
|
||||
_isDestoryed = true;
|
||||
GetRunner<IEcsDestroyProcess>().Destroy(this);
|
||||
GetRunner<IEcsDestroyProcess>().Destroy();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -3,6 +3,7 @@ using DCFApixels.DragonECS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static DCFApixels.DragonECS.EcsWorld;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -32,6 +33,8 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
internal int[][] _entitiesComponentMasks;
|
||||
|
||||
private readonly PoolsMediator _poolsMediator;
|
||||
|
||||
#region Properties
|
||||
public bool IsDestroyed => _isDestroyed;
|
||||
public int Count => _entitiesCount;
|
||||
@ -47,6 +50,8 @@ namespace DCFApixels.DragonECS
|
||||
public EcsWorld() : this(true) { }
|
||||
internal EcsWorld(bool isIndexable)
|
||||
{
|
||||
_poolsMediator = new PoolsMediator(this);
|
||||
|
||||
_entitesCapacity = 512;
|
||||
|
||||
if (isIndexable)
|
||||
@ -268,20 +273,18 @@ namespace DCFApixels.DragonECS
|
||||
//public void CloneEntity(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
||||
#endregion
|
||||
|
||||
#region Components Increment
|
||||
#region Components Register
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void IncrementEntityComponentCount(int entityID, int componentID)
|
||||
private void RegisterEntityComponent(int entityID, int componentTypeID, EcsMaskBit maskBit)
|
||||
{
|
||||
_componentCounts[entityID]++;
|
||||
EcsMaskBit bit = EcsMaskBit.FromID(componentID);
|
||||
_entitiesComponentMasks[entityID][bit.chankIndex] |= bit.mask;
|
||||
_entitiesComponentMasks[entityID][maskBit.chankIndex] |= maskBit.mask;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void DecrementEntityComponentCount(int entityID, int componentID)
|
||||
private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskBit maskBit)
|
||||
{
|
||||
var count = --_componentCounts[entityID];
|
||||
EcsMaskBit bit = EcsMaskBit.FromID(componentID);
|
||||
_entitiesComponentMasks[entityID][bit.chankIndex] &= ~bit.mask;
|
||||
_entitiesComponentMasks[entityID][maskBit.chankIndex] &= ~maskBit.mask;
|
||||
|
||||
if (count == 0 && _allEntites.Has(entityID))
|
||||
DelEntity(entityID);
|
||||
@ -382,6 +385,34 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public readonly struct PoolsMediator
|
||||
{
|
||||
private readonly EcsWorld _world;
|
||||
public PoolsMediator(EcsWorld world)
|
||||
{
|
||||
if (world == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (world._poolsMediator._world != null)
|
||||
{
|
||||
throw new MethodAccessException("Нельзя создавать вручную");
|
||||
}
|
||||
_world = world;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void RegisterComponent(int entityID, int componentTypeID, EcsMaskBit maskBit)
|
||||
{
|
||||
_world.RegisterEntityComponent(entityID, componentTypeID, maskBit);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void UnregisterComponent(int entityID, int componentTypeID, EcsMaskBit maskBit)
|
||||
{
|
||||
_world.UnregisterEntityComponent(entityID, componentTypeID, maskBit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Callbacks Interface
|
||||
@ -433,9 +464,4 @@ namespace DCFApixels.DragonECS
|
||||
public static entlong ToEntityLong(this int self, EcsWorld world) => world.GetEntityLong(self);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public class PoolsController
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -77,15 +77,15 @@ namespace DCFApixels.DragonECS
|
||||
Type componentType = typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0];
|
||||
int componentTypeCode = EcsTypeCode.Get(componentType);
|
||||
|
||||
if (_componentIds.TryGetValue(componentTypeCode, out int componentID))
|
||||
if (_componentIds.TryGetValue(componentTypeCode, out int componentTypeID))
|
||||
{
|
||||
_poolIds[poolTypeCode] = componentID;
|
||||
_poolIds[poolTypeCode] = componentTypeID;
|
||||
}
|
||||
else
|
||||
{
|
||||
componentID = _poolsCount++;
|
||||
_poolIds[poolTypeCode] = componentID;
|
||||
_componentIds[componentTypeCode] = componentID;
|
||||
componentTypeID = _poolsCount++;
|
||||
_poolIds[poolTypeCode] = componentTypeID;
|
||||
_componentIds[componentTypeCode] = componentTypeID;
|
||||
}
|
||||
|
||||
if (_poolsCount >= _pools.Length)
|
||||
@ -98,13 +98,13 @@ namespace DCFApixels.DragonECS
|
||||
Array.Resize(ref _entitiesComponentMasks[i], _pools.Length / 32 + 1);
|
||||
}
|
||||
|
||||
if (_pools[componentID] == _nullPool)
|
||||
if (_pools[componentTypeID] == _nullPool)
|
||||
{
|
||||
var pool = new TPool();
|
||||
_pools[componentID] = pool;
|
||||
pool.OnInit(this, componentID);
|
||||
_pools[componentTypeID] = pool;
|
||||
pool.OnInit(this, _poolsMediator, componentTypeID);
|
||||
}
|
||||
return (TPool)_pools[componentID];
|
||||
return (TPool)_pools[componentTypeID];
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ namespace DCFApixels.DragonECS
|
||||
where T : IEcsHybridComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private int _componentID;
|
||||
private int _componentTypeID;
|
||||
private EcsMaskBit _maskBit;
|
||||
|
||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||
private T[] _items; //dense
|
||||
@ -32,10 +33,12 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
||||
|
||||
private EcsWorld.PoolsMediator _mediator;
|
||||
|
||||
#region Properites
|
||||
public int Count => _itemsCount;
|
||||
public int Capacity => _items.Length;
|
||||
public int ComponentID => _componentID;
|
||||
public int ComponentID => _componentTypeID;
|
||||
public Type ComponentType => typeof(T);
|
||||
public EcsWorld World => _source;
|
||||
#endregion
|
||||
@ -65,7 +68,7 @@ namespace DCFApixels.DragonECS
|
||||
Array.Resize(ref _entities, _items.Length);
|
||||
}
|
||||
}
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
if(isMain)
|
||||
component.OnAddToPool(_source.GetEntityLong(entityID));
|
||||
@ -126,7 +129,7 @@ namespace DCFApixels.DragonECS
|
||||
_mapping[entityID] = 0;
|
||||
_entities[itemIndex] = 0;
|
||||
_itemsCount--;
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
}
|
||||
public void Del(int entityID)
|
||||
@ -167,10 +170,12 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Callbacks
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
||||
{
|
||||
_source = world;
|
||||
_componentID = componentID;
|
||||
_mediator = mediator;
|
||||
_componentTypeID = componentTypeID;
|
||||
_maskBit = EcsMaskBit.FromID(componentTypeID);
|
||||
|
||||
const int capacity = 512;
|
||||
|
||||
@ -286,16 +291,15 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
|
||||
public partial class EcsWorld
|
||||
public abstract partial class EcsWorld
|
||||
{
|
||||
private Dictionary<Type, HybridMapping> _mappings = new Dictionary<Type, HybridMapping>();
|
||||
|
||||
private Dictionary<Type, HybridMapping> _hybridMapping = new Dictionary<Type, HybridMapping>();
|
||||
internal HybridMapping GetHybridMapping(Type type)
|
||||
{
|
||||
if(!_mappings.TryGetValue(type, out HybridMapping mapping))
|
||||
if(!_hybridMapping.TryGetValue(type, out HybridMapping mapping))
|
||||
{
|
||||
mapping = new HybridMapping(this, type);
|
||||
_mappings.Add(type, mapping);
|
||||
_hybridMapping.Add(type, mapping);
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
@ -313,7 +317,6 @@ namespace DCFApixels.DragonECS
|
||||
private static Type hybridPoolType = typeof(EcsHybridPool<>);
|
||||
private static MethodInfo getHybridPoolMethod = typeof(EcsHybridPoolExtensions).GetMethod($"{nameof(EcsHybridPoolExtensions.GetPool)}", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
|
||||
private static HashSet<Type> _hybridComponents = new HashSet<Type>();
|
||||
static HybridMapping()
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ namespace DCFApixels.DragonECS
|
||||
where T : struct, IEcsComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private int _componentID;
|
||||
private int _componentTypeID;
|
||||
private EcsMaskBit _maskBit;
|
||||
|
||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||
@ -25,10 +25,12 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
||||
|
||||
private EcsWorld.PoolsMediator _mediator;
|
||||
|
||||
#region Properites
|
||||
public int Count => _itemsCount;
|
||||
public int Capacity => _items.Length;
|
||||
public int ComponentID => _componentID;
|
||||
public int ComponentID => _componentTypeID;
|
||||
public Type ComponentType => typeof(T);
|
||||
public EcsWorld World => _source;
|
||||
#endregion
|
||||
@ -51,7 +53,7 @@ namespace DCFApixels.DragonECS
|
||||
if (itemIndex >= _items.Length)
|
||||
Array.Resize(ref _items, _items.Length << 1);
|
||||
}
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnAddAndGet(entityID);
|
||||
return ref _items[itemIndex];
|
||||
}
|
||||
@ -88,7 +90,7 @@ namespace DCFApixels.DragonECS
|
||||
if (itemIndex >= _items.Length)
|
||||
Array.Resize(ref _items, _items.Length << 1);
|
||||
}
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
}
|
||||
_listeners.InvokeOnGet(entityID);
|
||||
@ -111,7 +113,7 @@ namespace DCFApixels.DragonECS
|
||||
_recycledItems[_recycledItemsCount++] = itemIndex;
|
||||
_mapping[entityID] = 0;
|
||||
_itemsCount--;
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
}
|
||||
public void TryDel(int entityID)
|
||||
@ -135,12 +137,12 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Callbacks
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
||||
{
|
||||
_source = world;
|
||||
_componentID = componentID;
|
||||
|
||||
_maskBit = EcsMaskBit.FromID(componentID);
|
||||
_mediator = mediator;
|
||||
_componentTypeID = componentTypeID;
|
||||
_maskBit = EcsMaskBit.FromID(componentTypeID);
|
||||
|
||||
const int capacity = 512;
|
||||
|
||||
|
@ -49,7 +49,7 @@ namespace DCFApixels.DragonECS
|
||||
/// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary>
|
||||
public interface IEcsPoolImplementation : IEcsPool
|
||||
{
|
||||
void OnInit(EcsWorld world, int componentID);
|
||||
void OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID);
|
||||
void OnWorldResize(int newSize);
|
||||
void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer);
|
||||
void OnWorldDestroy();
|
||||
@ -71,17 +71,6 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public static class IEcsPoolImplementationExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void IncrementEntityComponentCount<T>(this IEcsPoolImplementation<T> self, int entityID, int componentID)
|
||||
{
|
||||
self.World.IncrementEntityComponentCount(entityID, componentID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void DecrementEntityComponentCount<T>(this IEcsPoolImplementation<T> self, int entityID, int componentID)
|
||||
{
|
||||
self.World.DecrementEntityComponentCount(entityID, componentID);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNullOrDummy(this IEcsPool self)
|
||||
{
|
||||
@ -116,7 +105,7 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Callbacks
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) { }
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) { }
|
||||
void IEcsPoolImplementation.OnWorldDestroy() { }
|
||||
void IEcsPoolImplementation.OnWorldResize(int newSize) { }
|
||||
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||
|
@ -10,7 +10,8 @@ namespace DCFApixels.DragonECS
|
||||
where T : struct, IEcsTagComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private int _componentID;
|
||||
private int _componentTypeID;
|
||||
private EcsMaskBit _maskBit;
|
||||
|
||||
private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||
private int _count;
|
||||
@ -18,8 +19,9 @@ namespace DCFApixels.DragonECS
|
||||
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
||||
|
||||
private T _fakeComponent;
|
||||
private EcsWorld.PoolsMediator _mediator;
|
||||
|
||||
|
||||
#region Constructors
|
||||
private static bool _isInvalidType;
|
||||
static EcsTagPool()
|
||||
{
|
||||
@ -30,11 +32,12 @@ namespace DCFApixels.DragonECS
|
||||
if (_isInvalidType)
|
||||
throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properites
|
||||
public int Count => _count;
|
||||
int IEcsPool.Capacity => -1;
|
||||
public int ComponentID => _componentID;
|
||||
public int ComponentID => _componentTypeID;
|
||||
public Type ComponentType => typeof(T);
|
||||
public EcsWorld World => _source;
|
||||
#endregion
|
||||
@ -47,7 +50,7 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
_count++;
|
||||
_mapping[entityID] = true;
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
}
|
||||
public void TryAdd(int entityID)
|
||||
@ -56,7 +59,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_count++;
|
||||
_mapping[entityID] = true;
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
}
|
||||
}
|
||||
@ -72,7 +75,7 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
_mapping[entityID] = false;
|
||||
_count--;
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
}
|
||||
public void TryDel(int entityID)
|
||||
@ -116,10 +119,12 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Callbacks
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
||||
{
|
||||
_source = world;
|
||||
_componentID = componentID;
|
||||
_mediator = mediator;
|
||||
_componentTypeID = componentTypeID;
|
||||
_maskBit = EcsMaskBit.FromID(componentTypeID);
|
||||
|
||||
_mapping = new bool[world.Capacity];
|
||||
_count = 0;
|
||||
|
@ -1,332 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
/// <summary>Pool for IEcsComponent components</summary>
|
||||
public sealed class EcsTestPool<T> : IEcsPoolImplementation<T>, IEcsStructPool<T>, IEnumerable<T> //IEnumerable<T> - IntelliSense hack
|
||||
where T : struct, IEcsTestComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private int _componentID;
|
||||
|
||||
|
||||
public const int MIN_CAPACITY_BITS_OFFSET = 4;
|
||||
public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET;
|
||||
private const int EMPTY = -1;
|
||||
|
||||
private int[] _buckets = Array.Empty<int>();
|
||||
private Entry[] _entries = Array.Empty<Entry>();
|
||||
|
||||
private int _count;
|
||||
|
||||
private int _freeList;
|
||||
private int _freeCount;
|
||||
|
||||
private int _modBitMask;
|
||||
|
||||
|
||||
private IEcsComponentReset<T> _componentResetHandler = EcsComponentResetHandler<T>.instance;
|
||||
private IEcsComponentCopy<T> _componentCopyHandler = EcsComponentCopyHandler<T>.instance;
|
||||
|
||||
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
||||
|
||||
#region Properites
|
||||
public int Count => _count;
|
||||
public int Capacity => _entries.Length;
|
||||
public int ComponentID => _componentID;
|
||||
public Type ComponentType => typeof(T);
|
||||
public EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public void Copy(int fromEntityID, int toEntityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
|
||||
#endif
|
||||
_componentCopyHandler.Copy(ref Get(fromEntityID), ref TryAddOrGet(toEntityID));
|
||||
}
|
||||
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
|
||||
#endif
|
||||
_componentCopyHandler.Copy(ref Get(fromEntityID), ref toWorld.GetPool<T>().TryAddOrGet(toEntityID));
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Callbacks
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||
{
|
||||
_source = world;
|
||||
_componentID = componentID;
|
||||
|
||||
int minCapacity = 512;
|
||||
minCapacity = NormalizeCapacity(minCapacity);
|
||||
_buckets = new int[minCapacity];
|
||||
for (int i = 0; i < minCapacity; i++)
|
||||
_buckets[i] = EMPTY;
|
||||
_entries = new Entry[minCapacity];
|
||||
_modBitMask = (minCapacity - 1) & 0x7FFFFFFF;
|
||||
}
|
||||
void IEcsPoolImplementation.OnWorldResize(int newSize) { }
|
||||
void IEcsPoolImplementation.OnWorldDestroy() { }
|
||||
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
|
||||
{
|
||||
foreach (var entityID in buffer)
|
||||
TryDel(entityID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID) = (T)dataRaw;
|
||||
object IEcsPool.GetRaw(int entityID) => Read(entityID);
|
||||
void IEcsPool.SetRaw(int entityID, object dataRaw) => Get(entityID) = (T)dataRaw;
|
||||
ref readonly T IEcsStructPool<T>.Read(int entityID) => ref Read(entityID);
|
||||
ref T IEcsStructPool<T>.Get(int entityID) => ref Get(entityID);
|
||||
#endregion
|
||||
|
||||
#region Listeners
|
||||
public void AddListener(IEcsPoolEventListener listener)
|
||||
{
|
||||
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||
_listeners.Add(listener);
|
||||
}
|
||||
public void RemoveListener(IEcsPoolEventListener listener)
|
||||
{
|
||||
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||
_listeners.Remove(listener);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerator - IntelliSense hack
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
|
||||
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
|
||||
#region Find/Insert/Remove
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int FindEntry(long x, long y)
|
||||
{
|
||||
return FindEntry(x << 32 | y);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int FindEntry(long key)
|
||||
{
|
||||
for (int i = _buckets[unchecked((int)key & _modBitMask)]; i >= 0; i = _entries[i].next)
|
||||
if (_entries[i].key == key) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Has(int entityID) => Has(entityID, entityID);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool Has(long x, long y) => Has(x << 32 | y);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool Has(long key) {
|
||||
for (int i = _buckets[unchecked((int)key & _modBitMask)]; i >= 0; i = _entries[i].next)
|
||||
if (_entries[i].key == key) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public ref T Add(int entityID) => ref Add(entityID, entityID);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ref T Add(long x, long y) => ref Add(x << 32 | y);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ref T Add(long key)
|
||||
{
|
||||
int entityID = unchecked((int)key);
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (Has(key: key)) EcsPoolThrowHalper.ThrowAlreadyHasComponent<T>(entityID);
|
||||
#endif
|
||||
|
||||
int index;
|
||||
if (_freeCount > 0)
|
||||
{
|
||||
index = _freeList;
|
||||
_freeList = _entries[index].next;
|
||||
_freeCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_count == _entries.Length)
|
||||
Resize();
|
||||
index = _count++;
|
||||
}
|
||||
int targetBucket = unchecked((int)key & _modBitMask);
|
||||
|
||||
ref var entry = ref _entries[index];
|
||||
entry.next = _buckets[targetBucket];
|
||||
entry.key = key;
|
||||
entry.value = default;
|
||||
_buckets[targetBucket] = index;
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnAddAndGet(entityID);
|
||||
return ref entry.value;
|
||||
}
|
||||
public ref T TryAddOrGet(int entityID)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Get(int entityID) => ref Get(entityID, entityID);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ref T Get(long x, long y) => ref Get(x << 32 | y);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ref T Get(long key)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(key: key)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(unchecked((int)key));
|
||||
#endif
|
||||
_listeners.InvokeOnGet(unchecked((int)key));
|
||||
//return ref _entries[FindEntry(key)].value;
|
||||
|
||||
for (int i = _buckets[unchecked((int)key & _modBitMask)]; i >= 0; i = _entries[i].next)
|
||||
if (_entries[i].key == key) return ref _entries[i].value; // return i;
|
||||
|
||||
#pragma warning disable CS0251 // Èíäåêñàöèÿ ìàññèâà ñ îòðèöàòåëüíûì èíäåêñîì
|
||||
return ref _entries[-1].value; //ïðè íîðìàëüíîé ðàáîòå ýòî íåäîñòèæèìûé êîä.
|
||||
#pragma warning restore CS0251 // Èíäåêñàöèÿ ìàññèâà ñ îòðèöàòåëüíûì èíäåêñîì
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(int entityID) => ref Read(entityID, entityID);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(long x, long y) => ref Read(x << 32 | y);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(long key)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(key: key)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(unchecked((int)key));
|
||||
#endif
|
||||
return ref _entries[FindEntry(key)].value;
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Del(int entityID) => Del(entityID, entityID);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Del(long keyX, long keyY) => Del(keyX + (keyY << 32));
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Del(long key)
|
||||
{
|
||||
int entityID = unchecked((int)key);
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(key: key)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
|
||||
#endif
|
||||
int bucket = unchecked((int)key & _modBitMask);
|
||||
int last = -1;
|
||||
for (int i = _buckets[bucket]; i >= 0; last = i, i = _entries[i].next)
|
||||
{
|
||||
if (_entries[i].key == key)
|
||||
{
|
||||
if (last < 0)
|
||||
{
|
||||
_buckets[bucket] = _entries[i].next;
|
||||
}
|
||||
else
|
||||
{
|
||||
_entries[last].next = _entries[i].next;
|
||||
}
|
||||
_entries[i].next = _freeList;
|
||||
_entries[i].key = -1;
|
||||
//_entries[i].value = default;
|
||||
_componentResetHandler.Reset(ref _entries[i].value);
|
||||
_freeList = i;
|
||||
_freeCount++;
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void TryDel(int entityID)
|
||||
{
|
||||
if (Has(entityID)) Del(entityID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Resize
|
||||
private void Resize()
|
||||
{
|
||||
int newSize = _buckets.Length << 1;
|
||||
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
||||
|
||||
Contract.Assert(newSize >= _entries.Length);
|
||||
int[] newBuckets = new int[newSize];
|
||||
for (int i = 0; i < newBuckets.Length; i++)
|
||||
newBuckets[i] = EMPTY;
|
||||
|
||||
Entry[] newEntries = new Entry[newSize];
|
||||
Array.Copy(_entries, 0, newEntries, 0, _count);
|
||||
for (int i = 0; i < _count; i++)
|
||||
{
|
||||
if (newEntries[i].key >= 0)
|
||||
{
|
||||
int bucket = unchecked((int)newEntries[i].key & _modBitMask);
|
||||
newEntries[i].next = newBuckets[bucket];
|
||||
newBuckets[bucket] = i;
|
||||
}
|
||||
}
|
||||
_buckets = newBuckets;
|
||||
_entries = newEntries;
|
||||
}
|
||||
|
||||
private int NormalizeCapacity(int capacity)
|
||||
{
|
||||
int result = MIN_CAPACITY;
|
||||
while (result < capacity) result <<= 1;
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
private struct Entry
|
||||
{
|
||||
public int next; // Index of next entry, -1 if last
|
||||
public long key;
|
||||
public T value;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
/// <summary>Standard component</summary>
|
||||
public interface IEcsTestComponent { }
|
||||
public static class EcsTestPoolExt
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static EcsTestPool<TComponent> GetPool<TComponent>(this EcsWorld self) where TComponent : struct, IEcsTestComponent
|
||||
{
|
||||
return self.GetPool<EcsTestPool<TComponent>>();
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static EcsTestPool<TComponent> GetPoolUnchecked<TComponent>(this EcsWorld self) where TComponent : struct, IEcsTestComponent
|
||||
{
|
||||
return self.GetPoolUnchecked<EcsTestPool<TComponent>>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static EcsTestPool<TComponent> Include<TComponent>(this EcsAspectBuilderBase self) where TComponent : struct, IEcsTestComponent
|
||||
{
|
||||
return self.Include<EcsTestPool<TComponent>>();
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static EcsTestPool<TComponent> Exclude<TComponent>(this EcsAspectBuilderBase self) where TComponent : struct, IEcsTestComponent
|
||||
{
|
||||
return self.Exclude<EcsTestPool<TComponent>>();
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static EcsTestPool<TComponent> Optional<TComponent>(this EcsAspectBuilderBase self) where TComponent : struct, IEcsTestComponent
|
||||
{
|
||||
return self.Optional<EcsTestPool<TComponent>>();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user