mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2026-04-22 01:45:55 +08:00
Rework
Rework runner system, SparseSet etc
This commit is contained in:
parent
b73652cb37
commit
66b136df92
@ -1,15 +0,0 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class FiltersProcessor : IEcsGReceive<_OnComponentAdded>, IEcsGReceive<_OnComponentRemoved>
|
||||
{
|
||||
void IEcsGReceive<_OnComponentAdded>.Do<T>(EcsSession session, in _OnComponentAdded message, in T obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IEcsGReceive<_OnComponentRemoved>.Do<T>(EcsSession session, in _OnComponentRemoved message, in T obj)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,9 +17,8 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
void IDo<_PreInit>.Do(EcsSession session)
|
||||
{
|
||||
_OnInject<T> m = new _OnInject<T>(_injectedData);
|
||||
var messenger = session.GetMessenger<_OnInject<T>>();
|
||||
messenger.Send(in m);
|
||||
messenger.Send(new _OnInject<T>(_injectedData));
|
||||
messenger.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,13 +34,13 @@ namespace DCFApixels.DragonECS
|
||||
public EcsGroup(IEcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 128)
|
||||
{
|
||||
_source = world;
|
||||
_entities = new SparseSet(entitiesCapacity);
|
||||
_entities = new SparseSet(entitiesCapacity, entitiesCapacity);
|
||||
_delayedOps = new DelayedOp[delayedOpsCapacity];
|
||||
_lockCount = 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region add/remove
|
||||
#region Add/Remove
|
||||
public void Add(int entityID)
|
||||
{
|
||||
if (_lockCount > 0)
|
||||
|
||||
@ -40,7 +40,7 @@ namespace DCFApixels.DragonECS
|
||||
public EcsPool(IEcsWorld source, int capacity)
|
||||
{
|
||||
_source = source;
|
||||
_sparseSet = new SparseSet(capacity);
|
||||
_sparseSet = new SparseSet(capacity, capacity);
|
||||
|
||||
_denseItems =new T[capacity];
|
||||
}
|
||||
@ -96,28 +96,4 @@ namespace DCFApixels.DragonECS
|
||||
public override int GetHashCode() => _source.GetHashCode() + ID;
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static partial class EntityExtensions
|
||||
{
|
||||
public static ref readonly T Read<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return ref self.world.GetPool<T>().Read(self.id);
|
||||
}
|
||||
public static ref T Write<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return ref self.world.GetPool<T>().Write(self.id);
|
||||
}
|
||||
public static bool Has<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return self.world.GetPool<T>().Has(self.id);
|
||||
}
|
||||
public static void Del<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
self.world.GetPool<T>().Del(self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,34 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class EcsWorldMap
|
||||
{
|
||||
private Dictionary<(Type, string), IEcsWorld> _worlds = new Dictionary<(Type, string), IEcsWorld>(8);
|
||||
private bool _built = false;
|
||||
|
||||
public void Add<TArchetype>(EcsWorld<TArchetype> world, string name = "")
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
if(_built) { throw new Exception($"Cant change built {nameof(EcsWorldMap)}"); }
|
||||
_worlds.Add((typeof(TArchetype), name), world);
|
||||
}
|
||||
|
||||
public EcsWorld<TArchetype> Get<TArchetype>(string name ="")
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
return (EcsWorld<TArchetype>)_worlds[(typeof(TArchetype), name)];
|
||||
}
|
||||
|
||||
public IEcsWorld Get(Type type, string name = "")
|
||||
{
|
||||
return _worlds[(type, name)];
|
||||
}
|
||||
|
||||
public void Build()
|
||||
{
|
||||
_built = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class EcsSession
|
||||
{
|
||||
@ -18,14 +46,13 @@ namespace DCFApixels.DragonECS
|
||||
private bool _isInit = false;
|
||||
private bool _isDestoryed = false;
|
||||
|
||||
private int _worldIdIncrement;
|
||||
private Dictionary<string, IEcsWorld> _worldsDict = new Dictionary<string, IEcsWorld>();
|
||||
private List<IEcsWorld> _worlds = new List<IEcsWorld>();
|
||||
|
||||
private Dictionary<Type, IEcsProcessorsRunner> _runners;
|
||||
private Dictionary<Type, IEcsProcessorsMessenger> _messengers;
|
||||
private EcsProcessorsRunner<_Run> _runRunnerCache;
|
||||
|
||||
private EcsWorldMap _worldMap = new EcsWorldMap();
|
||||
|
||||
#region Properties
|
||||
public ReadOnlyCollection<IEcsProcessor> AllProcessors => _allProcessorsSealed;
|
||||
|
||||
@ -33,7 +60,6 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region React Runners/Messengers
|
||||
public EcsProcessorsRunner<TDoTag> GetRunner<TDoTag>()
|
||||
where TDoTag : IEcsDoTag
|
||||
{
|
||||
Type type = typeof(TDoTag);
|
||||
if (_runners.TryGetValue(type, out IEcsProcessorsRunner result))
|
||||
@ -45,7 +71,6 @@ namespace DCFApixels.DragonECS
|
||||
return (EcsProcessorsRunner<TDoTag>)result;
|
||||
}
|
||||
internal void OnRunnerDetroyed<TDoTag>(EcsProcessorsRunner<TDoTag> target)
|
||||
where TDoTag : IEcsDoTag
|
||||
{
|
||||
_runners.Remove(typeof(TDoTag));
|
||||
}
|
||||
@ -62,18 +87,6 @@ namespace DCFApixels.DragonECS
|
||||
_messengers.Add(type, result);
|
||||
return (EcsProcessorsMessenger<TMessege>)result;
|
||||
}
|
||||
public EcsProcessorsGMessenger<TMessege> GetGMessenger<TMessege>()
|
||||
where TMessege : IEcsMessage
|
||||
{
|
||||
Type type = typeof(EcsProcessorsGMessenger<TMessege>);
|
||||
if (_messengers.TryGetValue(type, out IEcsProcessorsMessenger result))
|
||||
{
|
||||
return (EcsProcessorsGMessenger<TMessege>)result;
|
||||
}
|
||||
result = new EcsProcessorsMessenger<TMessege>(this);
|
||||
_messengers.Add(type, result);
|
||||
return (EcsProcessorsGMessenger<TMessege>)result;
|
||||
}
|
||||
internal void OnMessengerDetroyed<TMessege>(IEcsProcessorsMessenger<TMessege> target)
|
||||
where TMessege : IEcsMessage
|
||||
{
|
||||
@ -85,7 +98,6 @@ namespace DCFApixels.DragonECS
|
||||
public EcsSession Add(IEcsProcessor system)
|
||||
{
|
||||
CheckInitForMethod(nameof(AddWorld));
|
||||
|
||||
_allProcessors.Add(system);
|
||||
return this;
|
||||
}
|
||||
@ -93,8 +105,7 @@ namespace DCFApixels.DragonECS
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
CheckInitForMethod(nameof(AddWorld));
|
||||
|
||||
_worlds.Add(new EcsWorld(_worldIdIncrement++));
|
||||
_worldMap.Add(world, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -104,9 +115,12 @@ namespace DCFApixels.DragonECS
|
||||
public void Init()
|
||||
{
|
||||
CheckInitForMethod(nameof(Init));
|
||||
_worldMap.Build();
|
||||
_allProcessorsSealed = _allProcessors.AsReadOnly();
|
||||
_isInit = true;
|
||||
|
||||
GetMessenger<_OnInject<EcsWorldMap>>().Send(new _OnInject<EcsWorldMap>(_worldMap));
|
||||
|
||||
GetRunner<_PreInit>().Run();
|
||||
GetRunner<_Init>().Run();
|
||||
|
||||
@ -158,6 +172,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
|
||||
|
||||
|
||||
#region Utils
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,20 +8,16 @@ using System.Threading.Tasks;
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public interface IWorldArchetype { }
|
||||
public struct DefaultArchetype : IWorldArchetype { }
|
||||
public struct DefaultWorld : IWorldArchetype { }
|
||||
|
||||
public interface IEcsWorld
|
||||
{
|
||||
public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254
|
||||
public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей
|
||||
|
||||
//private float _timeScale;//TODO реализовать собсвенныйтайм склей для разных миров
|
||||
|
||||
#region Properties
|
||||
public ushort ID { get; internal set; }
|
||||
public bool IsAlive { get; }
|
||||
public bool IsEmpty { get; }
|
||||
public Type ArchetypeType { get; }
|
||||
public int ID { get; }
|
||||
#endregion
|
||||
|
||||
public EcsPool<T> GetPool<T>() where T : struct;
|
||||
@ -36,15 +32,29 @@ namespace DCFApixels.DragonECS
|
||||
internal void OnEntityComponentRemoved(int entityID, int changedPoolID);
|
||||
}
|
||||
|
||||
public class EcsWorld<TArchetype> : IEcsWorld
|
||||
|
||||
public abstract class EcsWorld
|
||||
{
|
||||
internal static IEcsWorld[] Worlds = new IEcsWorld[8];
|
||||
private static IntDispenser _worldIdDispenser = new IntDispenser();
|
||||
|
||||
public readonly short id;
|
||||
|
||||
public EcsWorld()
|
||||
{
|
||||
id = (short)_worldIdDispenser.GetFree();
|
||||
Worlds[id] = (IEcsWorld)this;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EcsWorld<TArchetype> : EcsWorld, IEcsWorld
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
private ushort _id = IEcsWorld.DEAD_WORLD_ID;
|
||||
private IntDispenser _entityDispenser;
|
||||
private EcsGroup _entities;
|
||||
|
||||
private SparseSet _componentIDToPoolID;
|
||||
|
||||
private SparseSet _entities = new SparseSet();
|
||||
private short[] _gens;
|
||||
private short[] _componentCounts;
|
||||
|
||||
private IEcsPool[] _pools;
|
||||
|
||||
@ -54,22 +64,18 @@ namespace DCFApixels.DragonECS
|
||||
private EcsFilter[] _filters;
|
||||
|
||||
#region Properties
|
||||
public ushort ID => _id;
|
||||
ushort IEcsWorld.ID { get => _id; set => _id = value; }
|
||||
|
||||
public bool IsAlive => _id != IEcsWorld.DEAD_WORLD_ID;
|
||||
public bool IsEmpty => _entities.Count < 0;
|
||||
public Type ArchetypeType => typeof(TArchetype);
|
||||
|
||||
public int ID => id;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsWorld()
|
||||
{
|
||||
_entityDispenser = new IntDispenser();
|
||||
_pools = new IEcsPool[512];
|
||||
_entities = new SparseSet(512);
|
||||
_componentIDToPoolID = new SparseSet(512);
|
||||
_filters = new EcsFilter[512];
|
||||
_filters = new EcsFilter[64];
|
||||
_entities = new EcsGroup(this, 512);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -117,14 +123,14 @@ namespace DCFApixels.DragonECS
|
||||
BakedMask bakedMask = mask.GetBaked<TArchetype>();
|
||||
for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++)
|
||||
{
|
||||
if (!_pools[_componentIDToPoolID[bakedMask.Inc[i]]].Has(entity))
|
||||
if (!_pools[bakedMask.Inc[i]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = bakedMask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
if (_pools[_componentIDToPoolID[bakedMask.Exc[i]]].Has(entity))
|
||||
if (_pools[bakedMask.Exc[i]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -137,7 +143,7 @@ namespace DCFApixels.DragonECS
|
||||
BakedMask bakedMask = mask.GetBaked<TArchetype>();
|
||||
for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++)
|
||||
{
|
||||
int poolID = _componentIDToPoolID[bakedMask.Inc[i]];
|
||||
int poolID = bakedMask.Inc[i];
|
||||
if (poolID == otherPoolID || !_pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
@ -145,7 +151,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
for (int i = 0, iMax = bakedMask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
int poolID = _componentIDToPoolID[bakedMask.Exc[i]];
|
||||
int poolID = bakedMask.Exc[i];
|
||||
if (poolID != otherPoolID && _pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
@ -212,20 +218,18 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region NewEntity
|
||||
public Entity NewEntity()
|
||||
public ent NewEntity()
|
||||
{
|
||||
int entityID = _entities.GetFree();
|
||||
_entities.Normalize(ref _gens);
|
||||
_gens[entityID]++;
|
||||
|
||||
return new Entity(this, entityID);
|
||||
int entid = _entityDispenser.GetFree();
|
||||
if(_gens.Length < entid) Array.Resize(ref _gens, _gens.Length << 1);
|
||||
return new ent(entid, _gens[entid]++, id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Destroy
|
||||
public void Destroy()
|
||||
{
|
||||
_id = IEcsWorld.DEAD_WORLD_ID;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
Мервтый мир - значение byte 255, зарезервированный адишник мира, все что ссылается на мертвый мир считается так же мертвым.
|
||||
|
||||
DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных проверок
|
||||
DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных проверок
|
||||
|
||||
public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254
|
||||
public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей
|
||||
@ -2,14 +2,12 @@
|
||||
{
|
||||
public interface IEcsProcessor { }
|
||||
|
||||
public interface IEcsDoTag { }
|
||||
public struct _PreInit : IEcsDoTag { }
|
||||
public struct _Init : IEcsDoTag { }
|
||||
public struct _Run : IEcsDoTag { }
|
||||
public struct _Destroy : IEcsDoTag { }
|
||||
public struct _PostDestroy : IEcsDoTag { }
|
||||
public struct _PreInit { }
|
||||
public struct _Init { }
|
||||
public struct _Run { }
|
||||
public struct _Destroy { }
|
||||
public struct _PostDestroy { }
|
||||
public interface IDo<TTag> : IEcsProcessor
|
||||
where TTag : IEcsDoTag
|
||||
{
|
||||
public void Do(EcsSession session);
|
||||
}
|
||||
@ -53,19 +51,4 @@
|
||||
{
|
||||
public void Do(EcsSession session, in TMessage m);
|
||||
}
|
||||
|
||||
|
||||
public struct _OnComponentRemoved : IEcsMessage
|
||||
{
|
||||
public int entityID;
|
||||
}
|
||||
public struct _OnComponentAdded : IEcsMessage
|
||||
{
|
||||
public int entityID;
|
||||
}
|
||||
public interface IEcsGReceive<TMessage> : IEcsProcessor
|
||||
where TMessage : IEcsMessage
|
||||
{
|
||||
public void Do<T>(EcsSession session, in TMessage m, in T obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,17 +31,17 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
// но чтобы значене default было NULL сульностью, мир хранится в виде ID + 1
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public ushort world
|
||||
public short world
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (ushort)(((_full << 48) >> 48) - 1);
|
||||
get => (short)(((_full << 48) >> 48) - 1);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public ent(int id, short gen, ushort world)
|
||||
public ent(int id, short gen, short world)
|
||||
{
|
||||
_full = ((long)id) << 32;
|
||||
_full += ((long)gen) << 16;
|
||||
@ -104,22 +104,83 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class entExtensions
|
||||
public static partial class entExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNull(this in ent self)
|
||||
{
|
||||
return self == ent.NULL;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref readonly T Read<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
return ref EcsWorld.Worlds[self.world].GetPool<T>().Read(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T Write<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
return ref EcsWorld.Worlds[self.world].GetPool<T>().Write(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool Has<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
return EcsWorld.Worlds[self.world].GetPool<T>().Has(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Del<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
EcsWorld.Worlds[self.world].GetPool<T>().Del(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly ref struct Entity
|
||||
public struct Entity
|
||||
{
|
||||
internal readonly IEcsWorld world;
|
||||
internal readonly int id;
|
||||
public Entity(IEcsWorld world, ent id)
|
||||
public IEcsWorld world;
|
||||
public int id;
|
||||
|
||||
public Entity(IEcsWorld world, int id)
|
||||
{
|
||||
this.world = world;
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class EntityExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNull(this in Entity self)
|
||||
{
|
||||
return self.world == null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref readonly T Read<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return ref self.world.GetPool<T>().Read(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T Write<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return ref self.world.GetPool<T>().Write(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool Has<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return self.world.GetPool<T>().Has(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Del<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
self.world.GetPool<T>().Del(self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class EcsProcessorsGMessenger<TMessage> : IEcsProcessorsMessenger<TMessage>, IDisposable
|
||||
where TMessage : IEcsMessage
|
||||
{
|
||||
private readonly EcsSession _source;
|
||||
private readonly IEcsGReceive<TMessage>[] _targets;
|
||||
|
||||
public EcsSession Source => _source;
|
||||
public IReadOnlyList<IEcsGReceive<TMessage>> Targets => _targets;
|
||||
|
||||
internal EcsProcessorsGMessenger(EcsSession source)
|
||||
{
|
||||
_source = source;
|
||||
List<IEcsGReceive<TMessage>> list = new List<IEcsGReceive<TMessage>>();
|
||||
|
||||
foreach (var item in _source.AllProcessors)
|
||||
{
|
||||
if (item is IEcsGReceive<TMessage> targetItem)
|
||||
{
|
||||
list.Add(targetItem);
|
||||
}
|
||||
}
|
||||
_targets = list.ToArray();
|
||||
}
|
||||
|
||||
public void Send<T>(in TMessage message, in T obj)
|
||||
{
|
||||
foreach (var item in _targets)
|
||||
{
|
||||
item.Do(_source, in message, in obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void Destroy() => _source.OnMessengerDetroyed(this);
|
||||
void IDisposable.Dispose() => Destroy();
|
||||
}
|
||||
}
|
||||
@ -32,6 +32,10 @@ namespace DCFApixels.DragonECS
|
||||
_targets = list.ToArray();
|
||||
}
|
||||
|
||||
public void Send(TMessage message)
|
||||
{
|
||||
Send(in message);
|
||||
}
|
||||
public void Send(in TMessage message)
|
||||
{
|
||||
foreach (var item in _targets)
|
||||
|
||||
@ -9,7 +9,6 @@ namespace DCFApixels.DragonECS
|
||||
public void Run();
|
||||
}
|
||||
public class EcsProcessorsRunner<TDoTag> : IEcsProcessorsRunner, IDisposable
|
||||
where TDoTag : IEcsDoTag
|
||||
{
|
||||
private readonly EcsSession _source;
|
||||
private readonly IDo<TDoTag>[] _targets;
|
||||
|
||||
126
src/React/RunnerHandler.cs
Normal file
126
src/React/RunnerHandler.cs
Normal file
@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
|
||||
sealed class RunnerFilterAttribute : Attribute
|
||||
{
|
||||
public readonly Type interfaceType;
|
||||
public readonly object filter;
|
||||
public RunnerFilterAttribute(Type interfaceType, object filter)
|
||||
{
|
||||
this.interfaceType = interfaceType;
|
||||
this.filter = filter;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IProcessor { }
|
||||
|
||||
public static class IProcessorExtensions
|
||||
{
|
||||
public static bool IsRunner(this IProcessor self)
|
||||
{
|
||||
return self is IRunner;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class RunnerActivator
|
||||
{
|
||||
private static bool _isInit = false;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Init()
|
||||
{
|
||||
if (_isInit) return;
|
||||
Type targetType = typeof(Runner<>);
|
||||
var subclasses = Assembly.GetAssembly(targetType).GetTypes().Where(type => type.BaseType != null && type.BaseType.IsGenericType && targetType == type.BaseType.GetGenericTypeDefinition());
|
||||
foreach (var item in subclasses)
|
||||
{
|
||||
item.BaseType.GetMethod("Init", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { item });
|
||||
}
|
||||
_isInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IRunner { }
|
||||
|
||||
public abstract class Runner<TInterface> : IProcessor, IRunner
|
||||
where TInterface : IProcessor
|
||||
{
|
||||
internal static void Init(Type subclass)
|
||||
{
|
||||
|
||||
#if DEBUG || DCFAECS_NO_SANITIZE_CHECKS
|
||||
if (_subclass != null)
|
||||
{
|
||||
throw new ArgumentException($"The Runner<{typeof(TInterface).FullName}> can only have one subclass");
|
||||
}
|
||||
|
||||
Type interfaceType = typeof(TInterface);
|
||||
|
||||
var interfaces = interfaceType.GetInterfaces();
|
||||
if (interfaceType.IsInterface == false)
|
||||
{
|
||||
throw new ArgumentException($"{typeof(TInterface).FullName} is not interface");
|
||||
}
|
||||
if (interfaces.Length != 1 || interfaces[0] != typeof(IProcessor))
|
||||
{
|
||||
throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IProcessor)} interface");
|
||||
}
|
||||
#endif
|
||||
_subclass = subclass;
|
||||
}
|
||||
|
||||
public static TInterface Instantiate(IEnumerable<IProcessor> targets, object filter)
|
||||
{
|
||||
Type interfaceType = typeof(TInterface);
|
||||
|
||||
IEnumerable<IProcessor> newTargets;
|
||||
|
||||
if (filter != null)
|
||||
{
|
||||
newTargets = targets.Where(o =>
|
||||
{
|
||||
if (o is TInterface == false) return false;
|
||||
var atr = o.GetType().GetCustomAttribute<RunnerFilterAttribute>();
|
||||
return atr != null && atr.interfaceType == interfaceType && atr.filter.Equals(filter);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
newTargets = targets.Where(o =>
|
||||
{
|
||||
if (o is TInterface == false) return false;
|
||||
var atr = o.GetType().GetCustomAttribute<RunnerFilterAttribute>();
|
||||
return atr == null || atr.interfaceType == interfaceType && atr.filter == null;
|
||||
});
|
||||
}
|
||||
|
||||
return Instantiate(newTargets.Select(o => (TInterface)o).ToArray());
|
||||
}
|
||||
public static TInterface Instantiate(IEnumerable<IProcessor> targets)
|
||||
{
|
||||
return Instantiate(targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray());
|
||||
}
|
||||
internal static TInterface Instantiate(TInterface[] targets)
|
||||
{
|
||||
RunnerActivator.Init();
|
||||
var instance = (Runner<TInterface>)Activator.CreateInstance(_subclass);
|
||||
return (TInterface)(IProcessor)instance.Set(targets);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static Type _subclass;
|
||||
protected TInterface[] targets;
|
||||
|
||||
private Runner<TInterface> Set(TInterface[] targets)
|
||||
{
|
||||
this.targets = targets;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d340db685521a624792157f350923088
|
||||
guid: ae6eb3472cd282b46b26ab9f1e97ec81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
44
src/Utils/IntDispenser.cs
Normal file
44
src/Utils/IntDispenser.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
internal sealed class IntDispenser
|
||||
{
|
||||
private readonly ConcurrentStack<int> _freeInts;
|
||||
private int _increment;
|
||||
|
||||
#region Properties
|
||||
public int LastInt => _increment;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public IntDispenser()
|
||||
{
|
||||
_freeInts = new ConcurrentStack<int>();
|
||||
_increment = 0;
|
||||
}
|
||||
public IntDispenser(int startIncrement)
|
||||
{
|
||||
_freeInts = new ConcurrentStack<int>();
|
||||
_increment = startIncrement;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFree/Release
|
||||
public int GetFree()
|
||||
{
|
||||
if (!_freeInts.TryPop(out int result))
|
||||
{
|
||||
result = Interlocked.Increment(ref _increment);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Release(int released)
|
||||
{
|
||||
_freeInts.Push(released);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db219c3a9acc0964f8808af51e32afc3
|
||||
guid: a20cbd833c35ff3438f9fe003903c0c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@ -3,115 +3,124 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using coretype = System.Int32;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class SparseSet : IEnumerable<coretype>, ICollection<coretype>, IReadOnlyCollection<coretype>
|
||||
public class SparseSet : IEnumerable<int>, ICollection<int>, IReadOnlyCollection<int>
|
||||
{
|
||||
public const int DEFAULT_CAPACITY = 16;
|
||||
public const int MAX_CAPACITY = coretype.MaxValue;
|
||||
public const int DEFAULT_DENSE_CAPACITY = 8;
|
||||
public const int DEFAULT_SPARSE_CAPACITY = 16;
|
||||
|
||||
private coretype[] _dense;
|
||||
private coretype[] _sparse;
|
||||
public const int MIN_CAPACITY = 4;
|
||||
|
||||
private coretype _count;
|
||||
public const int MAX_CAPACITY = int.MaxValue;
|
||||
|
||||
private coretype _denseCapacity;
|
||||
private int[] _dense;
|
||||
private int[] _sparse;
|
||||
|
||||
private int _count;
|
||||
|
||||
#region Properties
|
||||
public int Count => _count;
|
||||
public int CapacityDense
|
||||
public int Count
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _denseCapacity;
|
||||
get => _count;
|
||||
}
|
||||
public int CapacitySparse
|
||||
public int CapacityDense
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _dense.Length;
|
||||
}
|
||||
|
||||
public coretype this[int index]
|
||||
public int CapacitySparse
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _sparse.Length;
|
||||
}
|
||||
|
||||
public int this[int index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#if DEBUG
|
||||
get
|
||||
{
|
||||
ThrowHalper.CheckOutOfRange(this, (coretype)index);
|
||||
#if DEBUG
|
||||
ThrowHalper.CheckOutOfRange(this, index);
|
||||
#endif
|
||||
return _dense[index];
|
||||
}
|
||||
#else
|
||||
get => _dense[index];
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public SparseSet() : this(DEFAULT_CAPACITY) { }
|
||||
public SparseSet(coretype capacity)
|
||||
public SparseSet() : this(DEFAULT_DENSE_CAPACITY, DEFAULT_SPARSE_CAPACITY) { }
|
||||
public SparseSet(int denseCapacity, int sparseCapacity)
|
||||
{
|
||||
#if DEBUG
|
||||
ThrowHalper.CheckCapacity(capacity);
|
||||
#endif
|
||||
_dense = new coretype[capacity];
|
||||
_sparse = new coretype[capacity];
|
||||
for (coretype i = 0; i < _sparse.Length; i++)
|
||||
{
|
||||
_dense[i] = i;
|
||||
_sparse[i] = i;
|
||||
}
|
||||
_count = 0;
|
||||
_denseCapacity = 0;
|
||||
denseCapacity = denseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(denseCapacity);
|
||||
sparseCapacity = sparseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(sparseCapacity);
|
||||
|
||||
_dense = new int[denseCapacity];
|
||||
_sparse = new int[sparseCapacity];
|
||||
|
||||
Reset();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add/AddRange/GetFree
|
||||
public void Add<T>(coretype value, ref T[] normalizedArray)
|
||||
#region Add/AddRange
|
||||
public void Add<T>(int value, ref T[] normalizedArray)
|
||||
{
|
||||
Add(value);
|
||||
Normalize(ref normalizedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Add(coretype value)
|
||||
public void Add(int value)
|
||||
{
|
||||
#if DEBUG
|
||||
ThrowHalper.CheckValueIsPositive(value);
|
||||
ThrowHalper.CheckValueNotContained(this, value);
|
||||
#endif
|
||||
if (value > CapacitySparse)
|
||||
if (_count >= _dense.Length)
|
||||
Array.Resize(ref _dense, _dense.Length << 1);
|
||||
|
||||
if (value > _sparse.Length)
|
||||
{
|
||||
coretype neadedSpace = (coretype)_dense.Length;
|
||||
while (value >= neadedSpace) neadedSpace <<= 1;
|
||||
Resize(neadedSpace);
|
||||
int neadedSpace = _sparse.Length;
|
||||
while (value >= neadedSpace)
|
||||
neadedSpace <<= 1;
|
||||
int i = _sparse.Length;
|
||||
Array.Resize(ref _sparse, neadedSpace);
|
||||
//loop unwinding
|
||||
for (; i < neadedSpace;)
|
||||
{
|
||||
_sparse[i++] = -1;
|
||||
_sparse[i++] = -1;
|
||||
_sparse[i++] = -1;
|
||||
_sparse[i++] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
Swap(value, _count++);
|
||||
if (_count > _denseCapacity) _denseCapacity <<= 1;
|
||||
_dense[_count] = value;
|
||||
_sparse[value] = _count++;
|
||||
}
|
||||
|
||||
public bool TryAdd<T>(coretype value, ref T[] normalizedArray)
|
||||
public bool TryAdd<T>(int value, ref T[] normalizedArray)
|
||||
{
|
||||
if (Contains(value)) return false;
|
||||
Add(value);
|
||||
Normalize(ref normalizedArray);
|
||||
return true;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryAdd(coretype value)
|
||||
public bool TryAdd(int value)
|
||||
{
|
||||
if (Contains(value)) return false;
|
||||
Add(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddRange<T>(IEnumerable<coretype> range, ref T[] normalizedArray)
|
||||
public void AddRange<T>(IEnumerable<int> range, ref T[] normalizedArray)
|
||||
{
|
||||
AddRange(range);
|
||||
Normalize(ref normalizedArray);
|
||||
}
|
||||
public void AddRange(IEnumerable<coretype> range)
|
||||
public void AddRange(IEnumerable<int> range)
|
||||
{
|
||||
foreach (var item in range)
|
||||
{
|
||||
@ -119,46 +128,28 @@ namespace DCFApixels.DragonECS
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Adds a value between 0 and Capacity to the array and returns it.</summary>
|
||||
/// <returns>Value between 0 and Capacity</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public coretype GetFree<T>(ref T[] normalizedArray)
|
||||
{
|
||||
coretype result = GetFree();
|
||||
Normalize(ref normalizedArray);
|
||||
return result;
|
||||
}
|
||||
/// <summary>Adds a value between 0 and Capacity to the array and returns it.</summary>
|
||||
/// <returns>Value between 0 and Capacity</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public coretype GetFree()
|
||||
{
|
||||
if (++_count >= CapacitySparse) AddSpaces();
|
||||
if (_count > _denseCapacity) _denseCapacity <<= 1;
|
||||
return _dense[_count - 1];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Contains
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Contains(coretype value)
|
||||
public bool Contains(int value)
|
||||
{
|
||||
return value >= 0 && value < CapacitySparse && _sparse[value] < _count;
|
||||
return value >= 0 && value < CapacitySparse && _sparse[value] >= 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Remove(coretype value)
|
||||
public void Remove(int value)
|
||||
{
|
||||
#if DEBUG
|
||||
ThrowHalper.CheckValueContained(this, value);
|
||||
#endif
|
||||
Swap(_sparse[value], --_count);
|
||||
_dense[_sparse[value]] = _dense[--_count];
|
||||
_sparse[_dense[_count]] = _sparse[value];
|
||||
_sparse[value] = -1;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryRemove(coretype value)
|
||||
public bool TryRemove(int value)
|
||||
{
|
||||
if (!Contains(value)) return false;
|
||||
Remove(value);
|
||||
@ -166,7 +157,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RemoveAt(coretype index)
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
#if DEBUG
|
||||
ThrowHalper.CheckOutOfRange(this, index);
|
||||
@ -183,7 +174,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IndexOf(coretype value)
|
||||
public int IndexOf(int value)
|
||||
{
|
||||
if (value < 0 || !Contains(value)) return -1;
|
||||
return _sparse[value];
|
||||
@ -191,8 +182,8 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public void Sort()
|
||||
{
|
||||
coretype increment = 0;
|
||||
for (coretype i = 0; i < CapacitySparse; i++)
|
||||
int increment = 0;
|
||||
for (int i = 0; i < CapacitySparse; i++)
|
||||
{
|
||||
if (_sparse[i] < _count)
|
||||
{
|
||||
@ -204,18 +195,17 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public void HardSort()
|
||||
{
|
||||
coretype inc = 0;
|
||||
coretype inc2 = _count;
|
||||
for (coretype i = 0; i < CapacitySparse; i++)
|
||||
int inc = 0;
|
||||
int inc2 = _count;
|
||||
for (int i = 0; i < CapacitySparse; i++)
|
||||
{
|
||||
if (_sparse[i] < _count)
|
||||
if (_sparse[i] >= 0)
|
||||
{
|
||||
_sparse[i] = inc;
|
||||
_dense[inc++] = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
_sparse[i] = inc2;
|
||||
_dense[inc2++] = i;
|
||||
}
|
||||
}
|
||||
@ -225,14 +215,14 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
other._count = _count;
|
||||
if (CapacitySparse != other.CapacitySparse)
|
||||
{
|
||||
other.Resize(CapacitySparse);
|
||||
}
|
||||
_dense.CopyTo(other._dense, 0);
|
||||
Array.Resize(ref other._sparse, CapacitySparse);
|
||||
if (CapacityDense != other.CapacityDense)
|
||||
Array.Resize(ref other._dense, CapacityDense);
|
||||
_sparse.CopyTo(other._sparse, 0);
|
||||
_dense.CopyTo(other._dense, 0);
|
||||
}
|
||||
|
||||
public void CopyTo(coretype[] array, int arrayIndex)
|
||||
public void CopyTo(int[] array, int arrayIndex)
|
||||
{
|
||||
#if DEBUG
|
||||
if (arrayIndex < 0) throw new ArgumentException("arrayIndex is less than 0");
|
||||
@ -243,6 +233,12 @@ namespace DCFApixels.DragonECS
|
||||
array[arrayIndex] = this[i];
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int NormalizeCapacity(int value)
|
||||
{
|
||||
return value + (MIN_CAPACITY - (value % MIN_CAPACITY));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Clear/Reset
|
||||
@ -251,52 +247,26 @@ namespace DCFApixels.DragonECS
|
||||
public void Reset()
|
||||
{
|
||||
Clear();
|
||||
for (coretype i = 0; i < _dense.Length; i++)
|
||||
//loop unwinding
|
||||
for (int i = 0; i < _sparse.Length;)
|
||||
{
|
||||
_dense[i] = i;
|
||||
_sparse[i] = i;
|
||||
_sparse[i++] = -1;
|
||||
_sparse[i++] = -1;
|
||||
_sparse[i++] = -1;
|
||||
_sparse[i++] = -1;
|
||||
}
|
||||
}
|
||||
public void Reset(coretype newCapacity)
|
||||
|
||||
public void Reset(int newDenseCapacity, int newSparseCapacity)
|
||||
{
|
||||
#if DEBUG
|
||||
ThrowHalper.CheckCapacity(newCapacity);
|
||||
#endif
|
||||
newDenseCapacity = newDenseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(newDenseCapacity);
|
||||
newSparseCapacity = newSparseCapacity < MIN_CAPACITY ? MIN_CAPACITY : NormalizeCapacity(newSparseCapacity);
|
||||
|
||||
if (CapacitySparse != newSparseCapacity)
|
||||
Array.Resize(ref _sparse, newSparseCapacity);
|
||||
if (CapacityDense != newDenseCapacity)
|
||||
Array.Resize(ref _dense, newDenseCapacity);
|
||||
Reset();
|
||||
Resize(newCapacity);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddSpace/Resize
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void AddSpaces() => Resize((_count << 1));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Resize(int newSpace)
|
||||
{
|
||||
coretype oldspace = (short)_dense.Length;
|
||||
Array.Resize(ref _dense, newSpace);
|
||||
Array.Resize(ref _sparse, newSpace);
|
||||
|
||||
for (coretype i = oldspace; i < newSpace; i++)
|
||||
{
|
||||
_dense[i] = i;
|
||||
_sparse[i] = i;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Swap
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Swap(coretype fromIndex, coretype toIndex)
|
||||
{
|
||||
coretype value = _dense[toIndex];
|
||||
coretype oldValue = _dense[fromIndex];
|
||||
|
||||
_dense[toIndex] = oldValue;
|
||||
_dense[fromIndex] = value;
|
||||
_sparse[_dense[fromIndex]] = fromIndex;
|
||||
_sparse[_dense[toIndex]] = toIndex;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -306,19 +276,19 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public ref struct RefEnumerator
|
||||
{
|
||||
private readonly coretype[] _dense;
|
||||
private readonly coretype _count;
|
||||
private coretype _index;
|
||||
private readonly int[] _dense;
|
||||
private readonly int _count;
|
||||
private int _index;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public RefEnumerator(coretype[] values, coretype count)
|
||||
public RefEnumerator(int[] values, int count)
|
||||
{
|
||||
_dense = values;
|
||||
_count = count;
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
public coretype Current
|
||||
public int Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _dense[_index];
|
||||
@ -334,20 +304,20 @@ namespace DCFApixels.DragonECS
|
||||
public void Reset() => _index = -1;
|
||||
}
|
||||
|
||||
IEnumerator<coretype> IEnumerable<coretype>.GetEnumerator() => new Enumerator(_dense, _count);
|
||||
IEnumerator<int> IEnumerable<int>.GetEnumerator() => new Enumerator(_dense, _count);
|
||||
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(_dense, _count);
|
||||
public struct Enumerator : IEnumerator<coretype> //to implement the IEnumerable interface and use the ref structure, 2 Enumerators were created.
|
||||
public struct Enumerator : IEnumerator<int> //to implement the IEnumerable interface and use the ref structure, 2 Enumerators were created.
|
||||
{
|
||||
private readonly coretype[] _dense;
|
||||
private readonly coretype _count;
|
||||
private coretype _index;
|
||||
public Enumerator(coretype[] values, coretype count)
|
||||
private readonly int[] _dense;
|
||||
private readonly int _count;
|
||||
private int _index;
|
||||
public Enumerator(int[] values, int count)
|
||||
{
|
||||
_dense = values;
|
||||
_count = count;
|
||||
_index = -1;
|
||||
}
|
||||
public coretype Current => _dense[_index];
|
||||
public int Current => _dense[_index];
|
||||
object IEnumerator.Current => _dense[_index];
|
||||
public void Dispose() { }
|
||||
public bool MoveNext() => ++_index < _count;
|
||||
@ -356,16 +326,16 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region ICollection
|
||||
bool ICollection<coretype>.IsReadOnly => false;
|
||||
bool ICollection<int>.IsReadOnly => false;
|
||||
|
||||
bool ICollection<coretype>.Remove(coretype value) => TryRemove(value);
|
||||
bool ICollection<int>.Remove(int value) => TryRemove(value);
|
||||
#endregion
|
||||
|
||||
#region Debug
|
||||
public string Log()
|
||||
{
|
||||
StringBuilder logbuild = new StringBuilder();
|
||||
for (int i = 0; i < CapacitySparse; i++)
|
||||
for (int i = 0; i < CapacityDense; i++)
|
||||
{
|
||||
logbuild.Append(_dense[i] + ", ");
|
||||
}
|
||||
@ -376,14 +346,14 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
logbuild.Append("\n\r --------------------------");
|
||||
logbuild.Append("\n\r");
|
||||
for (int i = 0; i < CapacitySparse; i++)
|
||||
for (int i = 0; i < CapacityDense; i++)
|
||||
{
|
||||
logbuild.Append((i < _count ? _dense[i].ToString() : "_") + ", ");
|
||||
}
|
||||
logbuild.Append("\n\r");
|
||||
for (int i = 0; i < CapacitySparse; i++)
|
||||
{
|
||||
logbuild.Append((_sparse[i] < _count ? _sparse[i].ToString() : "_") + ", ");
|
||||
logbuild.Append((_sparse[i] >= 0 ? _sparse[i].ToString() : "_") + ", ");
|
||||
}
|
||||
logbuild.Append("\n\r Count: " + _count);
|
||||
logbuild.Append("\n\r Capacity: " + CapacitySparse);
|
||||
@ -396,7 +366,7 @@ namespace DCFApixels.DragonECS
|
||||
public bool IsValide_Debug()
|
||||
{
|
||||
bool isPass = true;
|
||||
for (int index = 0; index < CapacitySparse; index++)
|
||||
for (int index = 0; index < _count; index++)
|
||||
{
|
||||
int value = _dense[index];
|
||||
isPass = isPass && _sparse[value] == index;
|
||||
@ -407,27 +377,27 @@ namespace DCFApixels.DragonECS
|
||||
#if DEBUG
|
||||
private static class ThrowHalper
|
||||
{
|
||||
public static void CheckCapacity(coretype capacity)
|
||||
public static void CheckCapacity(int capacity)
|
||||
{
|
||||
if (capacity < 0)
|
||||
throw new ArgumentException("Capacity cannot be a negative number");
|
||||
}
|
||||
public static void CheckValueIsPositive(coretype value)
|
||||
public static void CheckValueIsPositive(int value)
|
||||
{
|
||||
if (value < 0)
|
||||
throw new ArgumentException("The SparseSet can only contain positive numbers");
|
||||
}
|
||||
public static void CheckValueContained(SparseSet source, coretype value)
|
||||
public static void CheckValueContained(SparseSet source, int value)
|
||||
{
|
||||
if (!source.Contains(value))
|
||||
throw new ArgumentException($"Value {value} is not contained");
|
||||
}
|
||||
public static void CheckValueNotContained(SparseSet source, coretype value)
|
||||
public static void CheckValueNotContained(SparseSet source, int value)
|
||||
{
|
||||
if (source.Contains(value))
|
||||
throw new ArgumentException($"Value {value} is already contained");
|
||||
}
|
||||
public static void CheckOutOfRange(SparseSet source, coretype index)
|
||||
public static void CheckOutOfRange(SparseSet source, int index)
|
||||
{
|
||||
if (index < 0 || index >= source.Count)
|
||||
throw new ArgumentOutOfRangeException($"Index {index} was out of range. Must be non-negative and less than the size of the collection.");
|
||||
|
||||
@ -14,7 +14,6 @@ namespace DCFApixels.DragonECS
|
||||
private void Start()
|
||||
{
|
||||
_ecsSession
|
||||
.AddWorld("")
|
||||
.Add(new TestSystem())
|
||||
.Inject(_data)
|
||||
.Init();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user