rework api

This commit is contained in:
DCFApixels 2024-11-22 20:01:40 +08:00
parent a747b5043c
commit 691484b429
2 changed files with 61 additions and 212 deletions

View File

@ -1,63 +1,51 @@
using DCFApixels.DragonECS.Core; using DCFApixels.DragonECS.Graphs.Internal;
using DCFApixels.DragonECS.Graphs.Internal;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public static class GraphQueriesExtensions public static class GraphQueriesExtensions
{ {
#region JoinToGraph Empty private struct JoinExecutorsManager : IEcsWorldComponent<JoinExecutorsManager>
public static SubGraphMap Join(this EcsWorld entities, JoinMode mode = JoinMode.Start)
{ {
entities.GetQueryCache(out JoinExecutor executor, out EmptyAspect _); const int N = 32;
return executor.Execute(mode); 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.");
} }
#endregion component._joinExecutorsQueue = new JoinExecutor[N];
for (int i = 0; i < N; i++)
#region JoinToGraph Mask {
public static SubGraphMap Join<TCollection>(this TCollection entities, IComponentMask mask, JoinMode mode = JoinMode.Start) 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];
}
}
public static SubGraphMap Join<TCollection>(this TCollection entities, JoinMode mode = JoinMode.Start)
where TCollection : IEntityStorage where TCollection : IEntityStorage
{ {
if (ReferenceEquals(entities, entities.World)) var executor = entities.World.Get<JoinExecutorsManager>().GetExecutor();
{ return entities.ToSpan().Join(mode);
var executor = entities.World.GetExecutorForMask<JoinExecutor>(mask);
return executor.Execute();
} }
return entities.ToSpan().JoinSubGraph(mask, mode); public static SubGraphMap Join(this EcsReadonlyGroup group, JoinMode mode = JoinMode.Start)
}
public static SubGraphMap Join(this EcsReadonlyGroup group, IComponentMask mask, 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); 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
} }
} }

View File

@ -1,5 +1,4 @@
using DCFApixels.DragonECS.Core; using DCFApixels.DragonECS.Graphs.Internal;
using DCFApixels.DragonECS.Graphs.Internal;
using DCFApixels.DragonECS.UncheckedCore; using DCFApixels.DragonECS.UncheckedCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -9,21 +8,12 @@ using LinkedList = DCFApixels.DragonECS.Graphs.Internal.OnlyAppendHeadLinkedList
namespace DCFApixels.DragonECS.Graphs.Internal namespace DCFApixels.DragonECS.Graphs.Internal
{ {
internal sealed class JoinExecutor : MaskQueryExecutor, IEcsWorldEventListener internal sealed class JoinExecutor : IEcsWorldEventListener
{ {
private EcsWorld _graphWorld;
private EntityGraph _graph; 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 long _version;
private WorldStateVersionsChecker _versionsChecker;
private LinkedList _linkedList; private LinkedList _linkedList;
private LinkedListHead[] _linkedListSourceHeads; private LinkedListHead[] _linkedListSourceHeads;
@ -36,9 +26,8 @@ namespace DCFApixels.DragonECS.Graphs.Internal
public bool _isDestroyed = false; public bool _isDestroyed = false;
#region Properties #region Properties
public sealed override long Version public long Version
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _version; } get { return _version; }
@ -48,133 +37,39 @@ namespace DCFApixels.DragonECS.Graphs.Internal
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _graph; } 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 #endregion
#region OnInitialize/OnDestroy #region Constructors/OnDestroy
protected override void OnInitialize() public JoinExecutor(EcsWorld world)
{ {
if (World.IsGraphWorld() == false) _graphWorld = world;
{ _linkedList = new OnlyAppendHeadLinkedList(_graphWorld.Capacity);
Throw.Exception("The JounSubGraph query can only be used for EntityGraph.GraphWorld or a collection of that world."); _linkedListSourceHeads = new LinkedListHead[_graphWorld.Capacity];
_sourceEntities = new int[_graphWorld.Capacity * 2];
_graphWorld.AddListener(this);
_graph = _graphWorld.GetGraph();
} }
public void Destroy()
_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();
}
protected override void OnDestroy()
{ {
if (_isDestroyed) { return; } if (_isDestroyed) { return; }
_isDestroyed = true; _isDestroyed = true;
World.RemoveListener(this); _graphWorld.RemoveListener(this);
_versionsChecker.Dispose();
} }
#endregion #endregion
#region Execute #region Execute
[MethodImpl(MethodImplOptions.AggressiveInlining)] [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) private SubGraphMap ExecuteFor_Internal(EcsSpan span, JoinMode mode)
{ {
//_executeMarker.Begin(); //_executeMarker.Begin();
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (span.IsNull) { /*_executeMarker.End();*/ Throw.ArgumentNull(nameof(span)); } 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 #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]; _linkedListSourceHeads = new LinkedListHead[_targetWorldCapacity];
//_startEntities = new int[_targetWorldCapacity]; //_startEntities = new int[_targetWorldCapacity];
} }
@ -192,28 +87,22 @@ namespace DCFApixels.DragonECS.Graphs.Internal
//Заполнение массивов //Заполнение массивов
if ((mode & JoinMode.Start) != 0) 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) 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(); //_executeMarker.End();
return new SubGraphMap(this); return new SubGraphMap(this);
} }
public SubGraphMap Execute(JoinMode mode = JoinMode.Start)
{
return Execute_Internal(mode);
}
public SubGraphMap ExecuteFor(EcsSpan span, JoinMode mode = JoinMode.Start) public SubGraphMap ExecuteFor(EcsSpan span, JoinMode mode = JoinMode.Start)
{ {
return ExecuteFor_Internal(span, mode); return ExecuteFor_Internal(span, mode);
@ -299,11 +188,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
#region GetEntites #region GetEntites
internal EcsSpan GetNodeEntities() internal EcsSpan GetNodeEntities()
{ {
return UncheckedCoreUtility.CreateSpan(WorldID, _sourceEntities, _sourceEntitiesCount); return UncheckedCoreUtility.CreateSpan(_graphWorld.ID, _sourceEntities, _sourceEntitiesCount);
}
internal EcsSpan GetRelEntities()
{
return UncheckedCoreUtility.CreateSpan(WorldID, _currentFilteredEntities, _currentFilteredEntitiesCount);
} }
#endregion #endregion
} }
@ -327,39 +212,15 @@ namespace DCFApixels.DragonECS
{ {
get { return _executer.Graph; } get { return _executer.Graph; }
} }
public EcsSpan Nodes
{
get { return _executer.GetNodeEntities(); }
}
internal SubGraphMap(JoinExecutor executer) internal SubGraphMap(JoinExecutor executer)
{ {
_executer = 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) public NodeInfo GetRelations(int nodeEntityID)
{ {
return _executer.GetRelations_Internal(nodeEntityID); return _executer.GetRelations_Internal(nodeEntityID);