implemented JoinAttachQuery

This commit is contained in:
Mikhail 2023-04-23 04:10:54 +08:00
parent 22ff801f15
commit b5d9d0e5e1
5 changed files with 242 additions and 27 deletions

View File

@ -2,6 +2,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Unity.Profiling;
@ -22,7 +23,16 @@ namespace DCFApixels.DragonECS
public EcsAttachPool<TAttachComponent> Attach => _targetPool;
private int[] _mapping = Array.Empty<int>();
private int _targetWorldCapacity = -1;
private int _targetPoolCapacity = -1;
private int[] _mapping;
private int[] _counts;
private int[] _entites;
private EntityLinkedList _linkedBasket;
private bool _isJoinExecuted = false;
public bool IsJoinExecuted => _isJoinExecuted;
//private LinkedList<int>
@ -36,30 +46,74 @@ namespace DCFApixels.DragonECS
{
ExecuteWhere(_targetPool.Entites, groupFilter);
}
private ProfilerMarker _execute = new ProfilerMarker("Query.ExecuteJoin");
public sealed override void ExecuteJoin()
{
ExecuteWhere(_targetPool.Entites, groupFilter);
if (_isInitTargetWorlds == false) InitTargetWorlds();
_execute.Begin();
if (_isInitTargetWorlds == false)
{
InitTargetWorlds();
if (_isInitTargetWorlds == false)
return;
}
if (source.Capacity != _mapping.Length)
_mapping = new int[World.Capacity];
//Подготовка массивов
if (_targetWorldCapacity < _targetWorld.Capacity)
{
_mapping = new int[_targetWorldCapacity];
_counts = new int[_targetWorldCapacity];
_targetWorldCapacity = _targetWorld.Capacity;
}
else
ArrayUtility.Fill(_mapping, 0);
{
ArrayUtility.Fill(_counts, 0);
}
ArrayUtility.Fill(_mapping, -1);
if (_targetPoolCapacity < _targetPool.Capacity)
{
_entites = new int[_targetPoolCapacity];
_linkedBasket.Resize(_targetPoolCapacity);
_targetPoolCapacity = _targetPool.Capacity;
}
else
{
ArrayUtility.Fill(_entites, 0);
}
_linkedBasket.Clear();
//Конец подготовки массивов
ExecuteWhere();
foreach (var e in groupFilter)
{
int entityID = e.id;
int attachID = e.id;
EcsEntity attachTarget = _targetPool.Read(attachID).Target;
// if (!attachTarget.IsAlive)//TODO пофиксить IsAlive
//{
// _targetPool.Del(attachID);
// continue;
//}
int attachTargetID = attachTarget.id;
ref int nodeIndex = ref _mapping[attachTargetID];
if(nodeIndex< 0)
nodeIndex = _linkedBasket.Add(attachID);
else
_linkedBasket.Insert(nodeIndex, attachID);
_counts[attachTargetID]++;
}
}
_isJoinExecuted = true;
_execute.End();
}
public EntityLinkedList.EnumerableSpan GetNodes(int entityID) => _linkedBasket.Span(_mapping[entityID], _counts[entityID]);
private void InitTargetWorlds()
{
foreach (var e in groupFilter)
foreach (var e in _targetPool.Entites)
{
ref readonly var rel = ref _targetPool.Read(e);
if (rel.Target.IsNotNull)
//if (rel.Target.IsNotNull)
_targetWorld = EcsWorld.Worlds[rel.Target.world];
if (_targetWorld != null)
@ -68,16 +122,22 @@ namespace DCFApixels.DragonECS
break;
}
}
if (_isInitTargetWorlds)
{
_targetWorldCapacity = _targetWorld.Capacity;
_mapping = new int[_targetWorldCapacity];
_counts = new int[_targetWorldCapacity];
_targetPoolCapacity = _targetPool.Capacity;
_entites = new int[_targetPoolCapacity];
_linkedBasket = new EntityLinkedList(_targetPoolCapacity);
}
}
public EcsGroup.Enumerator GetEnumerator()
{
return groupFilter.GetEnumerator();
}
public NodesEnumrable GetNodes(int entityID)
{
throw new NotImplementedException();
}
}
public abstract class EcsJoinRelationQuery<TRelationComponent> : EcsJoinQueryBase
where TRelationComponent : struct, IEcsRelationComponent

View File

@ -94,7 +94,7 @@ namespace DCFApixels.DragonECS
_groups = new List<WeakReference<EcsGroup>>();
_allEntites = GetGroupFromPool();
_queries = new EcsQuery[128];
_queries = new EcsQueryBase[128];
_entityCreate = _pipeline.GetRunner<IEcsEntityCreate>();
_entityDestry = _pipeline.GetRunner<IEcsEntityDestroy>();
@ -241,7 +241,7 @@ namespace DCFApixels.DragonECS
return new EcsEntity(entityID, _gens[entityID], uniqueID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool EntityIsAlive(int entityID, short gen)
public bool EntityIsAlive(int entityID, short gen) //TODO пофиксить EntityIsAlive
{
return _gens[entityID] == gen;
}

View File

@ -25,6 +25,8 @@ namespace DCFApixels.DragonECS
//public ent ToEnt() => EcsWorld.Worlds[world].EntityIsAlive(id, gen) ? new ent(id) : default;
public ent ToEnt() => new ent(id);
public bool IsAlive => EcsWorld.Worlds[world].EntityIsAlive(id, gen);
#region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsEntity(int id, short gen, short world) : this()
@ -98,15 +100,15 @@ namespace DCFApixels.DragonECS
{
private static EcsProfilerMarker _IsAliveMarker = new EcsProfilerMarker("EcsEntity.IsAlive");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsAlive(this ref EcsEntity self)
{
//using (_IsAliveMarker.Auto())
//{
bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen);
if (!result) self = EcsEntity.NULL;
return result;
//}
}
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public static bool IsAlive(this ref EcsEntity self)
// {
// //using (_IsAliveMarker.Auto())
// //{
// bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen);
// if (!result) self = EcsEntity.NULL;
// return result;
// //}
// }
}
}

View File

@ -33,6 +33,8 @@ namespace DCFApixels.DragonECS
_source = world;
_poolRunners = new PoolRunners(world.Pipeline);
_entities = EcsGroup.New(world);
_entityFlags = new bool[world.Capacity];
_items = new T[world.Capacity];
_count = 0;

View File

@ -0,0 +1,151 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
namespace DCFApixels.DragonECS
{
public class EntityLinkedList
{
public const int First = 0;
private Node[] _nodes;
private int _count;
private int _lastNodeIndex;
#region Properties
public int Count => _count;
public int Capacity => _nodes.Length;
public int Last => _lastNodeIndex;
#endregion
#region Constructors
public EntityLinkedList(int capacity)
{
_nodes = new Node[capacity + 10];
Clear();
}
#endregion
public void Resize(int newCapacity)
{
Array.Resize(ref _nodes, newCapacity + 10);
}
public void Clear()
{
//ArrayUtility.Fill(_nodes, Node.Empty);
for (int i = 0; i < _nodes.Length; i++)
_nodes[i].next = -1;
_lastNodeIndex = First;
_count = 0;
}
public void Set(int nodeIndex, int entityID)
{
_nodes[nodeIndex].entityID = entityID;
}
/// <summary> Insert after</summary>
/// <returns> new node index</returns>
public int Insert(int nodeIndex, int entityID)
{
_nodes[_count].Set(entityID, _nodes[nodeIndex].next);
_nodes[nodeIndex].next = _count;
_lastNodeIndex = _count;
return _count++;
}
public int Add(int entityID) => Insert(_lastNodeIndex, entityID);
public Enumerator GetEnumerator() => new Enumerator(_nodes);
public EnumerableSpan Span(int startNodeIndex, int count) => new EnumerableSpan(this, startNodeIndex, count);
#region Utils
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
public struct Node
{
public static readonly Node Empty = new Node() { entityID = 0, next = -1 };
public int entityID;
/// <summary>next node index</summary>
public int next;
public void Set(int entityID, int next)
{
this.entityID = entityID;
this.next = next;
}
}
public struct Enumerator
{
private readonly Node[] _nodes;
private int _index;
private int _next;
public Enumerator(Node[] nodes)
{
_nodes = nodes;
_index = -1;
_next = First;
}
public int Current => _nodes[_index].entityID;
public bool MoveNext()
{
_index = _next;
_next = _nodes[_next].next;
return _index >= 0;
}
}
public readonly ref struct EnumerableSpan
{
private readonly EntityLinkedList _source;
private readonly int _startNodeIndex;
private readonly int _count;
public EnumerableSpan(EntityLinkedList source, int startNodeIndex, int count)
{
_source = source;
_startNodeIndex = startNodeIndex;
_count = count;
}
public SpanEnumerator GetEnumerator() => new SpanEnumerator(_source._nodes, _startNodeIndex, _count);
}
public struct SpanEnumerator
{
private readonly Node[] _nodes;
private int _index;
private int _count;
private int _next;
public SpanEnumerator(Node[] nodes, int startIndex, int count)
{
_nodes = nodes;
_index = -1;
_count = count;
_next = startIndex;
}
public int Current => _nodes[_index].entityID;
public bool MoveNext()
{
if (_count <= 0)
return false;
_index = _next;
_next = _nodes[_next].next;
return _index >= 0 && _count-- > 0;
}
}
#endregion
}
}