mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-18 03:34:35 +08:00
Merge branch 'main' of https://github.com/DCFApixels/DragonECS-Graphs
This commit is contained in:
commit
7bc442f756
@ -1,63 +1,51 @@
|
||||
using DCFApixels.DragonECS.Core;
|
||||
using DCFApixels.DragonECS.Graphs.Internal;
|
||||
using DCFApixels.DragonECS.Graphs.Internal;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public static class GraphQueriesExtensions
|
||||
{
|
||||
#region JoinToGraph Empty
|
||||
public static SubGraphMap Join(this EcsWorld entities, JoinMode mode = JoinMode.Start)
|
||||
private struct JoinExecutorsManager : IEcsWorldComponent<JoinExecutorsManager>
|
||||
{
|
||||
entities.GetQueryCache(out JoinExecutor executor, out EmptyAspect _);
|
||||
return executor.Execute(mode);
|
||||
const int N = 32;
|
||||
private JoinExecutor[] _joinExecutorsQueue;
|
||||
private int _increment;
|
||||
void IEcsWorldComponent<JoinExecutorsManager>.Init(ref JoinExecutorsManager component, EcsWorld graphWorld)
|
||||
{
|
||||
if (graphWorld.IsGraphWorld() == false)
|
||||
{
|
||||
Throw.Exception($"The {nameof(Join)} query can only be used for EntityGraph.GraphWorld or a collection of that _graphWorld.");
|
||||
}
|
||||
component._joinExecutorsQueue = new JoinExecutor[N];
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
component._joinExecutorsQueue[i] = new JoinExecutor(graphWorld);
|
||||
}
|
||||
_increment = 0;
|
||||
}
|
||||
void IEcsWorldComponent<JoinExecutorsManager>.OnDestroy(ref JoinExecutorsManager component, EcsWorld graphWorld)
|
||||
{
|
||||
_joinExecutorsQueue = null;
|
||||
}
|
||||
public JoinExecutor GetExecutor()
|
||||
{
|
||||
_increment = ++_increment % N;
|
||||
return _joinExecutorsQueue[_increment];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region JoinToGraph Mask
|
||||
public static SubGraphMap Join<TCollection>(this TCollection entities, IComponentMask mask, JoinMode mode = JoinMode.Start)
|
||||
public static SubGraphMap Join<TCollection>(this TCollection entities, JoinMode mode = JoinMode.Start)
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
if (ReferenceEquals(entities, entities.World))
|
||||
{
|
||||
var executor = entities.World.GetExecutorForMask<JoinExecutor>(mask);
|
||||
return executor.Execute();
|
||||
}
|
||||
return entities.ToSpan().JoinSubGraph(mask, mode);
|
||||
var executor = entities.World.Get<JoinExecutorsManager>().GetExecutor();
|
||||
return entities.ToSpan().Join(mode);
|
||||
}
|
||||
public static SubGraphMap Join(this EcsReadonlyGroup group, IComponentMask mask, JoinMode mode = JoinMode.Start)
|
||||
public static SubGraphMap Join(this EcsReadonlyGroup group, JoinMode mode = JoinMode.Start)
|
||||
{
|
||||
return group.ToSpan().JoinSubGraph(mask, mode);
|
||||
return group.ToSpan().Join(mode);
|
||||
}
|
||||
public static SubGraphMap JoinSubGraph(this EcsSpan span, IComponentMask mask, JoinMode mode = JoinMode.Start)
|
||||
public static SubGraphMap Join(this EcsSpan span, JoinMode mode = JoinMode.Start)
|
||||
{
|
||||
var executor = span.World.GetExecutorForMask<JoinExecutor>(mask);
|
||||
var executor = span.World.Get<JoinExecutorsManager>().GetExecutor();
|
||||
return executor.ExecuteFor(span, mode);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region JoinToGraph
|
||||
public static SubGraphMap Join<TCollection, TAspect>(this TCollection entities, out TAspect aspect, JoinMode mode = JoinMode.Start)
|
||||
where TAspect : EcsAspect, new()
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
if (ReferenceEquals(entities, entities.World))
|
||||
{
|
||||
entities.World.GetQueryCache(out JoinExecutor executor, out aspect);
|
||||
return executor.Execute();
|
||||
}
|
||||
return entities.ToSpan().Join(out aspect, mode);
|
||||
}
|
||||
public static SubGraphMap JoinSubGraph<TAspect>(this EcsReadonlyGroup group, out TAspect aspect, JoinMode mode = JoinMode.Start)
|
||||
where TAspect : EcsAspect, new()
|
||||
{
|
||||
return group.ToSpan().Join(out aspect, mode);
|
||||
}
|
||||
public static SubGraphMap Join<TAspect>(this EcsSpan span, out TAspect aspect, JoinMode mode = JoinMode.Start)
|
||||
where TAspect : EcsAspect, new()
|
||||
{
|
||||
span.World.GetQueryCache(out JoinExecutor executor, out aspect);
|
||||
return executor.ExecuteFor(span, mode);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using DCFApixels.DragonECS.Core;
|
||||
using DCFApixels.DragonECS.Graphs.Internal;
|
||||
using DCFApixels.DragonECS.Graphs.Internal;
|
||||
using DCFApixels.DragonECS.UncheckedCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -9,21 +8,12 @@ using LinkedList = DCFApixels.DragonECS.Graphs.Internal.OnlyAppendHeadLinkedList
|
||||
|
||||
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||
{
|
||||
internal sealed class JoinExecutor : MaskQueryExecutor, IEcsWorldEventListener
|
||||
internal sealed class JoinExecutor : IEcsWorldEventListener
|
||||
{
|
||||
private EcsWorld _graphWorld;
|
||||
private EntityGraph _graph;
|
||||
private EcsMaskIterator _iterator;
|
||||
|
||||
private int[] _filteredAllEntities = new int[32];
|
||||
private int _filteredAllEntitiesCount = 0;
|
||||
private int[] _filteredEntities = null;
|
||||
private int _filteredEntitiesCount = 0;
|
||||
|
||||
private int[] _currentFilteredEntities = null;
|
||||
private int _currentFilteredEntitiesCount = 0;
|
||||
|
||||
private long _version;
|
||||
private WorldStateVersionsChecker _versionsChecker;
|
||||
|
||||
private LinkedList _linkedList;
|
||||
private LinkedListHead[] _linkedListSourceHeads;
|
||||
@ -36,9 +26,8 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
||||
|
||||
public bool _isDestroyed = false;
|
||||
|
||||
|
||||
#region Properties
|
||||
public sealed override long Version
|
||||
public long Version
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _version; }
|
||||
@ -48,133 +37,39 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _graph; }
|
||||
}
|
||||
public sealed override bool IsCached
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _versionsChecker.Check(); }
|
||||
}
|
||||
public sealed override int LastCachedCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _filteredAllEntitiesCount; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region OnInitialize/OnDestroy
|
||||
protected override void OnInitialize()
|
||||
#region Constructors/OnDestroy
|
||||
public JoinExecutor(EcsWorld world)
|
||||
{
|
||||
if (World.IsGraphWorld() == false)
|
||||
{
|
||||
Throw.Exception("The JounSubGraph query can only be used for EntityGraph.GraphWorld or a collection of that world.");
|
||||
}
|
||||
|
||||
_versionsChecker = new WorldStateVersionsChecker(Mask);
|
||||
_linkedList = new OnlyAppendHeadLinkedList(World.Capacity);
|
||||
_linkedListSourceHeads = new LinkedListHead[World.Capacity];
|
||||
_sourceEntities = new int[World.Capacity * 2];
|
||||
World.AddListener(this);
|
||||
_graph = World.GetGraph();
|
||||
_iterator = Mask.GetIterator();
|
||||
_graphWorld = world;
|
||||
_linkedList = new OnlyAppendHeadLinkedList(_graphWorld.Capacity);
|
||||
_linkedListSourceHeads = new LinkedListHead[_graphWorld.Capacity];
|
||||
_sourceEntities = new int[_graphWorld.Capacity * 2];
|
||||
_graphWorld.AddListener(this);
|
||||
_graph = _graphWorld.GetGraph();
|
||||
}
|
||||
protected override void OnDestroy()
|
||||
public void Destroy()
|
||||
{
|
||||
if (_isDestroyed) { return; }
|
||||
_isDestroyed = true;
|
||||
World.RemoveListener(this);
|
||||
_versionsChecker.Dispose();
|
||||
_graphWorld.RemoveListener(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Execute
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private SubGraphMap Execute_Internal(JoinMode mode)
|
||||
{
|
||||
//_executeMarker.Begin();
|
||||
|
||||
World.ReleaseDelEntityBufferAllAuto();
|
||||
|
||||
if (Mask.IsEmpty || _versionsChecker.CheckAndNext() == false)
|
||||
{
|
||||
_filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities);
|
||||
if (_sourceEntities.Length < _graph.World.Capacity * 2)
|
||||
{
|
||||
_sourceEntities = new int[_graph.World.Capacity * 2];
|
||||
}
|
||||
//Подготовка массивов
|
||||
}
|
||||
|
||||
|
||||
//установка текущего массива
|
||||
_currentFilteredEntities = _filteredAllEntities;
|
||||
_currentFilteredEntitiesCount = _filteredAllEntitiesCount;
|
||||
|
||||
//Подготовка массивов
|
||||
if (_targetWorldCapacity < _graph.World.Capacity)
|
||||
{
|
||||
_targetWorldCapacity = _graph.World.Capacity;
|
||||
_linkedListSourceHeads = new LinkedListHead[_targetWorldCapacity];
|
||||
//_startEntities = new int[_targetWorldCapacity];
|
||||
}
|
||||
else
|
||||
{
|
||||
//ArrayUtility.Fill(_linkedListSourceHeads, default); //TODO оптимизировать, сделав не полную отчистку а только по элементов с прошлого раза
|
||||
for (int i = 0; i < _sourceEntitiesCount; i++)
|
||||
{
|
||||
_linkedListSourceHeads[_sourceEntities[i]] = default;
|
||||
}
|
||||
}
|
||||
_sourceEntitiesCount = 0;
|
||||
_linkedList.Clear();
|
||||
|
||||
//Заполнение массивов
|
||||
if ((mode & JoinMode.Start) != 0)
|
||||
{
|
||||
for (int i = 0; i < _filteredAllEntitiesCount; i++)
|
||||
{
|
||||
AddStart(_filteredAllEntities[i]);
|
||||
}
|
||||
}
|
||||
if ((mode & JoinMode.End) != 0)
|
||||
{
|
||||
for (int i = 0; i < _filteredAllEntitiesCount; i++)
|
||||
{
|
||||
AddEnd(_filteredAllEntities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_version++;
|
||||
|
||||
//_executeMarker.End();
|
||||
return new SubGraphMap(this);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private SubGraphMap ExecuteFor_Internal(EcsSpan span, JoinMode mode)
|
||||
{
|
||||
//_executeMarker.Begin();
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (span.IsNull) { /*_executeMarker.End();*/ Throw.ArgumentNull(nameof(span)); }
|
||||
if (span.WorldID != World.ID) { /*_executeMarker.End();*/ Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||
if (span.WorldID != _graphWorld.ID) { /*_executeMarker.End();*/ Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||
#endif
|
||||
if (_filteredEntities == null)
|
||||
{
|
||||
_filteredEntities = new int[32];
|
||||
}
|
||||
_filteredEntitiesCount = _iterator.IterateTo(span, ref _filteredEntities);
|
||||
if (_sourceEntities.Length < _filteredEntitiesCount * 2)
|
||||
{
|
||||
_sourceEntities = new int[_filteredEntitiesCount * 2];
|
||||
}
|
||||
|
||||
|
||||
//установка текущего массива
|
||||
_currentFilteredEntities = _filteredEntities;
|
||||
_currentFilteredEntitiesCount = _filteredEntitiesCount;
|
||||
|
||||
//Подготовка массивов
|
||||
if (_targetWorldCapacity < World.Capacity)
|
||||
if (_targetWorldCapacity < _graphWorld.Capacity)
|
||||
{
|
||||
_targetWorldCapacity = World.Capacity;
|
||||
_targetWorldCapacity = _graphWorld.Capacity;
|
||||
_linkedListSourceHeads = new LinkedListHead[_targetWorldCapacity];
|
||||
//_startEntities = new int[_targetWorldCapacity];
|
||||
}
|
||||
@ -192,28 +87,22 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
||||
//Заполнение массивов
|
||||
if ((mode & JoinMode.Start) != 0)
|
||||
{
|
||||
for (int i = 0; i < _filteredEntitiesCount; i++)
|
||||
for (int i = 0, iMax = span.Count; i < iMax; i++)
|
||||
{
|
||||
AddStart(_filteredEntities[i]);
|
||||
AddStart(span[i]);
|
||||
}
|
||||
}
|
||||
if ((mode & JoinMode.End) != 0)
|
||||
{
|
||||
for (int i = 0; i < _filteredEntitiesCount; i++)
|
||||
for (int i = 0, iMax = span.Count; i < iMax; i++)
|
||||
{
|
||||
AddEnd(_filteredEntities[i]);
|
||||
AddEnd(span[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//_executeMarker.End();
|
||||
return new SubGraphMap(this);
|
||||
}
|
||||
|
||||
public SubGraphMap Execute(JoinMode mode = JoinMode.Start)
|
||||
{
|
||||
return Execute_Internal(mode);
|
||||
}
|
||||
public SubGraphMap ExecuteFor(EcsSpan span, JoinMode mode = JoinMode.Start)
|
||||
{
|
||||
return ExecuteFor_Internal(span, mode);
|
||||
@ -299,11 +188,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
||||
#region GetEntites
|
||||
internal EcsSpan GetNodeEntities()
|
||||
{
|
||||
return UncheckedCoreUtility.CreateSpan(WorldID, _sourceEntities, _sourceEntitiesCount);
|
||||
}
|
||||
internal EcsSpan GetRelEntities()
|
||||
{
|
||||
return UncheckedCoreUtility.CreateSpan(WorldID, _currentFilteredEntities, _currentFilteredEntitiesCount);
|
||||
return UncheckedCoreUtility.CreateSpan(_graphWorld.ID, _sourceEntities, _sourceEntitiesCount);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@ -327,39 +212,15 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
get { return _executer.Graph; }
|
||||
}
|
||||
public EcsSpan Nodes
|
||||
{
|
||||
get { return _executer.GetNodeEntities(); }
|
||||
}
|
||||
|
||||
internal SubGraphMap(JoinExecutor executer)
|
||||
{
|
||||
_executer = executer;
|
||||
}
|
||||
|
||||
public EcsSpan WhereNodes<TAspect>(out TAspect a)
|
||||
where TAspect : EcsAspect, new()
|
||||
{
|
||||
return _executer.GetNodeEntities().Where(out a);
|
||||
}
|
||||
public EcsSpan WhereNodes<TAspect>(IComponentMask mask)
|
||||
{
|
||||
return _executer.GetNodeEntities().Where(mask);
|
||||
}
|
||||
public EcsSpan WhereNodes<TAspect>(out TAspect a, Comparison<int> comparison)
|
||||
where TAspect : EcsAspect, new()
|
||||
{
|
||||
return _executer.GetNodeEntities().Where(out a, comparison);
|
||||
}
|
||||
public EcsSpan WhereNodes<TAspect>(IComponentMask mask, Comparison<int> comparison)
|
||||
{
|
||||
return _executer.GetNodeEntities().Where(mask, comparison);
|
||||
}
|
||||
|
||||
public EcsSpan GetNodes()
|
||||
{
|
||||
return _executer.GetNodeEntities();
|
||||
}
|
||||
public EcsSpan GetAllRelations()
|
||||
{
|
||||
return _executer.GetRelEntities();
|
||||
}
|
||||
|
||||
public NodeInfo GetRelations(int nodeEntityID)
|
||||
{
|
||||
return _executer.GetRelations_Internal(nodeEntityID);
|
||||
|
Loading…
Reference in New Issue
Block a user