2024-01-07 18:52:54 +08:00
|
|
|
|
using DCFApixels.DragonECS.Internal;
|
2024-04-30 16:09:57 +08:00
|
|
|
|
using DCFApixels.DragonECS.PoolsCore;
|
2023-06-26 02:53:55 +08:00
|
|
|
|
using System;
|
2023-05-07 00:50:02 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS
|
|
|
|
|
{
|
2024-04-22 17:01:13 +08:00
|
|
|
|
public abstract class EcsAspect : ITemplateNode
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-01-07 18:52:54 +08:00
|
|
|
|
internal EcsWorld _source;
|
|
|
|
|
internal EcsMask _mask;
|
2024-03-26 16:06:03 +08:00
|
|
|
|
private bool _isBuilt = false;
|
|
|
|
|
|
|
|
|
|
[ThreadStatic]
|
2024-03-26 18:09:13 +08:00
|
|
|
|
private static Stack<Builder> _constructorBuildersStack = null;
|
|
|
|
|
private static Stack<Builder> GetBuildersStack()
|
|
|
|
|
{
|
2024-04-09 00:19:43 +08:00
|
|
|
|
if (_constructorBuildersStack == null)
|
2024-03-26 18:09:13 +08:00
|
|
|
|
{
|
|
|
|
|
_constructorBuildersStack = new Stack<Builder>();
|
|
|
|
|
}
|
|
|
|
|
return _constructorBuildersStack;
|
|
|
|
|
}
|
2024-07-05 22:13:17 +08:00
|
|
|
|
protected static Builder CurrentBuilder
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
var buildersStack = GetBuildersStack();
|
|
|
|
|
if (buildersStack.Count <= 0)
|
|
|
|
|
{
|
|
|
|
|
Throw.Aspect_CanOnlyBeUsedDuringInitialization(nameof(CurrentBuilder));
|
|
|
|
|
}
|
|
|
|
|
return buildersStack.Peek();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-26 16:06:03 +08:00
|
|
|
|
protected static IncludeMarker Inc
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2024-03-26 18:09:13 +08:00
|
|
|
|
var buildersStack = GetBuildersStack();
|
|
|
|
|
if (buildersStack.Count <= 0)
|
2024-04-22 17:37:37 +08:00
|
|
|
|
{
|
|
|
|
|
Throw.Aspect_CanOnlyBeUsedDuringInitialization(nameof(Inc));
|
2024-03-26 16:06:03 +08:00
|
|
|
|
}
|
2024-03-26 18:09:13 +08:00
|
|
|
|
return buildersStack.Peek().Inc;
|
2024-03-26 16:06:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
protected static ExcludeMarker Exc
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2024-03-26 18:09:13 +08:00
|
|
|
|
var buildersStack = GetBuildersStack();
|
|
|
|
|
if (buildersStack.Count <= 0)
|
2024-04-22 17:37:37 +08:00
|
|
|
|
{
|
|
|
|
|
Throw.Aspect_CanOnlyBeUsedDuringInitialization(nameof(Exc));
|
2024-03-26 16:06:03 +08:00
|
|
|
|
}
|
2024-03-26 18:09:13 +08:00
|
|
|
|
return buildersStack.Peek().Exc;
|
2024-03-26 16:06:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
protected static OptionalMarker Opt
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2024-03-26 18:09:13 +08:00
|
|
|
|
var buildersStack = GetBuildersStack();
|
|
|
|
|
if (buildersStack.Count <= 0)
|
2024-04-22 17:37:37 +08:00
|
|
|
|
{
|
|
|
|
|
Throw.Aspect_CanOnlyBeUsedDuringInitialization(nameof(Opt));
|
2024-03-26 16:06:03 +08:00
|
|
|
|
}
|
2024-03-26 18:09:13 +08:00
|
|
|
|
return buildersStack.Peek().Opt;
|
2024-03-26 16:06:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
|
2024-02-11 01:14:54 +08:00
|
|
|
|
private UnsafeArray<int> _sortIncBuffer;
|
|
|
|
|
private UnsafeArray<int> _sortExcBuffer;
|
|
|
|
|
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
|
|
|
|
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
2024-01-07 18:52:54 +08:00
|
|
|
|
|
2023-05-07 00:50:02 +08:00
|
|
|
|
#region Properties
|
2024-03-02 21:45:09 +08:00
|
|
|
|
public EcsMask Mask
|
|
|
|
|
{
|
|
|
|
|
get { return _mask; }
|
|
|
|
|
}
|
|
|
|
|
public EcsWorld World
|
|
|
|
|
{
|
|
|
|
|
get { return _source; }
|
|
|
|
|
}
|
|
|
|
|
public bool IsInit
|
|
|
|
|
{
|
2024-03-26 16:06:03 +08:00
|
|
|
|
get { return _isBuilt; }
|
2024-03-02 21:45:09 +08:00
|
|
|
|
}
|
2023-05-07 00:50:02 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Methods
|
2024-02-13 21:00:01 +08:00
|
|
|
|
public bool IsMatches(int entityID)
|
|
|
|
|
{
|
|
|
|
|
return _source.IsMatchesMask(_mask, entityID);
|
|
|
|
|
}
|
2023-05-07 00:50:02 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Builder
|
|
|
|
|
protected virtual void Init(Builder b) { }
|
2024-02-11 01:28:18 +08:00
|
|
|
|
public sealed class Builder
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
|
|
|
|
private EcsWorld _world;
|
2024-01-07 19:32:16 +08:00
|
|
|
|
private EcsMask.Builder _maskBuilder;
|
2024-07-05 22:13:17 +08:00
|
|
|
|
|
2024-03-08 20:40:19 +08:00
|
|
|
|
public IncludeMarker Inc
|
|
|
|
|
{
|
|
|
|
|
get { return new IncludeMarker(this); }
|
|
|
|
|
}
|
|
|
|
|
public ExcludeMarker Exc
|
|
|
|
|
{
|
|
|
|
|
get { return new ExcludeMarker(this); }
|
|
|
|
|
}
|
|
|
|
|
public OptionalMarker Opt
|
|
|
|
|
{
|
|
|
|
|
get { return new OptionalMarker(this); }
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-07 00:50:02 +08:00
|
|
|
|
public EcsWorld World => _world;
|
|
|
|
|
|
|
|
|
|
private Builder(EcsWorld world)
|
|
|
|
|
{
|
|
|
|
|
_world = world;
|
2024-01-11 00:48:39 +08:00
|
|
|
|
_maskBuilder = EcsMask.New(world);
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2024-07-05 22:13:17 +08:00
|
|
|
|
internal static unsafe TAspect New<TAspect>(EcsWorld world) where TAspect : EcsAspect, new()
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
|
|
|
|
Builder builder = new Builder(world);
|
2023-06-22 14:31:13 +08:00
|
|
|
|
Type aspectType = typeof(TAspect);
|
|
|
|
|
EcsAspect newAspect;
|
2024-03-26 16:06:03 +08:00
|
|
|
|
|
2024-03-26 18:09:13 +08:00
|
|
|
|
var buildersStack = GetBuildersStack();
|
|
|
|
|
buildersStack.Push(builder);
|
2024-06-27 00:26:05 +08:00
|
|
|
|
|
2024-07-05 22:13:17 +08:00
|
|
|
|
newAspect = new TAspect();
|
2024-03-26 18:09:13 +08:00
|
|
|
|
newAspect.Init(builder);
|
|
|
|
|
buildersStack.Pop();
|
2024-01-07 18:52:54 +08:00
|
|
|
|
newAspect._source = world;
|
2024-01-07 19:32:16 +08:00
|
|
|
|
builder.Build(out newAspect._mask);
|
2024-03-26 16:06:03 +08:00
|
|
|
|
newAspect._isBuilt = true;
|
2024-01-07 18:52:54 +08:00
|
|
|
|
|
2024-04-22 17:20:31 +08:00
|
|
|
|
newAspect._sortIncBuffer = new UnsafeArray<int>(newAspect._mask._inc.Length, true);
|
|
|
|
|
newAspect._sortExcBuffer = new UnsafeArray<int>(newAspect._mask._exc.Length, true);
|
|
|
|
|
newAspect._sortIncChunckBuffer = new UnsafeArray<EcsMaskChunck>(newAspect._mask._incChunckMasks.Length, true);
|
|
|
|
|
newAspect._sortExcChunckBuffer = new UnsafeArray<EcsMaskChunck>(newAspect._mask._excChunckMasks.Length, true);
|
2024-01-07 18:52:54 +08:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < newAspect._sortIncBuffer.Length; i++)
|
|
|
|
|
{
|
2024-04-22 17:20:31 +08:00
|
|
|
|
newAspect._sortIncBuffer.ptr[i] = newAspect._mask._inc[i];
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < newAspect._sortExcBuffer.Length; i++)
|
|
|
|
|
{
|
2024-04-22 17:20:31 +08:00
|
|
|
|
newAspect._sortExcBuffer.ptr[i] = newAspect._mask._exc[i];
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < newAspect._sortIncChunckBuffer.Length; i++)
|
|
|
|
|
{
|
2024-04-22 17:20:31 +08:00
|
|
|
|
newAspect._sortIncChunckBuffer.ptr[i] = newAspect._mask._incChunckMasks[i];
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < newAspect._sortExcChunckBuffer.Length; i++)
|
|
|
|
|
{
|
2024-04-22 17:20:31 +08:00
|
|
|
|
newAspect._sortExcChunckBuffer.ptr[i] = newAspect._mask._excChunckMasks[i];
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-22 14:31:13 +08:00
|
|
|
|
return (TAspect)newAspect;
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-04-18 22:14:50 +08:00
|
|
|
|
#region Include/Exclude/Optional/Combine/Except
|
2024-03-07 03:40:06 +08:00
|
|
|
|
public TPool IncludePool<TPool>() where TPool : IEcsPoolImplementation, new()
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-03-07 03:30:18 +08:00
|
|
|
|
var pool = _world.GetPoolInstance<TPool>();
|
2024-02-23 18:34:40 +08:00
|
|
|
|
IncludeImplicit(pool.ComponentType);
|
|
|
|
|
return pool;
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2024-03-07 03:40:06 +08:00
|
|
|
|
public TPool ExcludePool<TPool>() where TPool : IEcsPoolImplementation, new()
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-03-07 03:30:18 +08:00
|
|
|
|
var pool = _world.GetPoolInstance<TPool>();
|
2024-02-23 18:34:40 +08:00
|
|
|
|
ExcludeImplicit(pool.ComponentType);
|
|
|
|
|
return pool;
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2024-03-07 03:40:06 +08:00
|
|
|
|
public TPool OptionalPool<TPool>() where TPool : IEcsPoolImplementation, new()
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-03-07 03:30:18 +08:00
|
|
|
|
return _world.GetPoolInstance<TPool>();
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2023-06-04 18:32:05 +08:00
|
|
|
|
private void IncludeImplicit(Type type)
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-01-07 19:32:16 +08:00
|
|
|
|
_maskBuilder.Include(type);
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2023-06-04 18:32:05 +08:00
|
|
|
|
private void ExcludeImplicit(Type type)
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-01-07 19:32:16 +08:00
|
|
|
|
_maskBuilder.Exclude(type);
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2024-07-05 22:13:17 +08:00
|
|
|
|
public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new()
|
2023-06-03 01:58:54 +08:00
|
|
|
|
{
|
2023-06-22 14:31:13 +08:00
|
|
|
|
var result = _world.GetAspect<TOtherAspect>();
|
2024-01-11 00:48:39 +08:00
|
|
|
|
_maskBuilder.Combine(result.Mask);
|
2023-06-03 01:58:54 +08:00
|
|
|
|
return result;
|
|
|
|
|
}
|
2024-07-05 22:13:17 +08:00
|
|
|
|
public TOtherAspect Except<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new()
|
2024-04-18 22:14:50 +08:00
|
|
|
|
{
|
|
|
|
|
var result = _world.GetAspect<TOtherAspect>();
|
|
|
|
|
_maskBuilder.Except(result.Mask);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2023-06-03 01:58:54 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
2024-01-07 19:32:16 +08:00
|
|
|
|
private void Build(out EcsMask mask)
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-01-07 19:32:16 +08:00
|
|
|
|
mask = _maskBuilder.Build();
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2023-05-28 05:53:08 +08:00
|
|
|
|
|
|
|
|
|
#region SupportReflectionHack
|
|
|
|
|
#if UNITY_2020_3_OR_NEWER
|
|
|
|
|
[UnityEngine.Scripting.Preserve]
|
|
|
|
|
#endif
|
2023-06-04 18:32:05 +08:00
|
|
|
|
private void SupportReflectionHack<TPool>() where TPool : IEcsPoolImplementation, new()
|
2023-05-28 05:53:08 +08:00
|
|
|
|
{
|
2024-03-07 03:40:06 +08:00
|
|
|
|
IncludePool<TPool>();
|
|
|
|
|
ExcludePool<TPool>();
|
|
|
|
|
OptionalPool<TPool>();
|
2023-06-04 18:32:05 +08:00
|
|
|
|
IncludeImplicit(null);
|
|
|
|
|
ExcludeImplicit(null);
|
2023-05-28 05:53:08 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2024-03-02 21:45:09 +08:00
|
|
|
|
#region Finalizator
|
2024-01-07 18:52:54 +08:00
|
|
|
|
unsafe ~EcsAspect()
|
|
|
|
|
{
|
|
|
|
|
_sortIncBuffer.Dispose();
|
|
|
|
|
_sortExcBuffer.Dispose();
|
|
|
|
|
_sortIncChunckBuffer.Dispose();
|
|
|
|
|
_sortExcChunckBuffer.Dispose();
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2023-06-02 04:00:08 +08:00
|
|
|
|
#region Iterator
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public Iterator GetIterator()
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
return new Iterator(this, _source.Entities);
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public Iterator GetIteratorFor(EcsSpan span)
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
return new Iterator(this, span);
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2023-06-02 04:00:08 +08:00
|
|
|
|
#endregion
|
2023-06-05 22:09:34 +08:00
|
|
|
|
|
2024-01-07 18:52:54 +08:00
|
|
|
|
#region Combined
|
2023-06-25 23:13:51 +08:00
|
|
|
|
private readonly struct Combined
|
2023-06-05 22:09:34 +08:00
|
|
|
|
{
|
2023-06-25 23:13:51 +08:00
|
|
|
|
public readonly EcsAspect aspect;
|
|
|
|
|
public readonly int order;
|
2023-06-22 14:31:13 +08:00
|
|
|
|
public Combined(EcsAspect aspect, int order)
|
2023-06-05 22:09:34 +08:00
|
|
|
|
{
|
2023-06-22 14:31:13 +08:00
|
|
|
|
this.aspect = aspect;
|
2023-06-05 22:09:34 +08:00
|
|
|
|
this.order = order;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
#endregion
|
2023-05-07 00:50:02 +08:00
|
|
|
|
|
2024-02-11 01:14:54 +08:00
|
|
|
|
#region Iterator
|
|
|
|
|
public ref struct Iterator
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
2024-04-16 12:46:09 +08:00
|
|
|
|
public readonly short worldID;
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public readonly EcsAspect aspect;
|
|
|
|
|
private EcsSpan _span;
|
|
|
|
|
|
|
|
|
|
public Iterator(EcsAspect aspect, EcsSpan span)
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
worldID = aspect.World.id;
|
|
|
|
|
_span = span;
|
|
|
|
|
this.aspect = aspect;
|
2023-12-24 15:40:19 +08:00
|
|
|
|
}
|
2024-04-18 00:36:05 +08:00
|
|
|
|
|
|
|
|
|
#region CopyTo
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public void CopyTo(EcsGroup group)
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
group.Clear();
|
|
|
|
|
var enumerator = GetEnumerator();
|
|
|
|
|
while (enumerator.MoveNext())
|
2024-03-02 21:45:09 +08:00
|
|
|
|
{
|
2024-03-02 04:20:34 +08:00
|
|
|
|
group.Add_Internal(enumerator.Current);
|
2024-03-02 21:45:09 +08:00
|
|
|
|
}
|
2023-12-24 15:40:19 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public int CopyTo(ref int[] array)
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
int count = 0;
|
2024-03-02 21:45:09 +08:00
|
|
|
|
var enumerator = GetEnumerator();
|
2024-02-11 01:14:54 +08:00
|
|
|
|
while (enumerator.MoveNext())
|
2024-01-07 18:52:54 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
if (array.Length <= count)
|
2024-03-02 21:45:09 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
Array.Resize(ref array, array.Length << 1);
|
2024-03-02 21:45:09 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
array[count++] = enumerator.Current;
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
return count;
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public EcsSpan CopyToSpan(ref int[] array)
|
2024-01-07 18:52:54 +08:00
|
|
|
|
{
|
2024-03-02 21:45:09 +08:00
|
|
|
|
int count = CopyTo(ref array);
|
2024-02-11 01:14:54 +08:00
|
|
|
|
return new EcsSpan(worldID, array, count);
|
|
|
|
|
}
|
2024-04-18 00:36:05 +08:00
|
|
|
|
#endregion
|
2024-02-11 01:14:54 +08:00
|
|
|
|
|
2024-03-02 21:45:09 +08:00
|
|
|
|
#region Other
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
List<int> ints = new List<int>();
|
|
|
|
|
foreach (var e in this)
|
2024-01-07 18:52:54 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
ints.Add(e);
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
return CollectionUtility.EntitiesToString(ints, "it");
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
2024-01-07 23:19:18 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
2024-02-11 01:14:54 +08:00
|
|
|
|
#region Enumerator
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 21:45:09 +08:00
|
|
|
|
public Enumerator GetEnumerator() { return new Enumerator(_span, aspect); }
|
2024-01-07 18:52:54 +08:00
|
|
|
|
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public unsafe ref struct Enumerator
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
#region CountComparers
|
|
|
|
|
private readonly struct IncCountComparer : IComparerX<int>
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public readonly int[] counts;
|
|
|
|
|
public IncCountComparer(int[] counts)
|
|
|
|
|
{
|
|
|
|
|
this.counts = counts;
|
|
|
|
|
}
|
|
|
|
|
public int Compare(int a, int b)
|
|
|
|
|
{
|
|
|
|
|
return counts[a] - counts[b];
|
|
|
|
|
}
|
2024-01-06 00:07:07 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
private readonly struct ExcCountComparer : IComparerX<int>
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public readonly int[] counts;
|
|
|
|
|
public ExcCountComparer(int[] counts)
|
2024-01-07 23:19:18 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
this.counts = counts;
|
2024-01-07 23:19:18 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public int Compare(int a, int b)
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
return counts[b] - counts[a];
|
2024-01-06 00:07:07 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private ReadOnlySpan<int>.Enumerator _span;
|
2024-02-16 21:17:20 +08:00
|
|
|
|
private readonly int[] _entityComponentMasks;
|
2024-02-11 01:14:54 +08:00
|
|
|
|
|
|
|
|
|
private static EcsMaskChunck* _preSortedIncBuffer;
|
|
|
|
|
private static EcsMaskChunck* _preSortedExcBuffer;
|
2024-01-06 00:07:07 +08:00
|
|
|
|
|
2024-02-11 01:14:54 +08:00
|
|
|
|
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
|
|
|
|
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
|
|
|
|
|
2024-04-18 00:36:05 +08:00
|
|
|
|
private readonly int _entityComponentMaskLengthBitShift;
|
2024-02-11 01:14:54 +08:00
|
|
|
|
|
|
|
|
|
public unsafe Enumerator(EcsSpan span, EcsAspect aspect)
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-16 21:17:20 +08:00
|
|
|
|
_entityComponentMasks = aspect.World._entityComponentMasks;
|
2024-02-11 01:14:54 +08:00
|
|
|
|
_sortIncChunckBuffer = aspect._sortIncChunckBuffer;
|
|
|
|
|
_sortExcChunckBuffer = aspect._sortExcChunckBuffer;
|
|
|
|
|
|
2024-04-18 00:36:05 +08:00
|
|
|
|
_entityComponentMaskLengthBitShift = aspect.World._entityComponentMaskLengthBitShift;
|
2024-02-16 21:17:20 +08:00
|
|
|
|
|
2024-04-18 22:14:50 +08:00
|
|
|
|
if (aspect.Mask.IsBroken)
|
|
|
|
|
{
|
|
|
|
|
_span = span.Slice(0, 0).GetEnumerator();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-11 01:14:54 +08:00
|
|
|
|
#region Sort
|
|
|
|
|
UnsafeArray<int> _sortIncBuffer = aspect._sortIncBuffer;
|
|
|
|
|
UnsafeArray<int> _sortExcBuffer = aspect._sortExcBuffer;
|
|
|
|
|
int[] counts = aspect.World._poolComponentCounts;
|
|
|
|
|
|
|
|
|
|
if (_preSortedIncBuffer == null)
|
2024-01-07 23:19:18 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
_preSortedIncBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
|
|
|
|
|
_preSortedExcBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
|
2024-01-07 23:19:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-11 01:14:54 +08:00
|
|
|
|
if (_sortIncChunckBuffer.Length > 1)
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
IncCountComparer incComparer = new IncCountComparer(counts);
|
|
|
|
|
UnsafeArraySortHalperX<int>.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref incComparer);
|
|
|
|
|
for (int i = 0; i < _sortIncBuffer.Length; i++)
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
_preSortedIncBuffer[i] = EcsMaskChunck.FromID(_sortIncBuffer.ptr[i]);
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0, ii = 0; ii < _sortIncChunckBuffer.Length; ii++)
|
|
|
|
|
{
|
2024-04-18 22:14:50 +08:00
|
|
|
|
EcsMaskChunck chunkX = _preSortedIncBuffer[i];
|
|
|
|
|
int chankIndexX = chunkX.chankIndex;
|
|
|
|
|
int maskX = chunkX.mask;
|
2024-02-11 01:14:54 +08:00
|
|
|
|
|
|
|
|
|
for (int j = i + 1; j < _sortIncBuffer.Length; j++)
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
if (_preSortedIncBuffer[j].chankIndex == chankIndexX)
|
|
|
|
|
{
|
|
|
|
|
maskX |= _preSortedIncBuffer[j].mask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_sortIncChunckBuffer.ptr[ii] = new EcsMaskChunck(chankIndexX, maskX);
|
|
|
|
|
while (++i < _sortIncBuffer.Length && _preSortedIncBuffer[i].chankIndex == chankIndexX)
|
|
|
|
|
{
|
|
|
|
|
// skip
|
2024-01-06 00:07:07 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
}
|
2024-04-08 23:49:56 +08:00
|
|
|
|
if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]] <= 0)
|
|
|
|
|
{
|
|
|
|
|
_span = span.Slice(0, 0).GetEnumerator();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
if (_sortExcChunckBuffer.Length > 1)
|
|
|
|
|
{
|
|
|
|
|
ExcCountComparer excComparer = new ExcCountComparer(counts);
|
|
|
|
|
UnsafeArraySortHalperX<int>.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref excComparer);
|
|
|
|
|
for (int i = 0; i < _sortExcBuffer.Length; i++)
|
2024-01-06 00:07:07 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
_preSortedExcBuffer[i] = EcsMaskChunck.FromID(_sortExcBuffer.ptr[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0, ii = 0; ii < _sortExcChunckBuffer.Length; ii++)
|
|
|
|
|
{
|
|
|
|
|
EcsMaskChunck bas = _preSortedExcBuffer[i];
|
|
|
|
|
int chankIndexX = bas.chankIndex;
|
|
|
|
|
int maskX = bas.mask;
|
|
|
|
|
|
|
|
|
|
for (int j = i + 1; j < _sortExcBuffer.Length; j++)
|
|
|
|
|
{
|
|
|
|
|
if (_preSortedExcBuffer[j].chankIndex == chankIndexX)
|
|
|
|
|
{
|
|
|
|
|
maskX |= _preSortedExcBuffer[j].mask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_sortExcChunckBuffer.ptr[ii] = new EcsMaskChunck(chankIndexX, maskX);
|
|
|
|
|
while (++i < _sortExcBuffer.Length && _preSortedExcBuffer[i].chankIndex == chankIndexX)
|
|
|
|
|
{
|
|
|
|
|
// skip
|
|
|
|
|
}
|
2024-01-06 00:07:07 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
#endregion
|
2024-04-18 00:36:05 +08:00
|
|
|
|
|
2024-04-08 23:49:56 +08:00
|
|
|
|
_span = span.GetEnumerator();
|
2024-01-06 00:07:07 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public int Current
|
|
|
|
|
{
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 21:45:09 +08:00
|
|
|
|
get { return _span.Current; }
|
2024-02-11 01:14:54 +08:00
|
|
|
|
}
|
2023-05-07 00:50:02 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-02-11 01:14:54 +08:00
|
|
|
|
public bool MoveNext()
|
2023-05-07 00:50:02 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
while (_span.MoveNext())
|
2023-11-22 17:35:03 +08:00
|
|
|
|
{
|
2024-04-18 00:36:05 +08:00
|
|
|
|
int chunck = _span.Current << _entityComponentMaskLengthBitShift;
|
2024-02-11 01:14:54 +08:00
|
|
|
|
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var bit = _sortIncChunckBuffer.ptr[i];
|
2024-04-08 23:49:56 +08:00
|
|
|
|
if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != bit.mask)
|
2024-03-02 21:45:09 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
goto skip;
|
2024-03-02 21:45:09 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var bit = _sortExcChunckBuffer.ptr[i];
|
2024-04-08 23:49:56 +08:00
|
|
|
|
if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != 0)
|
2024-03-02 21:45:09 +08:00
|
|
|
|
{
|
2024-02-11 01:14:54 +08:00
|
|
|
|
goto skip;
|
2024-03-02 21:45:09 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
skip: continue;
|
2023-11-22 17:35:03 +08:00
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
return false;
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-11 01:14:54 +08:00
|
|
|
|
#endregion
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2023-06-02 04:00:08 +08:00
|
|
|
|
#endregion
|
2024-04-22 17:01:13 +08:00
|
|
|
|
|
|
|
|
|
#region Template
|
|
|
|
|
public virtual void Apply(short worldID, int entityID)
|
|
|
|
|
{
|
|
|
|
|
EcsWorld world = EcsWorld.GetWorld(worldID);
|
2024-04-22 17:20:31 +08:00
|
|
|
|
foreach (var incTypeID in _mask._inc)
|
2024-04-22 17:01:13 +08:00
|
|
|
|
{
|
2024-08-21 14:40:44 +08:00
|
|
|
|
var pool = world.FindPoolInstance(incTypeID);
|
2024-04-22 17:16:37 +08:00
|
|
|
|
if (pool != null)
|
2024-04-22 17:01:13 +08:00
|
|
|
|
{
|
2024-04-22 17:16:37 +08:00
|
|
|
|
if (pool.Has(entityID) == false)
|
|
|
|
|
{
|
|
|
|
|
pool.AddRaw(entityID, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if DEBUG
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
EcsDebug.PrintWarning("Component has not been added because the pool has not been initialized yet.");
|
2024-04-22 17:01:13 +08:00
|
|
|
|
}
|
2024-04-22 17:16:37 +08:00
|
|
|
|
#endif
|
2024-04-26 04:55:19 +08:00
|
|
|
|
}
|
2024-04-22 17:20:31 +08:00
|
|
|
|
foreach (var excTypeID in _mask._exc)
|
2024-04-22 17:01:13 +08:00
|
|
|
|
{
|
2024-08-21 14:40:44 +08:00
|
|
|
|
var pool = world.FindPoolInstance(excTypeID);
|
2024-04-22 17:09:06 +08:00
|
|
|
|
if (pool != null && pool.Has(entityID))
|
2024-04-22 17:01:13 +08:00
|
|
|
|
{
|
|
|
|
|
pool.Del(entityID);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|
2024-03-08 20:40:19 +08:00
|
|
|
|
public readonly ref struct IncludeMarker
|
|
|
|
|
{
|
|
|
|
|
private readonly EcsAspect.Builder _builder;
|
|
|
|
|
public IncludeMarker(EcsAspect.Builder builder)
|
|
|
|
|
{
|
|
|
|
|
_builder = builder;
|
|
|
|
|
}
|
2024-03-09 21:33:44 +08:00
|
|
|
|
public T GetInstance<T>()
|
2024-03-08 20:40:19 +08:00
|
|
|
|
where T : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
|
|
|
|
return _builder.IncludePool<T>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public readonly ref struct ExcludeMarker
|
|
|
|
|
{
|
|
|
|
|
private readonly EcsAspect.Builder _builder;
|
|
|
|
|
public ExcludeMarker(EcsAspect.Builder builder)
|
|
|
|
|
{
|
|
|
|
|
_builder = builder;
|
|
|
|
|
}
|
|
|
|
|
public T GetInstance<T>()
|
|
|
|
|
where T : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
|
|
|
|
return _builder.ExcludePool<T>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public readonly ref struct OptionalMarker
|
|
|
|
|
{
|
|
|
|
|
private readonly EcsAspect.Builder _builder;
|
|
|
|
|
public OptionalMarker(EcsAspect.Builder builder)
|
|
|
|
|
{
|
|
|
|
|
_builder = builder;
|
|
|
|
|
}
|
|
|
|
|
public T GetInstance<T>()
|
|
|
|
|
where T : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
|
|
|
|
return _builder.OptionalPool<T>();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-07 00:50:02 +08:00
|
|
|
|
}
|