mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
Update WIP, add Mask/Filter
This commit is contained in:
parent
dc2e0cd810
commit
796a555cbc
@ -1,6 +1,6 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class FitersProcessor : IEcsGReceive<_OnComponentAdded>, IEcsGReceive<_OnComponentRemoved>
|
||||
public class FiltersProcessor : IEcsGReceive<_OnComponentAdded>, IEcsGReceive<_OnComponentRemoved>
|
||||
{
|
||||
void IEcsGReceive<_OnComponentAdded>.Do<T>(EcsSession session, in _OnComponentAdded message, in T obj)
|
||||
{
|
@ -18,7 +18,9 @@ namespace DCFApixels.DragonECS
|
||||
void IDo<_PreInit>.Do(EcsSession session)
|
||||
{
|
||||
_OnInject<T> m = new _OnInject<T>(_injectedData);
|
||||
session.GetMessenger<_OnInject<T>>().Send(in m);
|
||||
var messenger = session.GetMessenger<_OnInject<T>>();
|
||||
messenger.Send(in m);
|
||||
messenger.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
16
src/Code.cs
16
src/Code.cs
@ -1,16 +0,0 @@
|
||||
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 { }
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdfd15ed79cb9e04caf3fb0275900c72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
565
src/EcsFilter.cs
565
src/EcsFilter.cs
@ -1,174 +1,465 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
#region Incs/Excs base
|
||||
public interface ICondition
|
||||
{
|
||||
public int[] GetComponentsIDs();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Incs
|
||||
public interface IInc : ICondition { }
|
||||
|
||||
public struct Inc<T0> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID,
|
||||
ComponentType<T7>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID,
|
||||
ComponentType<T7>.uniqueID,
|
||||
ComponentType<T8>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID,
|
||||
ComponentType<T7>.uniqueID,
|
||||
ComponentType<T8>.uniqueID,
|
||||
ComponentType<T9>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID,
|
||||
ComponentType<T7>.uniqueID,
|
||||
ComponentType<T8>.uniqueID,
|
||||
ComponentType<T9>.uniqueID,
|
||||
ComponentType<T10>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID,
|
||||
ComponentType<T7>.uniqueID,
|
||||
ComponentType<T8>.uniqueID,
|
||||
ComponentType<T9>.uniqueID,
|
||||
ComponentType<T10>.uniqueID,
|
||||
ComponentType<T11>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Excs
|
||||
public interface IExc : ICondition { }
|
||||
|
||||
public struct Exc<T0> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4, T5> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4, T5, T6> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4, T5, T6, T7> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.uniqueID,
|
||||
ComponentType<T1>.uniqueID,
|
||||
ComponentType<T2>.uniqueID,
|
||||
ComponentType<T3>.uniqueID,
|
||||
ComponentType<T4>.uniqueID,
|
||||
ComponentType<T5>.uniqueID,
|
||||
ComponentType<T6>.uniqueID,
|
||||
ComponentType<T7>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Masks
|
||||
public abstract class Mask
|
||||
{
|
||||
protected internal static int _typeIDIncrement = 0;
|
||||
|
||||
internal abstract int[] Include { get; }
|
||||
internal abstract int[] Exclude { get; }
|
||||
|
||||
public abstract int ID { get; }
|
||||
|
||||
public int IncCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Include.Length;
|
||||
}
|
||||
public int ExcCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Exclude.Length;
|
||||
}
|
||||
}
|
||||
public sealed class Mask<TInc> : Mask
|
||||
where TInc : struct, IInc
|
||||
{
|
||||
internal static readonly int[] include = new TInc().GetComponentsIDs();
|
||||
internal static readonly int[] exclude = Array.Empty<int>();
|
||||
public static readonly int id = _typeIDIncrement++;
|
||||
private static Mask<TInc> _instance = new Mask<TInc>();
|
||||
|
||||
private Mask() { }
|
||||
|
||||
public static Mask<TInc> Instance
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _instance;
|
||||
}
|
||||
public override int ID
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => id;
|
||||
}
|
||||
internal override int[] Include
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => include;
|
||||
}
|
||||
internal override int[] Exclude
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => exclude;
|
||||
}
|
||||
}
|
||||
public sealed class Mask<TInc, TExc> : Mask
|
||||
where TInc : struct, IInc
|
||||
where TExc : struct, IExc
|
||||
{
|
||||
internal static readonly int[] include = new TInc().GetComponentsIDs();
|
||||
internal static readonly int[] exclude = new TExc().GetComponentsIDs();
|
||||
public static readonly int id = _typeIDIncrement++;
|
||||
private static Mask<TInc, TExc> _instance = new Mask<TInc, TExc>();
|
||||
|
||||
private Mask() { }
|
||||
|
||||
public static Mask<TInc, TExc> Instance
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _instance;
|
||||
}
|
||||
public override int ID
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => id;
|
||||
}
|
||||
internal override int[] Include
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => include;
|
||||
}
|
||||
internal override int[] Exclude
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => exclude;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Filter
|
||||
public interface IEcsFilter
|
||||
{
|
||||
public EcsWorld World { get; }
|
||||
public Mask Mask { get; }
|
||||
public IEcsReadonlyGroup Entities { 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
|
||||
{
|
||||
private readonly EcsWorld _source;
|
||||
private readonly EcsWorld.Mask _mask;
|
||||
private readonly SparseSet _entities;
|
||||
|
||||
private DelayedOp[] _delayedOps;
|
||||
private int _delayedOpsCount;
|
||||
|
||||
private int _lockCount;
|
||||
private readonly EcsGroup _entities;
|
||||
private readonly Mask _mask;
|
||||
|
||||
#region Properties
|
||||
public EcsWorld World => _source;
|
||||
public EcsWorld.Mask Mask => _mask;
|
||||
public int EntitiesCount => _entities.Count;
|
||||
public EcsWorld World
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _source;
|
||||
}
|
||||
public Mask Mask
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _mask;
|
||||
}
|
||||
public IEcsReadonlyGroup Entities
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _entities;
|
||||
}
|
||||
public int EntitiesCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _entities.Count;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constrcutors
|
||||
internal EcsFilter(EcsWorld source, EcsWorld.Mask mask, int capasity)
|
||||
internal EcsFilter(EcsWorld source, Mask mask, int capasity)
|
||||
{
|
||||
_source = source;
|
||||
_mask = mask;
|
||||
_entities = new SparseSet(capasity);
|
||||
_delayedOps = new DelayedOp[512];
|
||||
_lockCount = 0;
|
||||
_entities = new EcsGroup(source, capasity);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
internal void Change(int entityID, bool isAdd)
|
||||
{
|
||||
if (isAdd)
|
||||
Add(entityID);
|
||||
else
|
||||
Remove(entityID);
|
||||
}
|
||||
#region EntityChangedReact
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void Add(int entityID)
|
||||
{
|
||||
if (_lockCount > 0)
|
||||
AddDelayedOp(entityID, true);
|
||||
_entities.Add(entityID);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal 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;
|
||||
}
|
||||
|
||||
#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 EcsFilter _source;
|
||||
private readonly SparseSet _entities;
|
||||
private int _index;
|
||||
|
||||
public Enumerator(EcsFilter filter)
|
||||
{
|
||||
_source = filter;
|
||||
_entities = filter._entities;
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
public int Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _entities[_index];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
return ++_index < _entities.Count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
_source.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private struct DelayedOp
|
||||
{
|
||||
public bool Added;
|
||||
public int Entity;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
@ -3,7 +3,19 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class EcsGroup
|
||||
public interface IEcsReadonlyGroup
|
||||
{
|
||||
public EcsWorld World { get; }
|
||||
public int Count { get; }
|
||||
public EcsGroup.Enumerator GetEnumerator();
|
||||
}
|
||||
public interface IEcsGroup : IEcsReadonlyGroup
|
||||
{
|
||||
public void Add(int entityID);
|
||||
public void Remove(int entityID);
|
||||
}
|
||||
|
||||
public class EcsGroup : IEcsGroup
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private SparseSet _entities;
|
||||
@ -15,7 +27,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Properties
|
||||
public EcsWorld World => _source;
|
||||
public int EntitiesCount => _entities.Count;
|
||||
public int Count => _entities.Count;
|
||||
#endregion
|
||||
|
||||
#region Constrcutors
|
||||
@ -55,6 +67,24 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddGroup/RemoveGroup
|
||||
public void AddGroup(IEcsReadonlyGroup group)
|
||||
{
|
||||
foreach (var item in group)
|
||||
{
|
||||
_entities.TryAdd(item.id);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveGroup(IEcsReadonlyGroup group)
|
||||
{
|
||||
foreach (var item in group)
|
||||
{
|
||||
_entities.TryRemove(item.id);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetEnumerator
|
||||
private void Unlock()
|
||||
{
|
||||
|
@ -44,11 +44,7 @@ namespace DCFApixels.DragonECS
|
||||
internal void OnRunnerDetroyed<TDoTag>(EcsProcessorsRunner<TDoTag> target)
|
||||
where TDoTag : IEcsDoTag
|
||||
{
|
||||
Type type = typeof(TDoTag);
|
||||
if (_runners.ContainsKey(type))
|
||||
{
|
||||
_runners.Remove(type);
|
||||
}
|
||||
_runners.Remove(typeof(TDoTag));
|
||||
}
|
||||
|
||||
public EcsProcessorsMessenger<TMessege> GetMessenger<TMessege>()
|
||||
@ -78,11 +74,7 @@ namespace DCFApixels.DragonECS
|
||||
internal void OnMessengerDetroyed<TMessege>(IEcsProcessorsMessenger<TMessege> target)
|
||||
where TMessege : IEcsMessage
|
||||
{
|
||||
Type type = typeof(TMessege);
|
||||
if (_messengers.ContainsKey(type))
|
||||
{
|
||||
_messengers.Remove(type);
|
||||
}
|
||||
_messengers.Remove(typeof(TMessege));
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
152
src/EcsWorld.cs
152
src/EcsWorld.cs
@ -25,6 +25,9 @@ namespace DCFApixels.DragonECS
|
||||
private List<EcsFilter>[] _filtersByIncludedComponents;
|
||||
private List<EcsFilter>[] _filtersByExcludedComponents;
|
||||
|
||||
private EcsFilter[] _filters;
|
||||
private SparseSet _maskIDToFilterID;
|
||||
|
||||
#region Properties
|
||||
public int ID => _id;
|
||||
public bool IsAlive => _id != DEAD_WORLD_ID;
|
||||
@ -37,6 +40,24 @@ namespace DCFApixels.DragonECS
|
||||
_pools = new IEcsPool[512];
|
||||
_entities = new SparseSet(512);
|
||||
_componentIDToPoolID = new SparseSet(512);
|
||||
_maskIDToFilterID = new SparseSet(512);
|
||||
_filters = new EcsFilter[512];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Filters
|
||||
public EcsFilter GetFilter<TMask>(TMask mask) where TMask : Mask
|
||||
{
|
||||
if (_maskIDToFilterID.TryAdd(mask.ID, ref _filters))
|
||||
{
|
||||
EcsFilter filter = new EcsFilter(this, mask, 512);
|
||||
_filters[_maskIDToFilterID.IndexOf(mask.ID)] = filter;
|
||||
return filter;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _filters[_maskIDToFilterID.IndexOf(mask.ID)];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -86,19 +107,20 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsMaskCompatible/IsMaskCompatibleWithout
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal bool IsMaskCompatible(Mask filterMask, int entity)
|
||||
public bool IsMaskCompatible(Mask mask, int entity)
|
||||
{
|
||||
for (int i = 0, iMax = filterMask.includeCount; i < iMax; i++)
|
||||
for (int i = 0, iMax = mask.IncCount; i < iMax; i++)
|
||||
{
|
||||
if (!_pools[filterMask.include[i]].Has(entity))
|
||||
if (!_pools[_componentIDToPoolID[mask.Include[i]]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = filterMask.excludeCount; i < iMax; i++)
|
||||
for (int i = 0, iMax = mask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
if (_pools[filterMask.exclude[i]].Has(entity))
|
||||
if (_pools[_componentIDToPoolID[mask.Exclude[i]]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -107,27 +129,29 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal bool IsMaskCompatibleWithout(Mask filterMask, int entity, int componentId)
|
||||
public bool IsMaskCompatibleWithout(Mask mask, int entity, int otherPoolID)
|
||||
{
|
||||
for (int i = 0, iMax = filterMask.includeCount; i < iMax; i++)
|
||||
for (int i = 0, iMax = mask.IncCount; i < iMax; i++)
|
||||
{
|
||||
var typeId = filterMask.include[i];
|
||||
if (typeId == componentId || !_pools[typeId].Has(entity))
|
||||
int poolID = _componentIDToPoolID[mask.Include[i]];
|
||||
if (poolID == otherPoolID || !_pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = filterMask.excludeCount; i < iMax; i++)
|
||||
for (int i = 0, iMax = mask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
var typeId = filterMask.exclude[i];
|
||||
if (typeId != componentId && _pools[typeId].Has(entity))
|
||||
int poolID = _componentIDToPoolID[mask.Exclude[i]];
|
||||
if (poolID != otherPoolID && _pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EntityChangedReact
|
||||
internal void OnEntityComponentAdded(int entityID, int changedPoolID)
|
||||
{
|
||||
var includeList = _filtersByIncludedComponents[changedPoolID];
|
||||
@ -155,96 +179,32 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal void OnEntityComponentRemoved(int entityID, int changedPool)
|
||||
internal void OnEntityComponentRemoved(int entityID, int changedPoolID)
|
||||
{
|
||||
var includeList = _filtersByIncludedComponents[changedPoolID];
|
||||
var excludeList = _filtersByExcludedComponents[changedPoolID];
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class Mask
|
||||
{
|
||||
private readonly EcsWorld _world;
|
||||
internal int[] include;
|
||||
internal int[] exclude;
|
||||
internal int includeCount;
|
||||
internal int excludeCount;
|
||||
|
||||
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
|
||||
bool _built;
|
||||
#endif
|
||||
|
||||
internal Mask(EcsWorld world)
|
||||
if (includeList != null)
|
||||
{
|
||||
_world = world;
|
||||
include = new int[8];
|
||||
exclude = new int[2];
|
||||
Reset();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void Reset()
|
||||
{
|
||||
includeCount = 0;
|
||||
excludeCount = 0;
|
||||
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
|
||||
_built = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Mask Inc<T>() where T : struct
|
||||
{
|
||||
var poolId = _world.GetPool<T>().ID;
|
||||
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
|
||||
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(exclude, poolId, 0, excludeCount) != -1) { throw new Exception($"{typeof(T).Name} already in constraints list."); }
|
||||
#endif
|
||||
if (includeCount == include.Length) { Array.Resize(ref include, includeCount << 1); }
|
||||
include[includeCount++] = poolId;
|
||||
return this;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Mask Exc<T>() where T : struct
|
||||
{
|
||||
var poolId = _world.GetPool<T>().ID;
|
||||
#if DEBUG && !DCFAECS_NO_SANITIZE_CHECKS
|
||||
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(exclude, poolId, 0, excludeCount) != -1) { throw new Exception($"{typeof(T).Name} already in constraints list."); }
|
||||
#endif
|
||||
if (excludeCount == exclude.Length) { Array.Resize(ref exclude, excludeCount << 1); }
|
||||
exclude[excludeCount++] = poolId;
|
||||
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)
|
||||
foreach (var filter in includeList)
|
||||
{
|
||||
Array.Resize(ref _world._masks, _world._masksCount << 1);
|
||||
if (IsMaskCompatible(filter.Mask, entityID))
|
||||
{
|
||||
filter.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeList != null)
|
||||
{
|
||||
foreach (var filter in excludeList)
|
||||
{
|
||||
if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID))
|
||||
{
|
||||
filter.Add(entityID);
|
||||
}
|
||||
}
|
||||
_world._masks[_world._masksCount++] = this;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class EcsProcessorsGMessenger<TMessage> : IEcsProcessorsMessenger<TMessage>
|
||||
public class EcsProcessorsGMessenger<TMessage> : IEcsProcessorsMessenger<TMessage>, IDisposable
|
||||
where TMessage : IEcsMessage
|
||||
{
|
||||
private readonly EcsSession _source;
|
||||
@ -35,5 +36,6 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
public void Destroy() => _source.OnMessengerDetroyed(this);
|
||||
void IDisposable.Dispose() => Destroy();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -7,7 +8,7 @@ namespace DCFApixels.DragonECS
|
||||
public EcsSession Source { get; }
|
||||
}
|
||||
public interface IEcsProcessorsMessenger<TMessage> : IEcsProcessorsMessenger where TMessage : IEcsMessage { }
|
||||
public class EcsProcessorsMessenger<TMessage> : IEcsProcessorsMessenger<TMessage>
|
||||
public class EcsProcessorsMessenger<TMessage> : IEcsProcessorsMessenger<TMessage>, IDisposable
|
||||
where TMessage : IEcsMessage
|
||||
{
|
||||
private readonly EcsSession _source;
|
||||
@ -40,5 +41,6 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
public void Destroy() => _source.OnMessengerDetroyed(this);
|
||||
void IDisposable.Dispose() => Destroy();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -7,7 +8,7 @@ namespace DCFApixels.DragonECS
|
||||
public EcsSession Source { get; }
|
||||
public void Run();
|
||||
}
|
||||
public class EcsProcessorsRunner<TDoTag> : IEcsProcessorsRunner
|
||||
public class EcsProcessorsRunner<TDoTag> : IEcsProcessorsRunner, IDisposable
|
||||
where TDoTag : IEcsDoTag
|
||||
{
|
||||
private readonly EcsSession _source;
|
||||
@ -40,5 +41,6 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
public void Destroy() => _source.OnRunnerDetroyed(this);
|
||||
void IDisposable.Dispose() => Destroy();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user