mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 18:14:37 +08:00
implemented JoinAttachQuery
This commit is contained in:
parent
22ff801f15
commit
b5d9d0e5e1
@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Unity.Profiling;
|
using Unity.Profiling;
|
||||||
@ -22,7 +23,16 @@ namespace DCFApixels.DragonECS
|
|||||||
public EcsAttachPool<TAttachComponent> Attach => _targetPool;
|
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>
|
//private LinkedList<int>
|
||||||
|
|
||||||
|
|
||||||
@ -36,30 +46,74 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
ExecuteWhere(_targetPool.Entites, groupFilter);
|
ExecuteWhere(_targetPool.Entites, groupFilter);
|
||||||
}
|
}
|
||||||
|
private ProfilerMarker _execute = new ProfilerMarker("Query.ExecuteJoin");
|
||||||
|
|
||||||
public sealed override void ExecuteJoin()
|
public sealed override void ExecuteJoin()
|
||||||
{
|
{
|
||||||
ExecuteWhere(_targetPool.Entites, groupFilter);
|
_execute.Begin();
|
||||||
if (_isInitTargetWorlds == false) InitTargetWorlds();
|
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
|
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)
|
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()
|
private void InitTargetWorlds()
|
||||||
{
|
{
|
||||||
foreach (var e in groupFilter)
|
foreach (var e in _targetPool.Entites)
|
||||||
{
|
{
|
||||||
ref readonly var rel = ref _targetPool.Read(e);
|
ref readonly var rel = ref _targetPool.Read(e);
|
||||||
if (rel.Target.IsNotNull)
|
//if (rel.Target.IsNotNull)
|
||||||
_targetWorld = EcsWorld.Worlds[rel.Target.world];
|
_targetWorld = EcsWorld.Worlds[rel.Target.world];
|
||||||
|
|
||||||
if (_targetWorld != null)
|
if (_targetWorld != null)
|
||||||
@ -68,16 +122,22 @@ namespace DCFApixels.DragonECS
|
|||||||
break;
|
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()
|
public EcsGroup.Enumerator GetEnumerator()
|
||||||
{
|
{
|
||||||
return groupFilter.GetEnumerator();
|
return groupFilter.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodesEnumrable GetNodes(int entityID)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public abstract class EcsJoinRelationQuery<TRelationComponent> : EcsJoinQueryBase
|
public abstract class EcsJoinRelationQuery<TRelationComponent> : EcsJoinQueryBase
|
||||||
where TRelationComponent : struct, IEcsRelationComponent
|
where TRelationComponent : struct, IEcsRelationComponent
|
||||||
|
@ -94,7 +94,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_groups = new List<WeakReference<EcsGroup>>();
|
_groups = new List<WeakReference<EcsGroup>>();
|
||||||
_allEntites = GetGroupFromPool();
|
_allEntites = GetGroupFromPool();
|
||||||
|
|
||||||
_queries = new EcsQuery[128];
|
_queries = new EcsQueryBase[128];
|
||||||
|
|
||||||
_entityCreate = _pipeline.GetRunner<IEcsEntityCreate>();
|
_entityCreate = _pipeline.GetRunner<IEcsEntityCreate>();
|
||||||
_entityDestry = _pipeline.GetRunner<IEcsEntityDestroy>();
|
_entityDestry = _pipeline.GetRunner<IEcsEntityDestroy>();
|
||||||
@ -241,7 +241,7 @@ namespace DCFApixels.DragonECS
|
|||||||
return new EcsEntity(entityID, _gens[entityID], uniqueID);
|
return new EcsEntity(entityID, _gens[entityID], uniqueID);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool EntityIsAlive(int entityID, short gen)
|
public bool EntityIsAlive(int entityID, short gen) //TODO пофиксить EntityIsAlive
|
||||||
{
|
{
|
||||||
return _gens[entityID] == gen;
|
return _gens[entityID] == gen;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ namespace DCFApixels.DragonECS
|
|||||||
//public ent ToEnt() => EcsWorld.Worlds[world].EntityIsAlive(id, gen) ? new ent(id) : default;
|
//public ent ToEnt() => EcsWorld.Worlds[world].EntityIsAlive(id, gen) ? new ent(id) : default;
|
||||||
public ent ToEnt() => new ent(id);
|
public ent ToEnt() => new ent(id);
|
||||||
|
|
||||||
|
public bool IsAlive => EcsWorld.Worlds[world].EntityIsAlive(id, gen);
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public EcsEntity(int id, short gen, short world) : this()
|
public EcsEntity(int id, short gen, short world) : this()
|
||||||
@ -98,15 +100,15 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
private static EcsProfilerMarker _IsAliveMarker = new EcsProfilerMarker("EcsEntity.IsAlive");
|
private static EcsProfilerMarker _IsAliveMarker = new EcsProfilerMarker("EcsEntity.IsAlive");
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsAlive(this ref EcsEntity self)
|
// public static bool IsAlive(this ref EcsEntity self)
|
||||||
{
|
// {
|
||||||
//using (_IsAliveMarker.Auto())
|
// //using (_IsAliveMarker.Auto())
|
||||||
//{
|
// //{
|
||||||
bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen);
|
// bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen);
|
||||||
if (!result) self = EcsEntity.NULL;
|
// if (!result) self = EcsEntity.NULL;
|
||||||
return result;
|
// return result;
|
||||||
//}
|
// //}
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ namespace DCFApixels.DragonECS
|
|||||||
_source = world;
|
_source = world;
|
||||||
_poolRunners = new PoolRunners(world.Pipeline);
|
_poolRunners = new PoolRunners(world.Pipeline);
|
||||||
|
|
||||||
|
_entities = EcsGroup.New(world);
|
||||||
|
|
||||||
_entityFlags = new bool[world.Capacity];
|
_entityFlags = new bool[world.Capacity];
|
||||||
_items = new T[world.Capacity];
|
_items = new T[world.Capacity];
|
||||||
_count = 0;
|
_count = 0;
|
||||||
|
151
src/Utils/EntityLinkedList.cs
Normal file
151
src/Utils/EntityLinkedList.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user