Update WIP, remove Members, add Read/Write pool getter, add DI

This commit is contained in:
Mikhail 2023-02-13 21:11:54 +08:00
parent 980ed316e1
commit dc2e0cd810
46 changed files with 897 additions and 822 deletions

View File

@ -1,22 +1,12 @@
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public class DestroyProcessor : IEcsDo<_Run> public class DestroyProcessor : IDo<_Run>
{ {
void IEcsDo<_Run>.Do(EcsSession session) void IDo<_Run>.Do(EcsSession session)
{ {
} }
} }
public class DestroyedTable : EcsTable public struct DestroyedTag { }
{
public readonly EcsPool<tag> isDestroyed;
public static mem<tag> isDestroyedMem = "isDestroyed";
public DestroyedTable(ref TableBuilder builder) : base(ref builder)
{
isDestroyed = builder.Inc(isDestroyedMem);
}
}
} }

View File

@ -0,0 +1,15 @@
namespace DCFApixels.DragonECS
{
public class FitersProcessor : 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)
{
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: a21421fecdd5670448a3a10c804238f7 guid: db219c3a9acc0964f8808af51e32afc3
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
public class InjectProcessor<T> : IDo<_PreInit>
{
private T _injectedData;
public InjectProcessor(T injectedData)
{
_injectedData = injectedData;
}
void IDo<_PreInit>.Do(EcsSession session)
{
_OnInject<T> m = new _OnInject<T>(_injectedData);
session.GetMessenger<_OnInject<T>>().Send(in m);
}
}
public static class InjectProcessorExstensions
{
public static EcsSession Inject<T>(this EcsSession self, T data)
{
self.Add(new InjectProcessor<T>(data));
return self;
}
public static EcsSession Inject<A, B>(this EcsSession self, A dataA, B dataB)
{
self.Inject(dataA).Inject(dataB);
return self;
}
public static EcsSession Inject<A, B, C, D>(this EcsSession self, A dataA, B dataB, C dataC, D dataD)
{
self.Inject(dataA).Inject(dataB).Inject(dataC).Inject(dataD);
return self;
}
public static EcsSession Inject<A, B, C, D, E>(this EcsSession self,
A dataA, B dataB, C dataC, D dataD, E dataE)
{
self.Inject(dataA).Inject(dataB).Inject(dataC).Inject(dataD).Inject(dataE);
return self;
}
}
}

16
src/Code.cs Normal file
View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
public static class Code
{
public static readonly NilType nil = default;
}
public readonly struct NilType { }
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: b5af477721d789f498a0de809e753321 guid: fdfd15ed79cb9e04caf3fb0275900c72
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -12,6 +12,32 @@ namespace DCFApixels.DragonECS
public EcsWorld World { get; } public EcsWorld World { get; }
public int EntitiesCount { get; } public int EntitiesCount { get; }
} }
public abstract class MaskBase
{
protected internal static int _typeIDIncrement = 0;
}
public abstract class IncBase { }
public abstract class ExcBase { }
public sealed class Inc<A> : IncBase { }
public sealed class Inc<A, b> : IncBase { }
public sealed class Exc<A> : ExcBase { }
public sealed class Exc<A, B> : ExcBase { }
public sealed class Mask<TInc> : MaskBase
where TInc : IncBase
{
public static readonly int typeID = _typeIDIncrement++;
}
public sealed class Mask<TInc, TExc> : MaskBase
where TInc : IncBase
where TExc : ExcBase
{
public static readonly int typeID = _typeIDIncrement++;
}
public class EcsFilter : IEcsFilter public class EcsFilter : IEcsFilter
{ {
private readonly EcsWorld _source; private readonly EcsWorld _source;
@ -25,6 +51,7 @@ namespace DCFApixels.DragonECS
#region Properties #region Properties
public EcsWorld World => _source; public EcsWorld World => _source;
public EcsWorld.Mask Mask => _mask;
public int EntitiesCount => _entities.Count; public int EntitiesCount => _entities.Count;
#endregion #endregion
@ -45,7 +72,7 @@ namespace DCFApixels.DragonECS
if (isAdd) if (isAdd)
Add(entityID); Add(entityID);
else else
Del(entityID); Remove(entityID);
} }
internal void Add(int entityID) internal void Add(int entityID)
{ {
@ -54,7 +81,7 @@ namespace DCFApixels.DragonECS
_entities.Add(entityID); _entities.Add(entityID);
} }
internal void Del(int entityID) internal void Remove(int entityID)
{ {
if (_lockCount > 0) if (_lockCount > 0)
AddDelayedOp(entityID, false); AddDelayedOp(entityID, false);
@ -67,9 +94,9 @@ namespace DCFApixels.DragonECS
{ {
Array.Resize(ref _delayedOps, _delayedOps.Length << 1); Array.Resize(ref _delayedOps, _delayedOps.Length << 1);
} }
ref DelayedOp delayedOd = ref _delayedOps[_delayedOpsCount];
_delayedOps[_delayedOpsCount].Entity = entityID; delayedOd.Entity = entityID;
_delayedOps[_delayedOpsCount].Added = isAdd; delayedOd.Added = isAdd;
} }
#region GetEnumerator #region GetEnumerator
@ -81,12 +108,19 @@ namespace DCFApixels.DragonECS
throw new Exception($"Invalid lock-unlock balance for {nameof(EcsFilter)}."); throw new Exception($"Invalid lock-unlock balance for {nameof(EcsFilter)}.");
} }
#endif #endif
_lockCount--; if (--_lockCount <= 0)
if (_lockCount <= 0)
{ {
for (int i = 0; i < _delayedOpsCount; i++) for (int i = 0; i < _delayedOpsCount; i++)
{ {
ref DelayedOp op = ref _delayedOps[i];
if (op.Added)
{
Add(op.Entity);
}
else
{
Remove(op.Entity);
}
} }
} }
} }
@ -100,9 +134,9 @@ namespace DCFApixels.DragonECS
#region Utils #region Utils
public ref struct Enumerator public ref struct Enumerator
{ {
readonly EcsFilter _source; private readonly EcsFilter _source;
readonly SparseSet _entities; private readonly SparseSet _entities;
int _index; private int _index;
public Enumerator(EcsFilter filter) public Enumerator(EcsFilter filter)
{ {

143
src/EcsGroup.cs Normal file
View File

@ -0,0 +1,143 @@
using System;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public class EcsGroup
{
private EcsWorld _source;
private SparseSet _entities;
private DelayedOp[] _delayedOps;
private int _delayedOpsCount;
private int _lockCount;
#region Properties
public EcsWorld World => _source;
public int EntitiesCount => _entities.Count;
#endregion
#region Constrcutors
public EcsGroup(EcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 128)
{
_source = world;
_entities = new SparseSet(entitiesCapacity);
_delayedOps = new DelayedOp[delayedOpsCapacity];
_lockCount = 0;
}
#endregion
#region add/remove
public void Add(int entityID)
{
if (_lockCount > 0)
AddDelayedOp(entityID, true);
_entities.Add(entityID);
}
public void Remove(int entityID)
{
if (_lockCount > 0)
AddDelayedOp(entityID, false);
_entities.Remove(entityID);
}
private void AddDelayedOp(int entityID, bool isAdd)
{
if (_delayedOpsCount >= _delayedOps.Length)
{
Array.Resize(ref _delayedOps, _delayedOps.Length << 1);
}
ref DelayedOp delayedOd = ref _delayedOps[_delayedOpsCount];
delayedOd.Entity = entityID;
delayedOd.Added = isAdd;
}
#endregion
#region GetEnumerator
private void Unlock()
{
#if DEBUG
if (_lockCount <= 0)
{
throw new Exception($"Invalid lock-unlock balance for {nameof(EcsFilter)}.");
}
#endif
if (--_lockCount <= 0)
{
for (int i = 0; i < _delayedOpsCount; i++)
{
ref DelayedOp op = ref _delayedOps[i];
if (op.Added)
{
Add(op.Entity);
}
else
{
Remove(op.Entity);
}
}
}
}
public Enumerator GetEnumerator()
{
_lockCount++;
return new Enumerator(this);
}
#endregion
#region Utils
public ref struct Enumerator
{
private readonly EcsGroup _source;
private readonly SparseSet _entities;
private int _index;
private Entity _currentEntity;
public Enumerator(EcsGroup group)
{
_source = group;
_entities = group._entities;
_index = -1;
_currentEntity = new Entity(group.World, -1);
}
public Entity Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
_currentEntity.id = _entities[_index];
return _currentEntity;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
return ++_index < _entities.Count;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose()
{
_source.Unlock();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
_index = -1;
_currentEntity.id = -1;
}
}
private struct DelayedOp
{
public bool Added;
public int Entity;
}
#endregion
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 73f5e1a2319dcb644818c9bd14dcbc5d guid: 8c5769ac232a9c44cbf639847ec56b36
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -1,152 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS.Reflection
{
public static class MemberDeclarator
{
private static Dictionary<string, EcsMemberBase> _nameMembersPairs = new Dictionary<string, EcsMemberBase>(1024);
private static EcsMemberBase[] _members = new EcsMemberBase[1024];
private static int _increment = 1; // 0 индекс всегда пустой, так как он используется в mem<T> для обозначения NULL mem<T>
public static int MembersCount => _increment - 1;
public static EcsMember<T> Declare<T>(string name)
where T : struct
{
name = $"{typeof(T).FullName}__{name}";
#if DEBUG && !DCFA_ECS_NO_SANITIZE_CHECKS
if (_increment < 0)
{
throw new EcsFrameworkException($"Maximum available members exceeded. The member of \"{name}\" was not declared");
}
if (_nameMembersPairs.ContainsKey(name))
{
throw new EcsFrameworkException($"The node with the name \"{name}\" has already been declared");
}
#endif
if (_increment >= _members.Length)
{
Array.Resize(ref _members, _members.Length << 1);
}
EcsMember<T> member = new EcsMember<T>(name, _increment);
_nameMembersPairs.Add(name, member);
_members[_increment++] = member;
return member;
}
public static EcsMember<T> GetOrDeclareMember<T>(string name)
where T : struct
{
if (_nameMembersPairs.TryGetValue(name, out EcsMemberBase memberBase))
{
return (EcsMember<T>)memberBase;
}
return Declare<T>(name);
}
public static EcsMember<T> GetMemberInfo<T>(mem<T> member)
where T : struct
{
#if DEBUG && !DCFA_ECS_NO_SANITIZE_CHECKS
if (member.HasValue == false)
{
throw new ArgumentException($"The mem<{typeof(T).Name}> argument is empty");
}
#endif
return (EcsMember<T>)_members[member.uniqueID];
}
}
public abstract class EcsMemberBase : IEquatable<EcsMemberBase>
{
protected const string TO_STRING_HEADER = "EcsMember:";
protected string _name;
protected int _uniqueID;
protected Type _type;
#region Propertiees
public int UniqueID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _uniqueID;
}
#endregion
#region GetHashCode/ToString
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => _uniqueID;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() => TO_STRING_HEADER + _name;
#endregion
#region Equals
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is EcsMemberBase key && _name == key._name;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(EcsMemberBase other)
{
return _uniqueID == other._uniqueID;
}
#endregion
#region operators
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(in EcsMemberBase left, in EcsMemberBase right) => left.Equals(right);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(in EcsMemberBase left, in EcsMemberBase right) => !left.Equals(right);
#endregion
}
public class EcsMember<T> : EcsMemberBase, IEquatable<EcsMember<T>>
where T : struct
{
#region Constructors
private EcsMember() { }
internal EcsMember(string name, int uniqueID)
{
_name = name;
_uniqueID = uniqueID;
_type = typeof(T);
}
#endregion
#region Equals
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj) => obj is EcsMember<T> key && _uniqueID == key._uniqueID;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(EcsMember<T> other) => _uniqueID == other._uniqueID;
#endregion
#region GetHashCode/ToString
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => _uniqueID;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() => TO_STRING_HEADER + _name;
#endregion
#region operators
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(in EcsMember<T> left, in EcsMember<T> right) => left.Equals(right);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(in EcsMember<T> left, in EcsMember<T> right) => !left.Equals(right);
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public static implicit operator EcsMember<T>(string name) => MemberDeclarator.Declare<T>(name);
#endregion
}
}

View File

@ -1,6 +1,5 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using DCFApixels.DragonECS.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using UnityEngine; using UnityEngine;
using System; using System;
@ -13,8 +12,6 @@ namespace DCFApixels.DragonECS
{ {
public EcsWorld World { get; } public EcsWorld World { get; }
public int ID { get; } public int ID { get; }
public EcsMemberBase Type { get; }
public bool IsTagsPool { get; }
public bool Has(int index); public bool Has(int index);
public void Add(int index); public void Add(int index);
public void Del(int index); public void Del(int index);
@ -23,72 +20,54 @@ namespace DCFApixels.DragonECS
public class EcsPool<T> : IEcsPool public class EcsPool<T> : IEcsPool
where T : struct where T : struct
{ {
private int _id; private readonly int _id;
private readonly EcsWorld _source; private readonly EcsWorld _source;
private readonly EcsMember<T> _type;
private readonly SparseSet _sparseSet; private readonly SparseSet _sparseSet;
private T[] _denseItems; private T[] _denseItems;
private int _isTagsPoolMask;
#region Properites #region Properites
public EcsWorld World => _source; public EcsWorld World => _source;
public EcsMemberBase Type => _type; public int ID => _id;
public int ID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _id;
}
public bool IsTagsPool
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _isTagsPoolMask < 0;
}
public ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref _denseItems[_sparseSet[index] | _isTagsPoolMask];
}
#endregion #endregion
#region Constructors #region Constructors
public EcsPool(EcsWorld source, mem<T> type, int capacity) public EcsPool(EcsWorld source, int capacity)
{ {
_source = source; _source = source;
_type = MemberDeclarator.GetMemberInfo(type);
_sparseSet = new SparseSet(capacity); _sparseSet = new SparseSet(capacity);
_isTagsPoolMask = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0 ? -1 : 0; _denseItems =new T[capacity];
_denseItems = IsTagsPool ? new T[1] : new T[capacity];
} }
#endregion #endregion
#region Add/Has/Get/Del #region Read/Write/Has/Del
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref readonly T Read(int index)
{
return ref _denseItems[_sparseSet[index]];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Write(int index)
{
return ref _denseItems[_sparseSet[index]];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Add(int index) public ref T Add(int index)
{ {
_sparseSet.Add(index); _sparseSet.Add(index);
if(IsTagsPool) _sparseSet.Normalize(ref _denseItems);
{ return ref _denseItems[_sparseSet.IndexOf(index)];
_sparseSet.Normalize(ref _denseItems);
return ref _denseItems[_sparseSet.IndexOf(index)];
}
return ref _denseItems[0];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int index) public bool Has(int index)
{ {
return _sparseSet.Contains(index); return _sparseSet.Contains(index);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Del(int index) public void Del(int index)
{ {
if (!IsTagsPool) { this[index] = default; }
_sparseSet.Remove(index); _sparseSet.Remove(index);
} }
#endregion #endregion
@ -105,7 +84,7 @@ namespace DCFApixels.DragonECS
{ {
return base.Equals(obj); return base.Equals(obj);
} }
public override int GetHashCode() => _type.GetHashCode(); public override int GetHashCode() => _source.GetHashCode() + ID;
#endregion #endregion
} }
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
@ -18,8 +19,6 @@ namespace DCFApixels.DragonECS
private Dictionary<string, EcsWorld> _worldsDict = new Dictionary<string, EcsWorld>(); private Dictionary<string, EcsWorld> _worldsDict = new Dictionary<string, EcsWorld>();
private List<EcsWorld> _worlds = new List<EcsWorld>(); private List<EcsWorld> _worlds = new List<EcsWorld>();
private Dictionary<Type, IEcsProcessorsRunner> _runners; private Dictionary<Type, IEcsProcessorsRunner> _runners;
private Dictionary<Type, IEcsProcessorsMessenger> _messengers; private Dictionary<Type, IEcsProcessorsMessenger> _messengers;
private EcsProcessorsRunner<_Run> _runRunnerCache; private EcsProcessorsRunner<_Run> _runRunnerCache;
@ -42,11 +41,20 @@ namespace DCFApixels.DragonECS
_runners.Add(type, result); _runners.Add(type, result);
return (EcsProcessorsRunner<TDoTag>)result; return (EcsProcessorsRunner<TDoTag>)result;
} }
internal void OnRunnerDetroyed<TDoTag>(EcsProcessorsRunner<TDoTag> target)
where TDoTag : IEcsDoTag
{
Type type = typeof(TDoTag);
if (_runners.ContainsKey(type))
{
_runners.Remove(type);
}
}
public EcsProcessorsMessenger<TMessege> GetMessenger<TMessege>() public EcsProcessorsMessenger<TMessege> GetMessenger<TMessege>()
where TMessege : IEcsMessage where TMessege : IEcsMessage
{ {
Type type = typeof(TMessege); Type type = typeof(EcsProcessorsMessenger<TMessege>);
if (_messengers.TryGetValue(type, out IEcsProcessorsMessenger result)) if (_messengers.TryGetValue(type, out IEcsProcessorsMessenger result))
{ {
return (EcsProcessorsMessenger<TMessege>)result; return (EcsProcessorsMessenger<TMessege>)result;
@ -55,6 +63,27 @@ namespace DCFApixels.DragonECS
_messengers.Add(type, result); _messengers.Add(type, result);
return (EcsProcessorsMessenger<TMessege>)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
{
Type type = typeof(TMessege);
if (_messengers.ContainsKey(type))
{
_messengers.Remove(type);
}
}
#endregion #endregion
#region Configuration #region Configuration
@ -115,5 +144,20 @@ namespace DCFApixels.DragonECS
throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после уничтожения {nameof(EcsSession)}"); throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после уничтожения {nameof(EcsSession)}");
} }
#endregion #endregion
#region EntityConvert
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Entity ToEntity(in ent target)
{
throw new NotImplementedException();
// return new Entity(null, target.id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ent ToEnt(in Entity target)
{
throw new NotImplementedException();
// return new ent(target.id, target.world._gens[target.id], -1000);
}
#endregion
} }
} }

View File

@ -14,9 +14,10 @@ namespace DCFApixels.DragonECS
private byte _id = DEAD_WORLD_ID; private byte _id = DEAD_WORLD_ID;
private IEcsPool[] _pools; private float _timeScale;//TODO реализовать собсвенныйтайм склей для разных миров
private SparseSet _memToPoolIDSet;
private IEcsPool[] _pools;
private SparseSet _componentIDToPoolID;
private SparseSet _entities = new SparseSet(); private SparseSet _entities = new SparseSet();
private short[] _gens; private short[] _gens;
@ -34,32 +35,35 @@ namespace DCFApixels.DragonECS
public EcsWorld() public EcsWorld()
{ {
_pools = new IEcsPool[512]; _pools = new IEcsPool[512];
_entities = new SparseSet(); _entities = new SparseSet(512);
_memToPoolIDSet = new SparseSet(512); _componentIDToPoolID = new SparseSet(512);
}
#endregion
#region ID
internal void SetId(byte id)
{
_id = id;
} }
#endregion #endregion
#region GetPool #region GetPool
public EcsPool<T> GetPool<T>(mem<T> member) public EcsPool<T> GetPool<T>()
where T : struct where T : struct
{ {
if(_memToPoolIDSet.Contains(member.uniqueID)) int uniqueID = ComponentType<T>.uniqueID;
int poolIndex = _componentIDToPoolID.IndexOf(uniqueID);
if (_pools.TryGetValue(type, out IEcsPool pool)) if (poolIndex >= 0)
{ {
return (EcsPool<T>)pool; return (EcsPool<T>)_pools[poolIndex];
} }
#if DEBUG
if (_componentIDToPoolID.Count >= ushort.MaxValue)
{
throw new EcsFrameworkException("No more room for new component into this world.");
}
#endif
var pool = new EcsPool<T>(this, 512);
_componentIDToPoolID.Add(uniqueID);
_componentIDToPoolID.Normalize(ref _pools);
_componentIDToPoolID.Normalize(ref _filtersByIncludedComponents);
_componentIDToPoolID.Normalize(ref _filtersByExcludedComponents);
pool = new EcsPool<T>(this, member, 512);//TODO сделать чтоб объем можно было указывать через конфиг _pools[_componentIDToPoolID.IndexOf(poolIndex)] = pool;
_pools.Add(type, pool); return pool;
return (EcsPool<T>)pool;
} }
#endregion #endregion
@ -82,13 +86,77 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
internal void OnEntityFieldAdd(int entityID, int changedPool) [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool IsMaskCompatible(Mask filterMask, int entity)
{ {
for (int i = 0, iMax = filterMask.includeCount; i < iMax; i++)
{
if (!_pools[filterMask.include[i]].Has(entity))
{
return false;
}
}
for (int i = 0, iMax = filterMask.excludeCount; i < iMax; i++)
{
if (_pools[filterMask.exclude[i]].Has(entity))
{
return false;
}
}
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool IsMaskCompatibleWithout(Mask filterMask, int entity, int componentId)
{
for (int i = 0, iMax = filterMask.includeCount; i < iMax; i++)
{
var typeId = filterMask.include[i];
if (typeId == componentId || !_pools[typeId].Has(entity))
{
return false;
}
}
for (int i = 0, iMax = filterMask.excludeCount; i < iMax; i++)
{
var typeId = filterMask.exclude[i];
if (typeId != componentId && _pools[typeId].Has(entity))
{
return false;
}
}
return true;
}
internal void OnEntityComponentAdded(int entityID, int changedPoolID)
{
var includeList = _filtersByIncludedComponents[changedPoolID];
var excludeList = _filtersByExcludedComponents[changedPoolID];
if (includeList != null)
{
foreach (var filter in includeList)
{
if (IsMaskCompatible(filter.Mask, entityID))
{
filter.Add(entityID);
}
}
}
if (excludeList != null)
{
foreach (var filter in excludeList)
{
if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID))
{
filter.Remove(entityID);
}
}
}
} }
internal void OnEntityFieldDel(int entityID, int changedPool) internal void OnEntityComponentRemoved(int entityID, int changedPool)
{ {
} }
@ -101,7 +169,7 @@ namespace DCFApixels.DragonECS
internal int[] exclude; internal int[] exclude;
internal int includeCount; internal int includeCount;
internal int excludeCount; internal int excludeCount;
internal int hash;
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS #if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
bool _built; bool _built;
#endif #endif
@ -119,16 +187,15 @@ namespace DCFApixels.DragonECS
{ {
includeCount = 0; includeCount = 0;
excludeCount = 0; excludeCount = 0;
hash = 0;
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS #if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
_built = false; _built = false;
#endif #endif
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Mask Inc<T>(mem<T> member) where T : struct public Mask Inc<T>() where T : struct
{ {
var poolId = _world.GetPool(member).ID; var poolId = _world.GetPool<T>().ID;
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS #if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
if (_built) { throw new Exception("Cant change built mask."); } if (_built) { throw new Exception("Cant change built mask."); }
if (Array.IndexOf(include, poolId, 0, includeCount) != -1) { throw new Exception($"{typeof(T).Name} already in constraints list."); } if (Array.IndexOf(include, poolId, 0, includeCount) != -1) { throw new Exception($"{typeof(T).Name} already in constraints list."); }
@ -140,9 +207,9 @@ namespace DCFApixels.DragonECS
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Mask Exc<T>(mem<T> member) where T : struct public Mask Exc<T>() where T : struct
{ {
var poolId = _world.GetPool(member).ID; var poolId = _world.GetPool<T>().ID;
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS #if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
if (_built) { throw new Exception("Cant change built mask."); } if (_built) { throw new Exception("Cant change built mask."); }
if (Array.IndexOf(include, poolId, 0, includeCount) != -1) { throw new Exception($"{typeof(T).Name} already in constraints list."); } if (Array.IndexOf(include, poolId, 0, includeCount) != -1) { throw new Exception($"{typeof(T).Name} already in constraints list."); }
@ -152,6 +219,32 @@ namespace DCFApixels.DragonECS
exclude[excludeCount++] = poolId; exclude[excludeCount++] = poolId;
return this; return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsFilter End(int capacity = 512)
{
#if DEBUG && !LEOECSLITE_NO_SANITIZE_CHECKS
if (_built) { throw new Exception("Cant change built mask."); }
_built = true;
#endif
Array.Sort(include, 0, includeCount);
Array.Sort(exclude, 0, excludeCount);
var (filter, isNew) = _world.GetFilterInternal(this, capacity);
if (!isNew) { Recycle(); }
return filter;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void Recycle()
{
Reset();
if (_world._masksCount == _world._masks.Length)
{
Array.Resize(ref _world._masks, _world._masksCount << 1);
}
_world._masks[_world._masksCount++] = this;
}
} }
} }
} }

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 9478c808aeb8de24a883819991780c9b guid: c53ca292f39cf9d48a0bb60a65fc1232
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -5,10 +5,9 @@ namespace DCFApixels.DragonECS
[Serializable] [Serializable]
public class EcsFrameworkException : Exception public class EcsFrameworkException : Exception
{ {
private const string MESSAGE_SUFFIX = "[DragonECS] ";
public EcsFrameworkException() { } public EcsFrameworkException() { }
public EcsFrameworkException(string message) : base(MESSAGE_SUFFIX + message) { } public EcsFrameworkException(string message) : base(Exceptions.MESSAGE_SUFFIX + message) { }
public EcsFrameworkException(string message, Exception inner) : base(MESSAGE_SUFFIX + message, inner) { } public EcsFrameworkException(string message, Exception inner) : base(Exceptions.MESSAGE_SUFFIX + message, inner) { }
protected EcsFrameworkException( protected EcsFrameworkException(
System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { } System.Runtime.Serialization.StreamingContext context) : base(info, context) { }

View File

@ -0,0 +1,15 @@
using System;
namespace DCFApixels.DragonECS
{
[Serializable]
public class EcsReactException : Exception
{
public EcsReactException() { }
public EcsReactException(string message) : base(Exceptions.MESSAGE_SUFFIX + message) { }
public EcsReactException(string message, Exception inner) : base(Exceptions.MESSAGE_SUFFIX + message, inner) { }
protected EcsReactException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}

View File

@ -0,0 +1,7 @@
namespace DCFApixels.DragonECS
{
internal static class Exceptions
{
public const string MESSAGE_SUFFIX = "[DragonECS] ";
}
}

View File

@ -0,0 +1,7 @@
namespace DCFApixels.DragonECS
{
public interface IEcsComponentReset<T>
{
public void Reset(ref T component);
}
}

View File

@ -8,15 +8,15 @@
public struct _Run : IEcsDoTag { } public struct _Run : IEcsDoTag { }
public struct _Destroy : IEcsDoTag { } public struct _Destroy : IEcsDoTag { }
public struct _PostDestroy : IEcsDoTag { } public struct _PostDestroy : IEcsDoTag { }
public interface IEcsDo<TTag> : IEcsProcessor public interface IDo<TTag> : IEcsProcessor
where TTag : IEcsDoTag where TTag : IEcsDoTag
{ {
public void Do(EcsSession session); public void Do(EcsSession session);
} }
public interface IEcsSimpleCycleProcessor : public interface IEcsSimpleCycleProcessor :
IEcsDo<_Init>, IDo<_Init>,
IEcsDo<_Run>, IDo<_Run>,
IEcsDo<_Destroy> IDo<_Destroy>
{ } { }
@ -40,9 +40,32 @@
} }
} }
public interface IEcsDoMessege<TMessage> : IEcsProcessor public readonly struct _OnInject<T> : IEcsMessage
{
public readonly T data;
public _OnInject(T data)
{
this.data = data;
}
}
public interface IReceive<TMessage> : IEcsProcessor
where TMessage : IEcsMessage where TMessage : IEcsMessage
{ {
public void Do(EcsSession session, in TMessage message); 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);
} }
} }

View File

@ -5,7 +5,6 @@ using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)] [StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
public readonly struct ent : IEquatable<long>, IEquatable<ent> public readonly struct ent : IEquatable<long>, IEquatable<ent>
{ {
@ -13,10 +12,10 @@ namespace DCFApixels.DragonECS
// id - 32 bits // id - 32 bits
// gen - 16 bits // gen - 16 bits
// world - 8 bits // world - 16 bits
// empty - 8 bits
public readonly long _full; public readonly long _full;
#region Properties
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public int id public int id
{ {
@ -30,30 +29,23 @@ namespace DCFApixels.DragonECS
get => (short)((_full << 32) >> 48); get => (short)((_full << 32) >> 48);
} }
// 255 = однозначно указывает что сущьность мертва или NULL
// но чтобы значене default было NULL сульностью, мир хранится в виде ID + 1 // но чтобы значене default было NULL сульностью, мир хранится в виде ID + 1
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public byte world public short world
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (byte)(((_full << 48) >> 56) - 1); get => (short)(((_full << 48) >> 48) - 1);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public byte type
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (byte)((_full << 56) >> 56);
} }
#endregion
#region Constructors
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public ent(int id, short gen, byte world) public ent(int id, short gen, short world)
{ {
_full = ((long)id) << 32; _full = ((long)id) << 32;
_full += ((long)gen) << 16; _full += ((long)gen) << 16;
_full += ((long)(++world)) << 8; // сдвиг айдишников + 1 _full += ++world; // сдвиг айдишников + 1
//_full += ...;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -61,6 +53,7 @@ namespace DCFApixels.DragonECS
{ {
_full = value; _full = value;
} }
#endregion
#region GetHashCode #region GetHashCode
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -103,6 +96,9 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator long(in ent eent) => eent._full; public static implicit operator long(in ent eent) => eent._full;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator int(in ent eent) => eent.id;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ent(in long value) => new ent(value); public static implicit operator ent(in long value) => new ent(value);
#endregion #endregion
@ -114,5 +110,21 @@ namespace DCFApixels.DragonECS
{ {
return self == ent.NULL; return self == ent.NULL;
} }
public static Entity UseIn(in ent self, EcsSession session)
{
session.GetWorld()
}
}
public ref struct Entity
{
internal EcsWorld world;
internal int id;
public Entity(EcsWorld world, int id)
{
this.world = world;
this.id = id;
}
} }
} }

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e85a87d0753512d4bb7b365dd451701a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,56 +0,0 @@
using System;
using System.Runtime.CompilerServices;
using DCFApixels.DragonECS.Reflection;
namespace DCFApixels.DragonECS
{
public readonly struct mem<T> : IEquatable<mem<T>>, IEquatable<int>
where T : struct
{
public static readonly mem<T> NULL = default;
internal readonly int uniqueID;
#region Properties
public bool HasValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => uniqueID != 0;
}
#endregion
#region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private mem(int uniqueID) => this.uniqueID = uniqueID;
#endregion
#region Equals
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj) => obj is mem<T> key && uniqueID == key.uniqueID;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(mem<T> other) => uniqueID == other.uniqueID;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(int other) => uniqueID == other;
#endregion
#region GetHashCode/ToString
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => uniqueID;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() => HasValue ? MemberDeclarator.GetMemberInfo(this).ToString() : "NULL";
#endregion
#region operators
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(in mem<T> left, in mem<T> right) => left.Equals(right);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(in mem<T> left, in mem<T> right) => !left.Equals(right);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator mem<T>(string name) => new mem<T>(MemberDeclarator.GetOrDeclareMember<T>(name).UniqueID);
#endregion
}
}

17
src/Primitives/proto.cs Normal file
View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
[StructLayout(LayoutKind.Sequential)]
public readonly struct proto
{
private readonly ent entity;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7b8a6b01f9e4e6041a681eadec261c55
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +0,0 @@
using System;
namespace DCFApixels.DragonECS
{
public struct tag { }
}

View File

@ -0,0 +1,39 @@
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
public class EcsProcessorsGMessenger<TMessage> : IEcsProcessorsMessenger<TMessage>
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);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d340db685521a624792157f350923088
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -6,23 +6,24 @@ namespace DCFApixels.DragonECS
{ {
public EcsSession Source { get; } public EcsSession Source { get; }
} }
public class EcsProcessorsMessenger<TMessage> : IEcsProcessorsMessenger public interface IEcsProcessorsMessenger<TMessage> : IEcsProcessorsMessenger where TMessage : IEcsMessage { }
public class EcsProcessorsMessenger<TMessage> : IEcsProcessorsMessenger<TMessage>
where TMessage : IEcsMessage where TMessage : IEcsMessage
{ {
private EcsSession _source; private readonly EcsSession _source;
private IEcsDoMessege<TMessage>[] _targets; private readonly IReceive<TMessage>[] _targets;
public EcsSession Source => _source; public EcsSession Source => _source;
public IReadOnlyList<IEcsDoMessege<TMessage>> Systems => _targets; public IReadOnlyList<IReceive<TMessage>> Targets => _targets;
internal EcsProcessorsMessenger(EcsSession source) internal EcsProcessorsMessenger(EcsSession source)
{ {
_source = source; _source = source;
List<IEcsDoMessege<TMessage>> list = new List<IEcsDoMessege<TMessage>>(); List<IReceive<TMessage>> list = new List<IReceive<TMessage>>();
foreach (var item in _source.AllProcessors) foreach (var item in _source.AllProcessors)
{ {
if (item is IEcsDoMessege<TMessage> targetItem) if (item is IReceive<TMessage> targetItem)
{ {
list.Add(targetItem); list.Add(targetItem);
} }
@ -34,8 +35,10 @@ namespace DCFApixels.DragonECS
{ {
foreach (var item in _targets) foreach (var item in _targets)
{ {
item.Do(_source, message); item.Do(_source, in message);
} }
} }
public void Destroy() => _source.OnMessengerDetroyed(this);
} }
} }

View File

@ -10,20 +10,20 @@ namespace DCFApixels.DragonECS
public class EcsProcessorsRunner<TDoTag> : IEcsProcessorsRunner public class EcsProcessorsRunner<TDoTag> : IEcsProcessorsRunner
where TDoTag : IEcsDoTag where TDoTag : IEcsDoTag
{ {
private EcsSession _source; private readonly EcsSession _source;
private IEcsDo<TDoTag>[] _targets; private readonly IDo<TDoTag>[] _targets;
public EcsSession Source => _source; public EcsSession Source => _source;
public IReadOnlyList<IEcsDo<TDoTag>> Systems => _targets; public IReadOnlyList<IDo<TDoTag>> Targets => _targets;
internal EcsProcessorsRunner(EcsSession source) internal EcsProcessorsRunner(EcsSession source)
{ {
_source = source; _source = source;
List<IEcsDo<TDoTag>> list = new List<IEcsDo<TDoTag>>(); List<IDo<TDoTag>> list = new List<IDo<TDoTag>>();
foreach (var item in _source.AllProcessors) foreach (var item in _source.AllProcessors)
{ {
if (item is IEcsDo<TDoTag> targetItem) if (item is IDo<TDoTag> targetItem)
{ {
list.Add(targetItem); list.Add(targetItem);
} }
@ -38,5 +38,7 @@ namespace DCFApixels.DragonECS
item.Do(_source); item.Do(_source);
} }
} }
public void Destroy() => _source.OnRunnerDetroyed(this);
} }
} }

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
internal abstract class ComponentType
{
protected static int _increment = 0;
}
internal sealed class ComponentType<T> : ComponentType
{
internal static int uniqueID = _increment++;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cef3dbf379d584346bc8a9313c22c563
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
public class CompressedBitMask
{
private const int CHUNK = 32; //int bits
private int[] _fullChunkIndexes; // индексы чанков с полным заполнением
private int[] _sparseIndexes;
private int[] _denseMasks;
private int _highBit = 0;
public int HightBit => _highBit;
public void Set(int[] indexes, int count)
{
}
public ref struct EqualsRequest
{
private CompressedBitMask _source;
private CompressedBitMask _other;
public void GetEnumerator() =>
}
public ref struct Enumerator
{
private readonly int[] _indexes;
private readonly int[] _masks;
private int _index;
public Enumerator(int[] indexes, int[] masks)
{
_indexes = indexes;
_masks = masks;
_index = -1;
}
public int Current
{
get => 0;
}
public void Dispose() { }
public bool MoveNext()
{
}
public void Reset()
{
_index = -1;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f88c761abb374574fba2ac5aa2d5e41a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,177 +1,156 @@
// _sparse[value] == index using System;
// _dense[index] == value
//
// int[] _dense => |2|4|1|_|_|
// int[] _sparse => |_|2|0|_|1|
//
// indexator => [0]2, [1]4, [2]1
//
// can use foreach
// implements IEnumerable<int>
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using coretype = System.Int32;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public class SparseSet : IEnumerable<int>, ICollection<int>, IReadOnlyCollection<int> public class SparseSet : IEnumerable<coretype>, ICollection<coretype>, IReadOnlyCollection<coretype>
{ {
public const int DEFAULT_CAPACITY = 16; public const int DEFAULT_CAPACITY = 16;
public const int MAX_CAPACITY = coretype.MaxValue;
private int[] _dense; private coretype[] _dense;
private int[] _sparse; private coretype[] _sparse;
private int _count; private coretype _count;
private coretype _denseCapacity;
#region Properties #region Properties
public int Count => _count; public int Count => _count;
public int Capacity => _dense.Length; public int CapacityDense
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _denseCapacity;
}
public int CapacitySparse
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _dense.Length;
}
public int this[int index] public coretype this[int index]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
#if DEBUG #if DEBUG
get get
{ {
ThrowHalper.CheckOutOfRange(this, index); ThrowHalper.CheckOutOfRange(this, (coretype)index);
return _dense[index]; return _dense[index];
} }
#else #else
get => _dense[index]; get => _dense[index];
#endif #endif
} }
public IndexesCollection Indexes => new IndexesCollection(_sparse);
#endregion #endregion
#region Constructors #region Constructors
public SparseSet() : this(DEFAULT_CAPACITY) { } public SparseSet() : this(DEFAULT_CAPACITY) { }
public SparseSet(int capacity) public SparseSet(coretype capacity)
{ {
#if DEBUG #if DEBUG
ThrowHalper.CheckCapacity(capacity); ThrowHalper.CheckCapacity(capacity);
#endif #endif
_dense = new int[capacity]; _dense = new coretype[capacity];
_sparse = new int[capacity]; _sparse = new coretype[capacity];
for (int i = 0; i < _sparse.Length; i++) for (coretype i = 0; i < _sparse.Length; i++)
{ {
_dense[i] = i; _dense[i] = i;
_sparse[i] = i; _sparse[i] = i;
} }
_count = 0; _count = 0;
_denseCapacity = 0;
} }
#endregion #endregion
#region Add/AddRange/GetFree #region Add/AddRange/GetFree
public void Add<T>(int value, ref T[] normalizedArray) public void Add<T>(coretype value, ref T[] normalizedArray)
{ {
Add(value); Add(value);
Normalize(ref normalizedArray); Normalize(ref normalizedArray);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(int value) public void Add(coretype value)
{ {
#if DEBUG #if DEBUG
ThrowHalper.CheckValueIsPositive(value); ThrowHalper.CheckValueIsPositive(value);
ThrowHalper.CheckValueNotContained(this, value); ThrowHalper.CheckValueNotContained(this, value);
#endif #endif
if (value > CapacitySparse)
int neadedSpace = _dense.Length;
while (value >= neadedSpace)
neadedSpace <<= 1;
if (neadedSpace != _dense.Length)
Resize(neadedSpace);
if (Contains(value))
{ {
return; coretype neadedSpace = (coretype)_dense.Length;
while (value >= neadedSpace) neadedSpace <<= 1;
Resize(neadedSpace);
} }
Swap(value, _count++); Swap(value, _count++);
if (_count > _denseCapacity) _denseCapacity <<= 1;
} }
public bool TryAdd<T>(int value, ref T[] normalizedArray) public bool TryAdd<T>(coretype value, ref T[] normalizedArray)
{ {
if (Contains(value)) if (Contains(value)) return false;
return false; Add(value);
Normalize(ref normalizedArray);
Add(value, ref normalizedArray);
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryAdd(int value) public bool TryAdd(coretype value)
{ {
if (Contains(value)) if (Contains(value)) return false;
return false;
Add(value); Add(value);
return true; return true;
} }
public void AddRange<T>(IEnumerable<int> range, ref T[] normalizedArray) public void AddRange<T>(IEnumerable<coretype> range, ref T[] normalizedArray)
{ {
foreach (var item in range) AddRange(range);
{
if (Contains(item))
continue;
Add(item);
}
Normalize(ref normalizedArray); Normalize(ref normalizedArray);
} }
public void AddRange(IEnumerable<coretype> range)
public void AddRange(IEnumerable<int> range)
{ {
foreach (var item in range) foreach (var item in range)
{ {
if (Contains(item)) if (Contains(item)) continue;
continue;
Add(item); Add(item);
} }
} }
/// <summary>
/// Adds a value between 0 and Capacity to the array and returns it. /// <summary>Adds a value between 0 and Capacity to the array and returns it.</summary>
/// </summary>
/// <returns>Value between 0 and Capacity</returns> /// <returns>Value between 0 and Capacity</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetFree<T>(ref T[] normalizedArray) public coretype GetFree<T>(ref T[] normalizedArray)
{ {
int result = GetFree(); coretype result = GetFree();
Normalize(ref normalizedArray); Normalize(ref normalizedArray);
return result; return result;
} }
/// <summary> /// <summary>Adds a value between 0 and Capacity to the array and returns it.</summary>
/// Adds a value between 0 and Capacity to the array and returns it.
/// </summary>
/// <returns>Value between 0 and Capacity</returns> /// <returns>Value between 0 and Capacity</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetFree() public coretype GetFree()
{ {
if (++_count >= _dense.Length) if (++_count >= CapacitySparse) AddSpaces();
AddSpaces(); if (_count > _denseCapacity) _denseCapacity <<= 1;
return _dense[_count - 1]; return _dense[_count - 1];
} }
#endregion #endregion
#region Contains #region Contains
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(int value) public bool Contains(coretype value)
{ {
return value >= 0 && value < Capacity && _sparse[value] < _count; return value >= 0 && value < CapacitySparse && _sparse[value] < _count;
} }
#endregion #endregion
#region Remove #region Remove
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Remove(int value) public void Remove(coretype value)
{ {
#if DEBUG #if DEBUG
ThrowHalper.CheckValueContained(this, value); ThrowHalper.CheckValueContained(this, value);
@ -179,17 +158,15 @@ namespace DCFApixels.DragonECS
Swap(_sparse[value], --_count); Swap(_sparse[value], --_count);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryRemove(int value) public bool TryRemove(coretype value)
{ {
if (!Contains(value)) if (!Contains(value)) return false;
return false;
Remove(value); Remove(value);
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveAt(int index) public void RemoveAt(coretype index)
{ {
#if DEBUG #if DEBUG
ThrowHalper.CheckOutOfRange(this, index); ThrowHalper.CheckOutOfRange(this, index);
@ -202,23 +179,20 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Normalize<T>(ref T[] array) public void Normalize<T>(ref T[] array)
{ {
if (array.Length != _dense.Length) if (array.Length < CapacityDense) Array.Resize(ref array, CapacityDense);
Array.Resize(ref array, _dense.Length);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int IndexOf(int value) public int IndexOf(coretype value)
{ {
if (value < 0 || !Contains(value)) if (value < 0 || !Contains(value)) return -1;
return -1;
return _sparse[value]; return _sparse[value];
} }
public void Sort() public void Sort()
{ {
int increment = 0; coretype increment = 0;
for (int i = 0; i < Capacity; i++) for (coretype i = 0; i < CapacitySparse; i++)
{ {
if (_sparse[i] < _count) if (_sparse[i] < _count)
{ {
@ -230,9 +204,9 @@ namespace DCFApixels.DragonECS
public void HardSort() public void HardSort()
{ {
int inc = 0; coretype inc = 0;
int inc2 = _count; coretype inc2 = _count;
for (int i = 0; i < Capacity; i++) for (coretype i = 0; i < CapacitySparse; i++)
{ {
if (_sparse[i] < _count) if (_sparse[i] < _count)
{ {
@ -250,21 +224,19 @@ namespace DCFApixels.DragonECS
public void CopyTo(SparseSet other) public void CopyTo(SparseSet other)
{ {
other._count = _count; other._count = _count;
if (Capacity != other.Capacity) if (CapacitySparse != other.CapacitySparse)
{ {
other.Resize(Capacity); other.Resize(CapacitySparse);
} }
_dense.CopyTo(other._dense, 0); _dense.CopyTo(other._dense, 0);
_sparse.CopyTo(other._sparse, 0); _sparse.CopyTo(other._sparse, 0);
} }
public void CopyTo(int[] array, int arrayIndex) public void CopyTo(coretype[] array, int arrayIndex)
{ {
#if DEBUG #if DEBUG
if (arrayIndex < 0) if (arrayIndex < 0) throw new ArgumentException("arrayIndex is less than 0");
throw new ArgumentException("arrayIndex is less than 0"); if (arrayIndex + _count >= array.Length) throw new ArgumentException("The number of elements in the source List<T> is greater than the available space from arrayIndex to the end of the destination array.");
if (arrayIndex + _count >= array.Length)
throw new ArgumentException("The number of elements in the source List<T> is greater than the available space from arrayIndex to the end of the destination array.");
#endif #endif
for (int i = 0; i < _count; i++, arrayIndex++) for (int i = 0; i < _count; i++, arrayIndex++)
{ {
@ -275,21 +247,17 @@ namespace DCFApixels.DragonECS
#region Clear/Reset #region Clear/Reset
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear() public void Clear() => _count = 0;
{
_count = 0;
}
public void Reset() public void Reset()
{ {
Clear(); Clear();
for (int i = 0; i < _dense.Length; i++) for (coretype i = 0; i < _dense.Length; i++)
{ {
_dense[i] = i; _dense[i] = i;
_sparse[i] = i; _sparse[i] = i;
} }
} }
public void Reset(int newCapacity) public void Reset(coretype newCapacity)
{ {
#if DEBUG #if DEBUG
ThrowHalper.CheckCapacity(newCapacity); ThrowHalper.CheckCapacity(newCapacity);
@ -301,16 +269,16 @@ namespace DCFApixels.DragonECS
#region AddSpace/Resize #region AddSpace/Resize
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void AddSpaces() => Resize(_count << 1); private void AddSpaces() => Resize((_count << 1));
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Resize(int newSpace) private void Resize(int newSpace)
{ {
int oldspace = _dense.Length; coretype oldspace = (short)_dense.Length;
Array.Resize(ref _dense, newSpace); Array.Resize(ref _dense, newSpace);
Array.Resize(ref _sparse, newSpace); Array.Resize(ref _sparse, newSpace);
for (int i = oldspace; i < newSpace; i++) for (coretype i = oldspace; i < newSpace; i++)
{ {
_dense[i] = i; _dense[i] = i;
_sparse[i] = i; _sparse[i] = i;
@ -320,10 +288,10 @@ namespace DCFApixels.DragonECS
#region Swap #region Swap
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Swap(int fromIndex, int toIndex) private void Swap(coretype fromIndex, coretype toIndex)
{ {
int value = _dense[toIndex]; coretype value = _dense[toIndex];
int oldValue = _dense[fromIndex]; coretype oldValue = _dense[fromIndex];
_dense[toIndex] = oldValue; _dense[toIndex] = oldValue;
_dense[fromIndex] = value; _dense[fromIndex] = value;
@ -338,19 +306,19 @@ namespace DCFApixels.DragonECS
public ref struct RefEnumerator public ref struct RefEnumerator
{ {
private readonly int[] _dense; private readonly coretype[] _dense;
private readonly int _count; private readonly coretype _count;
private int _index; private coretype _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public RefEnumerator(int[] values, int count) public RefEnumerator(coretype[] values, coretype count)
{ {
_dense = values; _dense = values;
_count = count; _count = count;
_index = -1; _index = -1;
} }
public int Current public coretype Current
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _dense[_index]; get => _dense[_index];
@ -366,20 +334,20 @@ namespace DCFApixels.DragonECS
public void Reset() => _index = -1; public void Reset() => _index = -1;
} }
IEnumerator<int> IEnumerable<int>.GetEnumerator() => new Enumerator(_dense, _count); IEnumerator<coretype> IEnumerable<coretype>.GetEnumerator() => new Enumerator(_dense, _count);
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(_dense, _count); IEnumerator IEnumerable.GetEnumerator() => new Enumerator(_dense, _count);
public struct Enumerator : IEnumerator<int> //to implement the IEnumerable interface and use the ref structure, 2 Enumerators were created. public struct Enumerator : IEnumerator<coretype> //to implement the IEnumerable interface and use the ref structure, 2 Enumerators were created.
{ {
private readonly int[] _dense; private readonly coretype[] _dense;
private readonly int _count; private readonly coretype _count;
private int _index; private coretype _index;
public Enumerator(int[] values, int count) public Enumerator(coretype[] values, coretype count)
{ {
_dense = values; _dense = values;
_count = count; _count = count;
_index = -1; _index = -1;
} }
public int Current => _dense[_index]; public coretype Current => _dense[_index];
object IEnumerator.Current => _dense[_index]; object IEnumerator.Current => _dense[_index];
public void Dispose() { } public void Dispose() { }
public bool MoveNext() => ++_index < _count; public bool MoveNext() => ++_index < _count;
@ -387,55 +355,38 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
#region Utils
public ref struct IndexesCollection
{
private readonly int[] _indexes;
public IndexesCollection(int[] indexes)
{
_indexes = indexes;
}
public int this[int value]
{
get => _indexes[value];
}
}
#endregion
#region ICollection #region ICollection
bool ICollection<int>.IsReadOnly => false; bool ICollection<coretype>.IsReadOnly => false;
bool ICollection<int>.Remove(int value) => TryRemove(value); bool ICollection<coretype>.Remove(coretype value) => TryRemove(value);
#endregion #endregion
#region Debug #region Debug
public string Log() public string Log()
{ {
StringBuilder logbuild = new StringBuilder(); StringBuilder logbuild = new StringBuilder();
for (int i = 0; i < Capacity; i++) for (int i = 0; i < CapacitySparse; i++)
{ {
logbuild.Append(_dense[i] + ", "); logbuild.Append(_dense[i] + ", ");
} }
logbuild.Append("\n\r"); logbuild.Append("\n\r");
for (int i = 0; i < Capacity; i++) for (int i = 0; i < CapacitySparse; i++)
{ {
logbuild.Append(_sparse[i] + ", "); logbuild.Append(_sparse[i] + ", ");
} }
logbuild.Append("\n\r --------------------------"); logbuild.Append("\n\r --------------------------");
logbuild.Append("\n\r"); logbuild.Append("\n\r");
for (int i = 0; i < Capacity; i++) for (int i = 0; i < CapacitySparse; i++)
{ {
logbuild.Append((i < _count ? _dense[i].ToString() : "_") + ", "); logbuild.Append((i < _count ? _dense[i].ToString() : "_") + ", ");
} }
logbuild.Append("\n\r"); logbuild.Append("\n\r");
for (int i = 0; i < Capacity; i++) for (int i = 0; i < CapacitySparse; i++)
{ {
logbuild.Append((_sparse[i] < _count ? _sparse[i].ToString() : "_") + ", "); logbuild.Append((_sparse[i] < _count ? _sparse[i].ToString() : "_") + ", ");
} }
logbuild.Append("\n\r Count: " + _count); logbuild.Append("\n\r Count: " + _count);
logbuild.Append("\n\r Capacity: " + Capacity); logbuild.Append("\n\r Capacity: " + CapacitySparse);
logbuild.Append("\n\r IsValide: " + IsValide_Debug()); logbuild.Append("\n\r IsValide: " + IsValide_Debug());
logbuild.Append("\n\r"); logbuild.Append("\n\r");
@ -445,7 +396,7 @@ namespace DCFApixels.DragonECS
public bool IsValide_Debug() public bool IsValide_Debug()
{ {
bool isPass = true; bool isPass = true;
for (int index = 0; index < Capacity; index++) for (int index = 0; index < CapacitySparse; index++)
{ {
int value = _dense[index]; int value = _dense[index];
isPass = isPass && _sparse[value] == index; isPass = isPass && _sparse[value] == index;
@ -453,31 +404,30 @@ namespace DCFApixels.DragonECS
return isPass; return isPass;
} }
#if DEBUG #if DEBUG
private static class ThrowHalper private static class ThrowHalper
{ {
public static void CheckCapacity(int capacity) public static void CheckCapacity(coretype capacity)
{ {
if (capacity < 0) if (capacity < 0)
throw new ArgumentException("Capacity cannot be a negative number"); throw new ArgumentException("Capacity cannot be a negative number");
} }
public static void CheckValueIsPositive(int value) public static void CheckValueIsPositive(coretype value)
{ {
if (value < 0) if (value < 0)
throw new ArgumentException("The SparseSet can only contain positive numbers"); throw new ArgumentException("The SparseSet can only contain positive numbers");
} }
public static void CheckValueContained(SparseSet source, int value) public static void CheckValueContained(SparseSet source, coretype value)
{ {
if (!source.Contains(value)) if (!source.Contains(value))
throw new ArgumentException($"Value {value} is not contained"); throw new ArgumentException($"Value {value} is not contained");
} }
public static void CheckValueNotContained(SparseSet source, int value) public static void CheckValueNotContained(SparseSet source, coretype value)
{ {
if (source.Contains(value)) if (source.Contains(value))
throw new ArgumentException($"Value {value} is already contained"); throw new ArgumentException($"Value {value} is already contained");
} }
public static void CheckOutOfRange(SparseSet source, int index) public static void CheckOutOfRange(SparseSet source, coretype index)
{ {
if (index < 0 || index >= source.Count) 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."); throw new ArgumentOutOfRangeException($"Index {index} was out of range. Must be non-negative and less than the size of the collection.");

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace DCFApixels.DragonECS
{
public static class Mems
{
public static readonly mem<float> health = "health";
public static readonly mem<float> regeneration = "regeneration";
public static readonly mem<Vector3> position = "position";
public static readonly mem<Quaternion> rotation = "rotation";
public static readonly mem<Vector3> scale = "scale";
}
}

12
test/SharedData.cs Normal file
View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
public class SharedData
{
}
}

View File

@ -9,12 +9,14 @@ namespace DCFApixels.DragonECS
{ {
private EcsSession _ecsSession; private EcsSession _ecsSession;
public SharedData _data = new SharedData();
private void Start() private void Start()
{ {
_ecsSession _ecsSession
.AddWorld("") .AddWorld("")
.Add(new TestSystem()) .Add(new TestSystem())
.Inject(_data)
.Init(); .Init();
} }

View File

@ -6,18 +6,26 @@ using System.Threading.Tasks;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public class TestSystem : IEcsDo<_Init>, IEcsDo<_Run>, IEcsDo<_Destroy> public class TestSystem :
IReceive<_OnInject<SharedData>>,
IDo<_Init>, IDo<_Run>, IDo<_Destroy>
{ {
void IEcsDo<_Init>.Do(EcsSession engine) private SharedData _sharedData;
void IReceive<_OnInject<SharedData>>.Do(EcsSession session, in _OnInject<SharedData> m) => _sharedData = m.data;
void IDo<_Init>.Do(EcsSession session)
{ {
} }
void IEcsDo<_Run>.Do(EcsSession engine) void IDo<_Run>.Do(EcsSession session)
{
}
void IDo<_Destroy>.Do(EcsSession session)
{ {
} }
void IEcsDo<_Destroy>.Do(EcsSession engine)
{
}
} }
} }

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 35dbc0eb7d0449242a40ddcb8cbdbc06
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,136 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public readonly struct EcsField<T> : IEcsMemberCachePool<EcsField<T>, T>
where T :struct
{
private readonly EcsPool<T> _pool;
private readonly int _poolID;
public EcsPool<T> Pool => _pool;
public int PoolID => _poolID;
private EcsField(int poolID)
{
_pool = null;
_poolID = poolID;
}
internal EcsField(EcsPool<T> pool)
{
_pool = pool;
_poolID = pool.ID;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public ref T this[int entityID]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref _pool[entityID];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int entityID)
{
return _pool.Has(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Add(int entityID)
{
return ref _pool.Add(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Del(int entityID)
{
_pool.Del(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsField<T>(in int poolID) => new EcsField<T>(poolID);
void IEcsMemberCachePool<EcsField<T>, T>.Inject(out EcsField<T> self, EcsPool<T> pool)
{
self = new EcsField<T>(pool);
}
}
public readonly struct EcsIncField<T> : IEcsMemberCachePool<EcsIncField<T>, T>
where T :struct
{
private readonly EcsPool<T> _pool;
private readonly int _poolID;
public EcsPool<T> Pool => _pool;
public int PoolID => _poolID;
private EcsIncField(int poolID)
{
_pool = null;
_poolID = poolID;
}
internal EcsIncField(EcsPool<T> pool)
{
_pool = pool;
_poolID = pool.ID;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public ref T this[int entityID]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref _pool[entityID];
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void Del(int entityID)
{
_pool.Del(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsIncField<T>(in int poolID) => new EcsIncField<T>(poolID);
void IEcsMemberCachePool<EcsIncField<T>, T>.Inject(out EcsIncField<T> self, EcsPool<T> pool)
{
self = new EcsIncField<T>(pool);
}
}
public struct EcsExcField<T> : IEcsMemberCachePool<EcsExcField<T>, T>
where T :struct
{
private readonly EcsPool<T> _pool;
private readonly int _poolID;
public EcsPool<T> Pool => _pool;
public int PoolID => _poolID;
private EcsExcField(int poolID)
{
_pool = null;
_poolID = poolID;
}
internal EcsExcField(EcsPool<T> pool)
{
_pool = pool;
_poolID = pool.ID;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Add(int entityID)
{
return ref _pool.Add(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsExcField<T>(in int poolID) => new EcsExcField<T>(poolID);
void IEcsMemberCachePool<EcsExcField<T>, T>.Inject(out EcsExcField<T> self, EcsPool<T> pool)
{
self = new EcsExcField<T>(pool);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 93de2f9d4ed4cd849a2b4fca39174c37
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,97 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public readonly struct EcsTag : IEcsMemberCachePool<EcsTag, tag>
where T :struct
{
private readonly EcsPool<tag> _pool;
private readonly int _poolID;
public EcsPool<tag> Pool => _pool;
public int PoolID => _poolID;
private EcsTag(int poolID)
{
_pool = null;
_poolID = poolID;
}
internal EcsTag(EcsPool<tag> pool)
{
_pool = pool;
_poolID = pool.ID;
}
public void Add(int entityID)
{
_pool.Add(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsTag(in int poolID) => new EcsTag(poolID);
void IEcsMemberCachePool<EcsTag, tag>.Inject(out EcsTag self, EcsPool<tag> pool)
{
self = new EcsTag(pool);
}
}
public readonly struct EcsIncTag : IEcsMemberCachePool<EcsIncTag, tag>
where T :struct
{
private readonly EcsPool<tag> _pool;
private readonly int _poolID;
public EcsPool<tag> Pool => _pool;
public int PoolID => _poolID;
private EcsIncTag(int poolID)
{
_pool = null;
_poolID = poolID;
}
internal EcsIncTag(EcsPool<tag> pool)
{
_pool = pool;
_poolID = pool.ID;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsIncTag(in int poolID) => new EcsIncTag(poolID);
void IEcsMemberCachePool<EcsIncTag, tag>.Inject(out EcsIncTag self, EcsPool<tag> pool)
{
self = new EcsIncTag(pool);
}
}
public readonly struct EcsExcTag : IEcsMemberCachePool<EcsExcTag, tag>
where T :struct
{
private readonly EcsPool<tag> _pool;
private readonly int _poolID;
public EcsPool<tag> Pool => _pool;
public int PoolID => _poolID;
private EcsExcTag(int poolID)
{
_pool = null;
_poolID = poolID;
}
internal EcsExcTag(EcsPool<tag> pool)
{
_pool = pool;
_poolID = pool.ID;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsExcTag(in int poolID) => new EcsExcTag(poolID);
void IEcsMemberCachePool<EcsExcTag, tag>.Inject(out EcsExcTag self, EcsPool<tag> pool)
{
self = new EcsExcTag(pool);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 524f71e4e46e94a44b302e2242150817
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
public interface IEcsTableMember
{
public int PoolID { get; }
}
public interface IEcsMemberCachePool<TSelf, T> : IEcsTableMember
where TSelf: struct, IEcsTableMember
where T :struct
{
public EcsPool<T> Pool { get; }
public void Inject(out TSelf self, EcsPool<T> pool);
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e765044f6e73f5847aa432da56a1ec9d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: