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
|
#region Interfaces
|
||||||
public interface IEcsPreInitProcess : IEcsProcess
|
public interface IEcsPreInitProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void PreInit(EcsPipeline pipeline);
|
void PreInit();
|
||||||
}
|
}
|
||||||
public interface IEcsInitProcess : IEcsProcess
|
public interface IEcsInitProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Init(EcsPipeline pipeline);
|
void Init();
|
||||||
}
|
}
|
||||||
public interface IEcsRunProcess : IEcsProcess
|
public interface IEcsRunProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Run(EcsPipeline pipeline);
|
void Run();
|
||||||
}
|
}
|
||||||
public interface IEcsDestroyProcess : IEcsProcess
|
public interface IEcsDestroyProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Destroy(EcsPipeline pipeline);
|
void Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -40,7 +40,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public void PreInit(EcsPipeline pipeline)
|
public void PreInit()
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||||
@ -48,7 +48,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_markers[i].Begin();
|
_markers[i].Begin();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
targets[i].PreInit(pipeline);
|
targets[i].PreInit();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#else
|
#else
|
||||||
foreach (var item in targets)
|
foreach (var item in targets)
|
||||||
{
|
{
|
||||||
try { item.PreInit(pipeline); }
|
try { item.PreInit(); }
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
#if DISABLE_CATH_EXCEPTIONS
|
#if DISABLE_CATH_EXCEPTIONS
|
||||||
@ -88,7 +88,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public void Init(EcsPipeline pipeline)
|
public void Init()
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||||
@ -96,7 +96,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_markers[i].Begin();
|
_markers[i].Begin();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
targets[i].Init(pipeline);
|
targets[i].Init();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -110,7 +110,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#else
|
#else
|
||||||
foreach (var item in targets)
|
foreach (var item in targets)
|
||||||
{
|
{
|
||||||
try { item.Init(pipeline); }
|
try { item.Init(); }
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
#if DISABLE_CATH_EXCEPTIONS
|
#if DISABLE_CATH_EXCEPTIONS
|
||||||
@ -136,7 +136,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public void Run(EcsPipeline pipeline)
|
public void Run()
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||||
@ -144,7 +144,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_markers[i].Begin();
|
_markers[i].Begin();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
targets[i].Run(pipeline);
|
targets[i].Run();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -158,7 +158,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#else
|
#else
|
||||||
foreach (var item in targets)
|
foreach (var item in targets)
|
||||||
{
|
{
|
||||||
try { item.Run(pipeline); }
|
try { item.Run(); }
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
#if DISABLE_CATH_EXCEPTIONS
|
#if DISABLE_CATH_EXCEPTIONS
|
||||||
@ -184,7 +184,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public void Destroy(EcsPipeline pipeline)
|
public void Destroy()
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++)
|
||||||
@ -192,7 +192,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_markers[i].Begin();
|
_markers[i].Begin();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
targets[i].Destroy(pipeline);
|
targets[i].Destroy();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -206,7 +206,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#else
|
#else
|
||||||
foreach (var item in targets)
|
foreach (var item in targets)
|
||||||
{
|
{
|
||||||
try { item.Destroy(pipeline); }
|
try { item.Destroy(); }
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
#if DISABLE_CATH_EXCEPTIONS
|
#if DISABLE_CATH_EXCEPTIONS
|
||||||
|
@ -102,32 +102,36 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
public class InjectSystemBase { }
|
public class InjectSystemBase { }
|
||||||
[DebugHide, DebugColor(DebugColor.Gray)]
|
[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;
|
private PreInitInjectController _injectController;
|
||||||
void IEcsInject<PreInitInjectController>.Inject(PreInitInjectController obj) => _injectController = obj;
|
void IEcsInject<PreInitInjectController>.Inject(PreInitInjectController obj) => _injectController = obj;
|
||||||
|
|
||||||
|
private T _injectedData;
|
||||||
|
|
||||||
public InjectSystem(T injectedData)
|
public InjectSystem(T injectedData)
|
||||||
{
|
{
|
||||||
if (injectedData == null) Throw.ArgumentNull();
|
if (injectedData == null) Throw.ArgumentNull();
|
||||||
_injectedData = injectedData;
|
_injectedData = injectedData;
|
||||||
}
|
}
|
||||||
public void PreInit(EcsPipeline pipeline)
|
public void PreInit()
|
||||||
{
|
{
|
||||||
if (_injectedData == null) return;
|
if (_injectedData == null) return;
|
||||||
if (_injectController == null)
|
if (_injectController == null)
|
||||||
{
|
{
|
||||||
_injectController = new PreInitInjectController(pipeline);
|
_injectController = new PreInitInjectController(_pipeline);
|
||||||
var injectMapRunner = pipeline.GetRunner<IEcsInject<PreInitInjectController>>();
|
var injectMapRunner = _pipeline.GetRunner<IEcsInject<PreInitInjectController>>();
|
||||||
pipeline.GetRunner<IEcsPreInitInjectProcess>().OnPreInitInjectionBefore();
|
_pipeline.GetRunner<IEcsPreInitInjectProcess>().OnPreInitInjectionBefore();
|
||||||
injectMapRunner.Inject(_injectController);
|
injectMapRunner.Inject(_injectController);
|
||||||
}
|
}
|
||||||
var injectRunnerGeneric = pipeline.GetRunner<IEcsInject<T>>();
|
var injectRunnerGeneric = _pipeline.GetRunner<IEcsInject<T>>();
|
||||||
injectRunnerGeneric.Inject(_injectedData);
|
injectRunnerGeneric.Inject(_injectedData);
|
||||||
if (_injectController.OnInject())
|
if (_injectController.OnInject())
|
||||||
{
|
{
|
||||||
_injectController.Destroy();
|
_injectController.Destroy();
|
||||||
var injectCallbacksRunner = pipeline.GetRunner<IEcsPreInitInjectProcess>();
|
var injectCallbacksRunner = _pipeline.GetRunner<IEcsPreInitInjectProcess>();
|
||||||
injectCallbacksRunner.OnPreInitInjectionAfter();
|
injectCallbacksRunner.OnPreInitInjectionAfter();
|
||||||
EcsRunner.Destroy(injectCallbacksRunner);
|
EcsRunner.Destroy(injectCallbacksRunner);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
|
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
|
||||||
public void Inject(EcsWorld obj) => _worlds.Add(obj);
|
public void Inject(EcsWorld obj) => _worlds.Add(obj);
|
||||||
public void Run(EcsPipeline pipeline)
|
public void Run()
|
||||||
{
|
{
|
||||||
foreach (var world in _worlds)
|
foreach (var world in _worlds)
|
||||||
{
|
{
|
||||||
@ -29,6 +29,7 @@ namespace DCFApixels.DragonECS
|
|||||||
public class DeleteOneFrameComponentSystem<TComponent> : IEcsRunProcess, IEcsInject<EcsWorld>
|
public class DeleteOneFrameComponentSystem<TComponent> : IEcsRunProcess, IEcsInject<EcsWorld>
|
||||||
where TComponent : struct, IEcsComponent
|
where TComponent : struct, IEcsComponent
|
||||||
{
|
{
|
||||||
|
public EcsPipeline pipeline { get; set; }
|
||||||
private sealed class Aspect : EcsAspect
|
private sealed class Aspect : EcsAspect
|
||||||
{
|
{
|
||||||
public EcsPool<TComponent> pool;
|
public EcsPool<TComponent> pool;
|
||||||
@ -36,7 +37,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
|
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
|
||||||
public void Inject(EcsWorld obj) => _worlds.Add(obj);
|
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++)
|
for (int i = 0, iMax = _worlds.Count; i < iMax; i++)
|
||||||
{
|
{
|
||||||
|
@ -67,10 +67,10 @@ namespace DCFApixels.DragonECS
|
|||||||
ecsPipelineInjectRunner.Inject(this);
|
ecsPipelineInjectRunner.Inject(this);
|
||||||
EcsRunner.Destroy(ecsPipelineInjectRunner);
|
EcsRunner.Destroy(ecsPipelineInjectRunner);
|
||||||
var preInitRunner = GetRunner<IEcsPreInitProcess>();
|
var preInitRunner = GetRunner<IEcsPreInitProcess>();
|
||||||
preInitRunner.PreInit(this);
|
preInitRunner.PreInit();
|
||||||
EcsRunner.Destroy(preInitRunner);
|
EcsRunner.Destroy(preInitRunner);
|
||||||
var initRunner = GetRunner<IEcsInitProcess>();
|
var initRunner = GetRunner<IEcsInitProcess>();
|
||||||
initRunner.Init(this);
|
initRunner.Init();
|
||||||
EcsRunner.Destroy(initRunner);
|
EcsRunner.Destroy(initRunner);
|
||||||
|
|
||||||
_runRunnerCache = GetRunner<IEcsRunProcess>();
|
_runRunnerCache = GetRunner<IEcsRunProcess>();
|
||||||
@ -85,7 +85,7 @@ namespace DCFApixels.DragonECS
|
|||||||
if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run));
|
if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run));
|
||||||
if (_isDestoryed) Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run));
|
if (_isDestoryed) Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run));
|
||||||
#endif
|
#endif
|
||||||
_runRunnerCache.Run(this);
|
_runRunnerCache.Run();
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
@ -98,7 +98,7 @@ namespace DCFApixels.DragonECS
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_isDestoryed = true;
|
_isDestoryed = true;
|
||||||
GetRunner<IEcsDestroyProcess>().Destroy(this);
|
GetRunner<IEcsDestroyProcess>().Destroy();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using DCFApixels.DragonECS.Utils;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using static DCFApixels.DragonECS.EcsWorld;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
@ -32,6 +33,8 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
internal int[][] _entitiesComponentMasks;
|
internal int[][] _entitiesComponentMasks;
|
||||||
|
|
||||||
|
private readonly PoolsMediator _poolsMediator;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public bool IsDestroyed => _isDestroyed;
|
public bool IsDestroyed => _isDestroyed;
|
||||||
public int Count => _entitiesCount;
|
public int Count => _entitiesCount;
|
||||||
@ -47,6 +50,8 @@ namespace DCFApixels.DragonECS
|
|||||||
public EcsWorld() : this(true) { }
|
public EcsWorld() : this(true) { }
|
||||||
internal EcsWorld(bool isIndexable)
|
internal EcsWorld(bool isIndexable)
|
||||||
{
|
{
|
||||||
|
_poolsMediator = new PoolsMediator(this);
|
||||||
|
|
||||||
_entitesCapacity = 512;
|
_entitesCapacity = 512;
|
||||||
|
|
||||||
if (isIndexable)
|
if (isIndexable)
|
||||||
@ -268,20 +273,18 @@ namespace DCFApixels.DragonECS
|
|||||||
//public void CloneEntity(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
//public void CloneEntity(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Components Increment
|
#region Components Register
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal void IncrementEntityComponentCount(int entityID, int componentID)
|
private void RegisterEntityComponent(int entityID, int componentTypeID, EcsMaskBit maskBit)
|
||||||
{
|
{
|
||||||
_componentCounts[entityID]++;
|
_componentCounts[entityID]++;
|
||||||
EcsMaskBit bit = EcsMaskBit.FromID(componentID);
|
_entitiesComponentMasks[entityID][maskBit.chankIndex] |= maskBit.mask;
|
||||||
_entitiesComponentMasks[entityID][bit.chankIndex] |= bit.mask;
|
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal void DecrementEntityComponentCount(int entityID, int componentID)
|
private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskBit maskBit)
|
||||||
{
|
{
|
||||||
var count = --_componentCounts[entityID];
|
var count = --_componentCounts[entityID];
|
||||||
EcsMaskBit bit = EcsMaskBit.FromID(componentID);
|
_entitiesComponentMasks[entityID][maskBit.chankIndex] &= ~maskBit.mask;
|
||||||
_entitiesComponentMasks[entityID][bit.chankIndex] &= ~bit.mask;
|
|
||||||
|
|
||||||
if (count == 0 && _allEntites.Has(entityID))
|
if (count == 0 && _allEntites.Has(entityID))
|
||||||
DelEntity(entityID);
|
DelEntity(entityID);
|
||||||
@ -382,6 +385,34 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#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
|
#region Callbacks Interface
|
||||||
@ -433,9 +464,4 @@ namespace DCFApixels.DragonECS
|
|||||||
public static entlong ToEntityLong(this int self, EcsWorld world) => world.GetEntityLong(self);
|
public static entlong ToEntityLong(this int self, EcsWorld world) => world.GetEntityLong(self);
|
||||||
}
|
}
|
||||||
#endregion
|
#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];
|
Type componentType = typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0];
|
||||||
int componentTypeCode = EcsTypeCode.Get(componentType);
|
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
|
else
|
||||||
{
|
{
|
||||||
componentID = _poolsCount++;
|
componentTypeID = _poolsCount++;
|
||||||
_poolIds[poolTypeCode] = componentID;
|
_poolIds[poolTypeCode] = componentTypeID;
|
||||||
_componentIds[componentTypeCode] = componentID;
|
_componentIds[componentTypeCode] = componentTypeID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_poolsCount >= _pools.Length)
|
if (_poolsCount >= _pools.Length)
|
||||||
@ -98,13 +98,13 @@ namespace DCFApixels.DragonECS
|
|||||||
Array.Resize(ref _entitiesComponentMasks[i], _pools.Length / 32 + 1);
|
Array.Resize(ref _entitiesComponentMasks[i], _pools.Length / 32 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pools[componentID] == _nullPool)
|
if (_pools[componentTypeID] == _nullPool)
|
||||||
{
|
{
|
||||||
var pool = new TPool();
|
var pool = new TPool();
|
||||||
_pools[componentID] = pool;
|
_pools[componentTypeID] = pool;
|
||||||
pool.OnInit(this, componentID);
|
pool.OnInit(this, _poolsMediator, componentTypeID);
|
||||||
}
|
}
|
||||||
return (TPool)_pools[componentID];
|
return (TPool)_pools[componentTypeID];
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,8 @@ namespace DCFApixels.DragonECS
|
|||||||
where T : IEcsHybridComponent
|
where T : IEcsHybridComponent
|
||||||
{
|
{
|
||||||
private EcsWorld _source;
|
private EcsWorld _source;
|
||||||
private int _componentID;
|
private int _componentTypeID;
|
||||||
|
private EcsMaskBit _maskBit;
|
||||||
|
|
||||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||||
private T[] _items; //dense
|
private T[] _items; //dense
|
||||||
@ -32,10 +33,12 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
||||||
|
|
||||||
|
private EcsWorld.PoolsMediator _mediator;
|
||||||
|
|
||||||
#region Properites
|
#region Properites
|
||||||
public int Count => _itemsCount;
|
public int Count => _itemsCount;
|
||||||
public int Capacity => _items.Length;
|
public int Capacity => _items.Length;
|
||||||
public int ComponentID => _componentID;
|
public int ComponentID => _componentTypeID;
|
||||||
public Type ComponentType => typeof(T);
|
public Type ComponentType => typeof(T);
|
||||||
public EcsWorld World => _source;
|
public EcsWorld World => _source;
|
||||||
#endregion
|
#endregion
|
||||||
@ -65,7 +68,7 @@ namespace DCFApixels.DragonECS
|
|||||||
Array.Resize(ref _entities, _items.Length);
|
Array.Resize(ref _entities, _items.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnAdd(entityID);
|
_listeners.InvokeOnAdd(entityID);
|
||||||
if(isMain)
|
if(isMain)
|
||||||
component.OnAddToPool(_source.GetEntityLong(entityID));
|
component.OnAddToPool(_source.GetEntityLong(entityID));
|
||||||
@ -126,7 +129,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_mapping[entityID] = 0;
|
_mapping[entityID] = 0;
|
||||||
_entities[itemIndex] = 0;
|
_entities[itemIndex] = 0;
|
||||||
_itemsCount--;
|
_itemsCount--;
|
||||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnDel(entityID);
|
_listeners.InvokeOnDel(entityID);
|
||||||
}
|
}
|
||||||
public void Del(int entityID)
|
public void Del(int entityID)
|
||||||
@ -167,10 +170,12 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
||||||
{
|
{
|
||||||
_source = world;
|
_source = world;
|
||||||
_componentID = componentID;
|
_mediator = mediator;
|
||||||
|
_componentTypeID = componentTypeID;
|
||||||
|
_maskBit = EcsMaskBit.FromID(componentTypeID);
|
||||||
|
|
||||||
const int capacity = 512;
|
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)
|
internal HybridMapping GetHybridMapping(Type type)
|
||||||
{
|
{
|
||||||
if(!_mappings.TryGetValue(type, out HybridMapping mapping))
|
if(!_hybridMapping.TryGetValue(type, out HybridMapping mapping))
|
||||||
{
|
{
|
||||||
mapping = new HybridMapping(this, type);
|
mapping = new HybridMapping(this, type);
|
||||||
_mappings.Add(type, mapping);
|
_hybridMapping.Add(type, mapping);
|
||||||
}
|
}
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
@ -313,7 +317,6 @@ namespace DCFApixels.DragonECS
|
|||||||
private static Type hybridPoolType = typeof(EcsHybridPool<>);
|
private static Type hybridPoolType = typeof(EcsHybridPool<>);
|
||||||
private static MethodInfo getHybridPoolMethod = typeof(EcsHybridPoolExtensions).GetMethod($"{nameof(EcsHybridPoolExtensions.GetPool)}", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
private static MethodInfo getHybridPoolMethod = typeof(EcsHybridPoolExtensions).GetMethod($"{nameof(EcsHybridPoolExtensions.GetPool)}", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
|
||||||
private static HashSet<Type> _hybridComponents = new HashSet<Type>();
|
private static HashSet<Type> _hybridComponents = new HashSet<Type>();
|
||||||
static HybridMapping()
|
static HybridMapping()
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ namespace DCFApixels.DragonECS
|
|||||||
where T : struct, IEcsComponent
|
where T : struct, IEcsComponent
|
||||||
{
|
{
|
||||||
private EcsWorld _source;
|
private EcsWorld _source;
|
||||||
private int _componentID;
|
private int _componentTypeID;
|
||||||
private EcsMaskBit _maskBit;
|
private EcsMaskBit _maskBit;
|
||||||
|
|
||||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
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 List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
||||||
|
|
||||||
|
private EcsWorld.PoolsMediator _mediator;
|
||||||
|
|
||||||
#region Properites
|
#region Properites
|
||||||
public int Count => _itemsCount;
|
public int Count => _itemsCount;
|
||||||
public int Capacity => _items.Length;
|
public int Capacity => _items.Length;
|
||||||
public int ComponentID => _componentID;
|
public int ComponentID => _componentTypeID;
|
||||||
public Type ComponentType => typeof(T);
|
public Type ComponentType => typeof(T);
|
||||||
public EcsWorld World => _source;
|
public EcsWorld World => _source;
|
||||||
#endregion
|
#endregion
|
||||||
@ -51,7 +53,7 @@ namespace DCFApixels.DragonECS
|
|||||||
if (itemIndex >= _items.Length)
|
if (itemIndex >= _items.Length)
|
||||||
Array.Resize(ref _items, _items.Length << 1);
|
Array.Resize(ref _items, _items.Length << 1);
|
||||||
}
|
}
|
||||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnAddAndGet(entityID);
|
_listeners.InvokeOnAddAndGet(entityID);
|
||||||
return ref _items[itemIndex];
|
return ref _items[itemIndex];
|
||||||
}
|
}
|
||||||
@ -88,7 +90,7 @@ namespace DCFApixels.DragonECS
|
|||||||
if (itemIndex >= _items.Length)
|
if (itemIndex >= _items.Length)
|
||||||
Array.Resize(ref _items, _items.Length << 1);
|
Array.Resize(ref _items, _items.Length << 1);
|
||||||
}
|
}
|
||||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnAdd(entityID);
|
_listeners.InvokeOnAdd(entityID);
|
||||||
}
|
}
|
||||||
_listeners.InvokeOnGet(entityID);
|
_listeners.InvokeOnGet(entityID);
|
||||||
@ -111,7 +113,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_recycledItems[_recycledItemsCount++] = itemIndex;
|
_recycledItems[_recycledItemsCount++] = itemIndex;
|
||||||
_mapping[entityID] = 0;
|
_mapping[entityID] = 0;
|
||||||
_itemsCount--;
|
_itemsCount--;
|
||||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnDel(entityID);
|
_listeners.InvokeOnDel(entityID);
|
||||||
}
|
}
|
||||||
public void TryDel(int entityID)
|
public void TryDel(int entityID)
|
||||||
@ -135,12 +137,12 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
||||||
{
|
{
|
||||||
_source = world;
|
_source = world;
|
||||||
_componentID = componentID;
|
_mediator = mediator;
|
||||||
|
_componentTypeID = componentTypeID;
|
||||||
_maskBit = EcsMaskBit.FromID(componentID);
|
_maskBit = EcsMaskBit.FromID(componentTypeID);
|
||||||
|
|
||||||
const int capacity = 512;
|
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>
|
/// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary>
|
||||||
public interface IEcsPoolImplementation : IEcsPool
|
public interface IEcsPoolImplementation : IEcsPool
|
||||||
{
|
{
|
||||||
void OnInit(EcsWorld world, int componentID);
|
void OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID);
|
||||||
void OnWorldResize(int newSize);
|
void OnWorldResize(int newSize);
|
||||||
void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer);
|
void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer);
|
||||||
void OnWorldDestroy();
|
void OnWorldDestroy();
|
||||||
@ -71,17 +71,6 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
public static class IEcsPoolImplementationExtensions
|
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)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsNullOrDummy(this IEcsPool self)
|
public static bool IsNullOrDummy(this IEcsPool self)
|
||||||
{
|
{
|
||||||
@ -116,7 +105,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) { }
|
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) { }
|
||||||
void IEcsPoolImplementation.OnWorldDestroy() { }
|
void IEcsPoolImplementation.OnWorldDestroy() { }
|
||||||
void IEcsPoolImplementation.OnWorldResize(int newSize) { }
|
void IEcsPoolImplementation.OnWorldResize(int newSize) { }
|
||||||
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||||
|
@ -10,7 +10,8 @@ namespace DCFApixels.DragonECS
|
|||||||
where T : struct, IEcsTagComponent
|
where T : struct, IEcsTagComponent
|
||||||
{
|
{
|
||||||
private EcsWorld _source;
|
private EcsWorld _source;
|
||||||
private int _componentID;
|
private int _componentTypeID;
|
||||||
|
private EcsMaskBit _maskBit;
|
||||||
|
|
||||||
private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||||
private int _count;
|
private int _count;
|
||||||
@ -18,8 +19,9 @@ namespace DCFApixels.DragonECS
|
|||||||
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
|
||||||
|
|
||||||
private T _fakeComponent;
|
private T _fakeComponent;
|
||||||
|
private EcsWorld.PoolsMediator _mediator;
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
private static bool _isInvalidType;
|
private static bool _isInvalidType;
|
||||||
static EcsTagPool()
|
static EcsTagPool()
|
||||||
{
|
{
|
||||||
@ -30,11 +32,12 @@ namespace DCFApixels.DragonECS
|
|||||||
if (_isInvalidType)
|
if (_isInvalidType)
|
||||||
throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data.");
|
throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data.");
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Properites
|
#region Properites
|
||||||
public int Count => _count;
|
public int Count => _count;
|
||||||
int IEcsPool.Capacity => -1;
|
int IEcsPool.Capacity => -1;
|
||||||
public int ComponentID => _componentID;
|
public int ComponentID => _componentTypeID;
|
||||||
public Type ComponentType => typeof(T);
|
public Type ComponentType => typeof(T);
|
||||||
public EcsWorld World => _source;
|
public EcsWorld World => _source;
|
||||||
#endregion
|
#endregion
|
||||||
@ -47,7 +50,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#endif
|
#endif
|
||||||
_count++;
|
_count++;
|
||||||
_mapping[entityID] = true;
|
_mapping[entityID] = true;
|
||||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnAdd(entityID);
|
_listeners.InvokeOnAdd(entityID);
|
||||||
}
|
}
|
||||||
public void TryAdd(int entityID)
|
public void TryAdd(int entityID)
|
||||||
@ -56,7 +59,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_count++;
|
_count++;
|
||||||
_mapping[entityID] = true;
|
_mapping[entityID] = true;
|
||||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnAdd(entityID);
|
_listeners.InvokeOnAdd(entityID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +75,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#endif
|
#endif
|
||||||
_mapping[entityID] = false;
|
_mapping[entityID] = false;
|
||||||
_count--;
|
_count--;
|
||||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||||
_listeners.InvokeOnDel(entityID);
|
_listeners.InvokeOnDel(entityID);
|
||||||
}
|
}
|
||||||
public void TryDel(int entityID)
|
public void TryDel(int entityID)
|
||||||
@ -116,10 +119,12 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
||||||
{
|
{
|
||||||
_source = world;
|
_source = world;
|
||||||
_componentID = componentID;
|
_mediator = mediator;
|
||||||
|
_componentTypeID = componentTypeID;
|
||||||
|
_maskBit = EcsMaskBit.FromID(componentTypeID);
|
||||||
|
|
||||||
_mapping = new bool[world.Capacity];
|
_mapping = new bool[world.Capacity];
|
||||||
_count = 0;
|
_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