mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-11-13 00:55:55 +08:00
moving part of the API into a separate module
This commit is contained in:
parent
32429e5af8
commit
7cc02d00ba
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using DCFApixels.DragonECS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using DCFApixels.DragonECS.Internal;
|
||||
using DCFApixels.DragonECS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using DCFApixels.DragonECS.Internal;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -144,7 +145,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Queries
|
||||
#region Subjects
|
||||
public TSubject GetSubject<TSubject>() where TSubject : EcsSubject
|
||||
{
|
||||
int uniqueID = WorldMetaStorage.GetSubjectId<TSubject>(_worldTypeID);
|
||||
@ -154,104 +155,45 @@ namespace DCFApixels.DragonECS
|
||||
_subjects[uniqueID] = EcsSubject.Builder.Build<TSubject>(this);
|
||||
return (TSubject)_subjects[uniqueID];
|
||||
}
|
||||
#region Iterate
|
||||
public EcsSubjectIterator<TSubject> IterateFor<TSubject>(EcsReadonlyGroup sourceGroup, out TSubject subject) where TSubject : EcsSubject
|
||||
{
|
||||
|
||||
subject = GetSubject<TSubject>();
|
||||
return subject.GetIteratorFor(sourceGroup);
|
||||
}
|
||||
public EcsSubjectIterator<TSubject> IterateFor<TSubject>(EcsReadonlyGroup sourceGroup) where TSubject : EcsSubject
|
||||
{
|
||||
return GetSubject<TSubject>().GetIteratorFor(sourceGroup);
|
||||
}
|
||||
public EcsSubjectIterator<TSubject> Iterate<TSubject>(out TSubject subject) where TSubject : EcsSubject
|
||||
{
|
||||
subject = GetSubject<TSubject>();
|
||||
return subject.GetIterator();
|
||||
}
|
||||
public EcsSubjectIterator<TSubject> Iterate<TSubject>() where TSubject : EcsSubject
|
||||
{
|
||||
return GetSubject<TSubject>().GetIterator();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Where
|
||||
private EcsWhereExecutor<TSubject> GetWhereExecutor<TSubject>() where TSubject : EcsSubject
|
||||
#region Queries
|
||||
public TExecutor GetExecutor<TExecutor>(Func<EcsWorld, TExecutor> builder) where TExecutor: EcsQueryExecutor
|
||||
{
|
||||
int id = WorldMetaStorage.GetExecutorId<EcsWhereExecutor<TSubject>>(_worldTypeID);
|
||||
int id = WorldMetaStorage.GetExecutorId<TExecutor>(_worldTypeID);
|
||||
if (id >= _executors.Length)
|
||||
Array.Resize(ref _executors, _executors.Length << 1);
|
||||
if (_executors[id] == null)
|
||||
_executors[id] = new EcsWhereExecutor<TSubject>(GetSubject<TSubject>());
|
||||
return (EcsWhereExecutor<TSubject>)_executors[id];
|
||||
_executors[id] = builder(this);
|
||||
return (TExecutor)_executors[id];
|
||||
}
|
||||
|
||||
private EcsWhereExecutor<TSubject> EcsWhereExecutorBuilder<TSubject>(EcsWorld world) where TSubject : EcsSubject
|
||||
{
|
||||
return new EcsWhereExecutor<TSubject>(world.GetSubject<TSubject>());
|
||||
}
|
||||
public EcsWhereResult<TSubject> WhereFor<TSubject>(EcsReadonlyGroup sourceGroup, out TSubject subject) where TSubject : EcsSubject
|
||||
{
|
||||
var executor = GetWhereExecutor<TSubject>();
|
||||
var executor = GetExecutor(EcsWhereExecutorBuilder<TSubject>);
|
||||
subject = executor.Subject;
|
||||
return executor.ExecuteFor(sourceGroup);
|
||||
}
|
||||
public EcsWhereResult<TSubject> WhereFor<TSubject>(EcsReadonlyGroup sourceGroup) where TSubject : EcsSubject
|
||||
{
|
||||
return GetWhereExecutor<TSubject>().ExecuteFor(sourceGroup);
|
||||
return GetExecutor(EcsWhereExecutorBuilder<TSubject>).ExecuteFor(sourceGroup);
|
||||
}
|
||||
public EcsWhereResult<TSubject> Where<TSubject>(out TSubject subject) where TSubject : EcsSubject
|
||||
{
|
||||
var executor = GetWhereExecutor<TSubject>();
|
||||
var executor = GetExecutor(EcsWhereExecutorBuilder<TSubject>);
|
||||
subject = executor.Subject;
|
||||
return executor.Execute();
|
||||
}
|
||||
public EcsWhereResult<TSubject> Where<TSubject>() where TSubject : EcsSubject
|
||||
{
|
||||
return GetWhereExecutor<TSubject>().Execute();
|
||||
return GetExecutor(EcsWhereExecutorBuilder<TSubject>).Execute();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Join
|
||||
private EcsJoinAttachExecutor<TSubject, TAttachComponent> GetJoinAttachExecutor<TSubject, TAttachComponent>()
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
int id = WorldMetaStorage.GetExecutorId<EcsJoinAttachExecutor<TSubject, TAttachComponent>>(_worldTypeID);
|
||||
if (id >= _executors.Length)
|
||||
Array.Resize(ref _executors, _executors.Length << 1);
|
||||
if (_executors[id] == null)
|
||||
_executors[id] = new EcsJoinAttachExecutor<TSubject, TAttachComponent>(GetSubject<TSubject>());
|
||||
return (EcsJoinAttachExecutor<TSubject, TAttachComponent>)_executors[id];
|
||||
}
|
||||
public EcsJoinAttachResult<TSubject, TAttachComponent> JoinFor<TSubject, TAttachComponent>(EcsReadonlyGroup sourceGroup, out TSubject subject)
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
var executor = GetJoinAttachExecutor<TSubject, TAttachComponent>();
|
||||
subject = executor.Subject;
|
||||
return executor.ExecuteFor(sourceGroup);
|
||||
}
|
||||
public EcsJoinAttachResult<TSubject, TAttachComponent> JoinFor<TSubject, TAttachComponent>(EcsReadonlyGroup sourceGroup)
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
return GetJoinAttachExecutor<TSubject, TAttachComponent>().ExecuteFor(sourceGroup);
|
||||
}
|
||||
public EcsJoinAttachResult<TSubject, TAttachComponent> Join<TSubject, TAttachComponent>(out TSubject subject)
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
var executor = GetJoinAttachExecutor<TSubject, TAttachComponent>();
|
||||
subject = executor.Subject;
|
||||
return executor.Execute();
|
||||
}
|
||||
public EcsJoinAttachResult<TSubject, TAttachComponent> Join<TSubject, TAttachComponent>()
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
return GetJoinAttachExecutor<TSubject, TAttachComponent>().Execute();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsMatchesMask
|
||||
public bool IsMatchesMask(EcsMask mask, int entityID)
|
||||
{
|
||||
|
||||
@ -1,189 +0,0 @@
|
||||
using Unity.Profiling;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public sealed class EcsJoinAttachExecutor<TSubject, TAttachComponent> : EcsQueryExecutor
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
private readonly TSubject _subject;
|
||||
internal readonly EcsGroup _filteredGroup;
|
||||
private EcsWorld _targetWorld;
|
||||
|
||||
private EcsAttachPool<TAttachComponent> _targetPool;
|
||||
|
||||
private int _targetWorldCapacity = -1;
|
||||
private int _targetPoolCapacity = -1;
|
||||
|
||||
private int[] _mapping;
|
||||
private int[] _counts;
|
||||
private EntityLinkedList _linkedBasket;
|
||||
|
||||
private bool _isInitTargetWorld = false;
|
||||
|
||||
private ProfilerMarker _executeJoin = new ProfilerMarker("JoinAttachQuery.Join");
|
||||
|
||||
private long _executeVersion;
|
||||
|
||||
#region Properties
|
||||
public TSubject Subject => _subject;
|
||||
internal long ExecuteVersion => _executeVersion;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsJoinAttachExecutor(TSubject subject)
|
||||
{
|
||||
_subject = subject;
|
||||
_filteredGroup = EcsGroup.New(subject.World);
|
||||
_targetPool = subject.World.GetPool<TAttachComponent>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public EcsJoinAttachResult<TSubject, TAttachComponent> Execute() => ExecuteFor(_targetPool.Entities);
|
||||
public EcsJoinAttachResult<TSubject, TAttachComponent> ExecuteFor(EcsReadonlyGroup sourceGroup)
|
||||
{
|
||||
_executeJoin.Begin();
|
||||
var world = _subject.World;
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения.
|
||||
#endif
|
||||
if (!_isInitTargetWorld)
|
||||
InitTargetWorlds(sourceGroup.World);
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
else
|
||||
if (_targetWorld != sourceGroup.World) throw new System.ArgumentException();//TODO составить текст исключения. это проверка на то что пользователь использует правильный мир
|
||||
#endif
|
||||
|
||||
//Подготовка массивов
|
||||
if (_targetWorldCapacity < _targetWorld.Capacity)
|
||||
{
|
||||
_targetWorldCapacity = _targetWorld.Capacity;
|
||||
_mapping = new int[_targetWorldCapacity];
|
||||
_counts = new int[_targetWorldCapacity];
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayUtility.Fill(_counts, 0);
|
||||
ArrayUtility.Fill(_mapping, 0);
|
||||
}
|
||||
if (_targetPoolCapacity < _targetPool.Capacity)
|
||||
{
|
||||
_targetPoolCapacity = _targetPool.Capacity;
|
||||
_linkedBasket.Resize(_targetPoolCapacity);
|
||||
}
|
||||
_linkedBasket.Clear();
|
||||
//Конец подготовки массивов
|
||||
|
||||
var iterator = new EcsSubjectIterator<TSubject>(_subject, sourceGroup);
|
||||
foreach (var attachID in iterator)
|
||||
{
|
||||
entlong attachTarget = _targetPool.Read(attachID).Target;
|
||||
if (!attachTarget.IsAlive)
|
||||
{
|
||||
//_targetPool.Del(attachID);
|
||||
continue;
|
||||
}
|
||||
int attachTargetID = attachTarget.id;
|
||||
//if (!CheckMaskInternal(targetWorldWhereQuery.query.mask, attachTargetID)) continue; //TODO проверить что все работает //исчключить все аттачи, цели которых не входят в targetWorldWhereQuery
|
||||
|
||||
ref int nodeIndex = ref _mapping[attachTargetID];
|
||||
if (nodeIndex <= 0)
|
||||
nodeIndex = _linkedBasket.Add(attachID);
|
||||
else
|
||||
_linkedBasket.Insert(nodeIndex, attachID);
|
||||
_counts[attachTargetID]++;
|
||||
}
|
||||
|
||||
_executeVersion++;
|
||||
_executeJoin.End();
|
||||
|
||||
return new EcsJoinAttachResult<TSubject, TAttachComponent>(_subject, this , _executeVersion);
|
||||
}
|
||||
private void InitTargetWorlds(EcsWorld targetWorld)
|
||||
{
|
||||
_targetWorld = targetWorld;
|
||||
|
||||
_targetWorldCapacity = _targetWorld.Capacity;
|
||||
_mapping = new int[_targetWorldCapacity];
|
||||
_counts = new int[_targetWorldCapacity];
|
||||
|
||||
_targetPoolCapacity = _targetPool.Capacity;
|
||||
_linkedBasket = new EntityLinkedList(_targetPoolCapacity);
|
||||
_isInitTargetWorld = true;
|
||||
}
|
||||
internal sealed override void Destroy()
|
||||
{
|
||||
_filteredGroup.Release();
|
||||
_targetWorld = null;
|
||||
_mapping = null;
|
||||
_counts = null;
|
||||
_linkedBasket = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Internal result methods
|
||||
internal bool Has(int attachedEnttiyID) => _filteredGroup.Has(attachedEnttiyID);
|
||||
internal EntityLinkedList.EnumerableSpan GetNodes(int entityID) => _linkedBasket.Span(_mapping[entityID], _counts[entityID]);
|
||||
internal int GetNode(int entityID) => _counts[entityID] > 0 ? _linkedBasket.Get(_mapping[entityID]) : 0;
|
||||
internal int GetNodesCount(int entityID) => _counts[entityID];
|
||||
internal bool HasNode(int entityID, int attachedEntityID) => _filteredGroup.Has(attachedEntityID) && _targetPool.Read(attachedEntityID).Target.id == entityID;
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region JoinAttachExecuter Results
|
||||
public readonly ref struct EcsJoinAttachResult<TSubject, TAttachComponent>
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
public readonly TSubject s;
|
||||
private readonly EcsJoinAttachExecutor<TSubject, TAttachComponent> _executer;
|
||||
private readonly long _verison;
|
||||
|
||||
public bool IsRelevant => _verison == _executer.ExecuteVersion;
|
||||
|
||||
public EcsJoinAttachResult(TSubject s, EcsJoinAttachExecutor<TSubject, TAttachComponent> executer, long version)
|
||||
{
|
||||
this.s = s;
|
||||
_executer = executer;
|
||||
_verison = version;
|
||||
}
|
||||
|
||||
public bool Has(int attachedEnttiyID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.Has(attachedEnttiyID);
|
||||
}
|
||||
public EntityLinkedList.EnumerableSpan GetNodes(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.GetNodes(entityID);
|
||||
}
|
||||
public int GetNode(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.GetNode(entityID);
|
||||
}
|
||||
public int GetNodesCount(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.GetNodesCount(entityID);
|
||||
}
|
||||
public bool HasNode(int entityID, int attachedEntityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new System.InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.HasNode(entityID, attachedEntityID);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@ -1,198 +0,0 @@
|
||||
using System;
|
||||
using Unity.Profiling;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public sealed class EcsJoinHierarchyExecutor<TSubject, TAttachComponent> : EcsQueryExecutor
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
private readonly TSubject _subject;
|
||||
internal readonly EcsGroup _filteredGroup;
|
||||
private EcsWorld _targetWorld;
|
||||
|
||||
private EcsAttachPool<TAttachComponent> _targetPool;
|
||||
|
||||
private int _targetWorldCapacity = -1;
|
||||
private int _targetPoolCapacity = -1;
|
||||
|
||||
private int[] _mapping;
|
||||
private int[] _counts;
|
||||
private EntityLinkedList _linkedBasket;
|
||||
|
||||
private bool _isInitTargetWorld = false;
|
||||
|
||||
private ProfilerMarker _executeWhere = new ProfilerMarker("JoinAttachQuery.Where");
|
||||
private ProfilerMarker _executeJoin = new ProfilerMarker("JoinAttachQuery.Join");
|
||||
|
||||
private long _executeVersion;
|
||||
|
||||
#region Properties
|
||||
public TSubject Subject => _subject;
|
||||
internal long ExecuteVersion => _executeVersion;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsJoinHierarchyExecutor(TSubject subject)
|
||||
{
|
||||
_subject = subject;
|
||||
_filteredGroup = EcsGroup.New(subject.World);
|
||||
_targetPool = subject.World.GetPool<TAttachComponent>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public EcsJoinHierarchyResult<TSubject, TAttachComponent> Execute() => ExecuteFor(_targetPool.Entities);
|
||||
public EcsJoinHierarchyResult<TSubject, TAttachComponent> ExecuteFor(EcsReadonlyGroup sourceGroup)
|
||||
{
|
||||
var world = _subject.World;
|
||||
_executeJoin.Begin();
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (sourceGroup.IsNull) throw new ArgumentNullException();//TODO составить текст исключения.
|
||||
#endif
|
||||
if (!_isInitTargetWorld)
|
||||
InitTargetWorlds(sourceGroup.World);
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
else
|
||||
if (_targetWorld != sourceGroup.World) throw new ArgumentException();//TODO составить текст исключения. это проверка на то что пользователь использует правильный мир
|
||||
#endif
|
||||
|
||||
//Подготовка массивов
|
||||
if (_targetWorldCapacity < _targetWorld.Capacity)
|
||||
{
|
||||
_targetWorldCapacity = _targetWorld.Capacity;
|
||||
_mapping = new int[_targetWorldCapacity];
|
||||
_counts = new int[_targetWorldCapacity];
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayUtility.Fill(_counts, 0);
|
||||
ArrayUtility.Fill(_mapping, 0);
|
||||
}
|
||||
if (_targetPoolCapacity < _targetPool.Capacity)
|
||||
{
|
||||
_targetPoolCapacity = _targetPool.Capacity;
|
||||
_linkedBasket.Resize(_targetPoolCapacity);
|
||||
}
|
||||
_linkedBasket.Clear();
|
||||
//Конец подготовки массивов
|
||||
|
||||
var iterator = new EcsSubjectIterator<TSubject>(_subject, sourceGroup);
|
||||
foreach (var attachID in iterator)
|
||||
{
|
||||
entlong attachTarget = _targetPool.Read(attachID).Target;
|
||||
if (!attachTarget.IsAlive)
|
||||
{
|
||||
//_targetPool.Del(attachID);
|
||||
continue;
|
||||
}
|
||||
int attachTargetID = attachTarget.id;
|
||||
//if (!CheckMaskInternal(targetWorldWhereQuery.query.mask, attachTargetID)) continue; //TODO проверить что все работает //исчключить все аттачи, цели которых не входят в targetWorldWhereQuery
|
||||
|
||||
ref int nodeIndex = ref _mapping[attachTargetID];
|
||||
if (nodeIndex <= 0)
|
||||
nodeIndex = _linkedBasket.Add(attachID);
|
||||
else
|
||||
_linkedBasket.Insert(nodeIndex, attachID);
|
||||
_counts[attachTargetID]++;
|
||||
}
|
||||
|
||||
_executeVersion++;
|
||||
_executeJoin.End();
|
||||
|
||||
return new EcsJoinHierarchyResult<TSubject, TAttachComponent>(_subject, this , _executeVersion);
|
||||
}
|
||||
private void InitTargetWorlds(EcsWorld targetWorld)
|
||||
{
|
||||
_targetWorld = targetWorld;
|
||||
|
||||
_targetWorldCapacity = _targetWorld.Capacity;
|
||||
_mapping = new int[_targetWorldCapacity];
|
||||
_counts = new int[_targetWorldCapacity];
|
||||
|
||||
_targetPoolCapacity = _targetPool.Capacity;
|
||||
_linkedBasket = new EntityLinkedList(_targetPoolCapacity);
|
||||
_isInitTargetWorld = true;
|
||||
}
|
||||
internal sealed override void Destroy()
|
||||
{
|
||||
_filteredGroup.Release();
|
||||
_targetWorld = null;
|
||||
_mapping = null;
|
||||
_counts = null;
|
||||
_linkedBasket = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Internal result methods
|
||||
internal bool Has(int attachedEnttiyID) => _filteredGroup.Has(attachedEnttiyID);
|
||||
|
||||
internal EntityLinkedList.EnumerableSpan GetNodes(int entityID) => _linkedBasket.Span(_mapping[entityID], _counts[entityID]);
|
||||
internal int GetNode(int entityID) => _counts[entityID] > 0 ? _linkedBasket.Get(_mapping[entityID]) : 0;
|
||||
internal int GetNodesCount(int entityID) => _counts[entityID];
|
||||
internal bool HasNode(int entityID, int attachedEntityID) => _filteredGroup.Has(attachedEntityID) && _targetPool.Read(attachedEntityID).Target.id == entityID;
|
||||
|
||||
|
||||
internal EntityLinkedList.EnumerableSpan GetSubNodes(int entityID) => throw new NotImplementedException();
|
||||
internal int GetSubNode(int entityID) => throw new NotImplementedException();
|
||||
internal bool GetSubNodesCount(int entityID, int attachedEntityID) => throw new NotImplementedException();
|
||||
internal bool HasSubNode(int entityID, int attachedEntityID) => throw new NotImplementedException();
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region JoinAttachExecuter Results
|
||||
public readonly ref struct EcsJoinHierarchyResult<TSubject, TAttachComponent>
|
||||
where TSubject : EcsSubject
|
||||
where TAttachComponent : struct, IEcsAttachComponent
|
||||
{
|
||||
public readonly TSubject s;
|
||||
private readonly EcsJoinHierarchyExecutor<TSubject, TAttachComponent> _executer;
|
||||
private readonly long _verison;
|
||||
|
||||
public bool IsRelevant => _verison == _executer.ExecuteVersion;
|
||||
|
||||
public EcsJoinHierarchyResult(TSubject s, EcsJoinHierarchyExecutor<TSubject, TAttachComponent> executer, long version)
|
||||
{
|
||||
this.s = s;
|
||||
_executer = executer;
|
||||
_verison = version;
|
||||
}
|
||||
|
||||
public bool Has(int attachedEnttiyID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.Has(attachedEnttiyID);
|
||||
}
|
||||
public EntityLinkedList.EnumerableSpan GetNodes(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.GetNodes(entityID);
|
||||
}
|
||||
public int GetNode(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.GetNode(entityID);
|
||||
}
|
||||
public int GetNodesCount(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.GetNodesCount(entityID);
|
||||
}
|
||||
public bool HasNode(int entityID, int attachedEntityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!IsRelevant) throw new InvalidOperationException();//TODO составить текст исключения.
|
||||
#endif
|
||||
return _executer.HasNode(entityID, attachedEntityID);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
{
|
||||
public abstract class EcsQueryExecutor
|
||||
{
|
||||
internal abstract void Destroy();
|
||||
internal void Destroy() => OnDestroy();
|
||||
protected abstract void OnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ namespace DCFApixels.DragonECS
|
||||
return new EcsWhereResult<TSubject>(this, _filteredGroup.Readonly);
|
||||
}
|
||||
}
|
||||
internal sealed override void Destroy()
|
||||
protected sealed override void OnDestroy()
|
||||
{
|
||||
_filteredGroup.Release();
|
||||
}
|
||||
|
||||
@ -1,140 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
//íå âëèÿåò íà ñ÷åò÷èê êîìïîíåíòîâ íà ñóùíîñòè
|
||||
/// <summary>Pool for IEcsNotNullComponent components</summary>
|
||||
public sealed class EcsNotNullPool<T> : IEcsPoolImplementation<T>, IEnumerable<T> //IntelliSense hack
|
||||
where T : struct, IEcsNotNullComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private int _id;
|
||||
|
||||
private T[] _items; //sparse
|
||||
private int _count;
|
||||
|
||||
private IEcsComponentReset<T> _componentResetHandler;
|
||||
private IEcsComponentCopy<T> _componentCopyHandler;
|
||||
|
||||
private List<IEcsPoolEventListener> _listeners;
|
||||
|
||||
#region Properites
|
||||
public int Count => _count;
|
||||
public int Capacity => _items.Length;
|
||||
public int ComponentID => _id;
|
||||
public Type ComponentType => typeof(T);
|
||||
public EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||
{
|
||||
_source = world;
|
||||
_id = componentID;
|
||||
|
||||
_items = new T[world.Capacity];
|
||||
_count = 0;
|
||||
|
||||
_listeners = new List<IEcsPoolEventListener>();
|
||||
|
||||
_componentResetHandler = EcsComponentResetHandler<T>.instance;
|
||||
_componentCopyHandler = EcsComponentCopyHandler<T>.instance;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Write(int entityID)
|
||||
{
|
||||
_listeners.InvokeOnWrite(entityID);
|
||||
return ref _items[entityID];
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(int entityID)
|
||||
{
|
||||
return ref _items[entityID];
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Has(int entityID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public void Copy(int fromEntityID, int toEntityID)
|
||||
{
|
||||
_componentCopyHandler.Copy(ref Write(fromEntityID), ref Write(toEntityID));
|
||||
}
|
||||
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
||||
{
|
||||
_componentCopyHandler.Copy(ref Write(fromEntityID), ref toWorld.GetPool<T>().Write(toEntityID));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Callbacks
|
||||
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
||||
{
|
||||
Array.Resize(ref _items, newSize);
|
||||
}
|
||||
void IEcsPoolImplementation.OnWorldDestroy() { }
|
||||
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
|
||||
{
|
||||
foreach (var entityID in buffer)
|
||||
_componentResetHandler.Reset(ref _items[entityID]);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
ref T IEcsPool<T>.Add(int entityID) => ref Write(entityID);
|
||||
ref readonly T IEcsPool<T>.Read(int entityID) => ref Read(entityID);
|
||||
ref T IEcsPool<T>.Write(int entityID) => ref Write(entityID);
|
||||
void IEcsPool.Del(int entityID) { }
|
||||
void IEcsPool.AddRaw(int entityID, object dataRaw) => Write(entityID) = (T)dataRaw;
|
||||
object IEcsPool.GetRaw(int entityID) => Write(entityID);
|
||||
void IEcsPool.SetRaw(int entityID, object dataRaw) => Write(entityID) = (T)dataRaw;
|
||||
#endregion
|
||||
|
||||
#region Listeners
|
||||
public void AddListener(IEcsPoolEventListener listener)
|
||||
{
|
||||
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||
_listeners.Add(listener);
|
||||
}
|
||||
public void RemoveListener(IEcsPoolEventListener listener)
|
||||
{
|
||||
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||
_listeners.Remove(listener);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerator - IntelliSense hack
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
|
||||
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
|
||||
#endregion
|
||||
}
|
||||
/// <summary>
|
||||
/// Not null component. Is present on all entities, without explicit addition and cannot be deleted
|
||||
/// </summary>
|
||||
public interface IEcsNotNullComponent { }
|
||||
public static class EcsNotNullPoolExt
|
||||
{
|
||||
public static EcsNotNullPool<TNotNullComponent> GetPool<TNotNullComponent>(this EcsWorld self) where TNotNullComponent : struct, IEcsNotNullComponent
|
||||
{
|
||||
return self.GetPool<TNotNullComponent, EcsNotNullPool<TNotNullComponent>>();
|
||||
}
|
||||
|
||||
public static EcsNotNullPool<TNotNullComponent> Include<TNotNullComponent>(this EcsSubjectBuilderBase self) where TNotNullComponent : struct, IEcsNotNullComponent
|
||||
{
|
||||
return self.Include<TNotNullComponent, EcsNotNullPool<TNotNullComponent>>();
|
||||
}
|
||||
public static EcsNotNullPool<TNotNullComponent> Exclude<TNotNullComponent>(this EcsSubjectBuilderBase self) where TNotNullComponent : struct, IEcsNotNullComponent
|
||||
{
|
||||
return self.Exclude<TNotNullComponent, EcsNotNullPool<TNotNullComponent>>();
|
||||
}
|
||||
public static EcsNotNullPool<TNotNullComponent> Optional<TNotNullComponent>(this EcsSubjectBuilderBase self) where TNotNullComponent : struct, IEcsNotNullComponent
|
||||
{
|
||||
return self.Optional<TNotNullComponent, EcsNotNullPool<TNotNullComponent>>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,177 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
using static EcsPoolThrowHalper;
|
||||
public sealed class EcsSinglePool<T> : IEcsPoolImplementation<T>, IEnumerable<T> //IntelliSense hack
|
||||
where T : struct, IEcsSingleComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private int _id;
|
||||
|
||||
private int[] _mapping;
|
||||
|
||||
private int _count;
|
||||
private T _component;
|
||||
|
||||
private List<IEcsPoolEventListener> _listeners;
|
||||
|
||||
#region Properites
|
||||
public ref T Instance
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref _component;
|
||||
}
|
||||
public int Count => _count;
|
||||
int IEcsPool.Capacity => -1;
|
||||
public int ComponentID => _id;
|
||||
public Type ComponentType => typeof(T);
|
||||
public EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||
{
|
||||
_source = world;
|
||||
_id = componentID;
|
||||
|
||||
_mapping = new int[world.Capacity];
|
||||
_count = 0;
|
||||
_listeners = new List<IEcsPoolEventListener>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public ref T Add(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (Has(entityID)) ThrowAlreadyHasComponent<T>(entityID);
|
||||
#endif
|
||||
_mapping[entityID] = ++_count;
|
||||
this.IncrementEntityComponentCount(entityID);
|
||||
_listeners.InvokeOnAddAndWrite(entityID);
|
||||
return ref _component;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Write(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
||||
#endif
|
||||
_listeners.InvokeOnWrite(entityID);
|
||||
return ref _component;
|
||||
}
|
||||
public ref T TryAddOrWrite(int entityID)
|
||||
{
|
||||
if (!Has(entityID))
|
||||
return ref Add(entityID);
|
||||
return ref Write(entityID);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
||||
#endif
|
||||
return ref _component;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Has(int entityID)
|
||||
{
|
||||
return _mapping[entityID] > 0;
|
||||
}
|
||||
public void Del(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
||||
#endif
|
||||
_mapping[entityID] = 0;
|
||||
_count--;
|
||||
this.DecrementEntityComponentCount(entityID);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
}
|
||||
public void TryDel(int entityID)
|
||||
{
|
||||
if (Has(entityID)) Del(entityID);
|
||||
}
|
||||
public void Copy(int fromEntityID, int toEntityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(fromEntityID)) ThrowNotHaveComponent<T>(fromEntityID);
|
||||
#endif
|
||||
TryAddOrWrite(toEntityID);
|
||||
}
|
||||
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (!Has(fromEntityID)) ThrowNotHaveComponent<T>(fromEntityID);
|
||||
#endif
|
||||
toWorld.GetPool<T>().TryAddOrWrite(toEntityID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Callbacks
|
||||
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
||||
{
|
||||
Array.Resize(ref _mapping, newSize);
|
||||
}
|
||||
void IEcsPoolImplementation.OnWorldDestroy() { }
|
||||
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
|
||||
{
|
||||
foreach (var entityID in buffer)
|
||||
TryDel(entityID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
void IEcsPool.AddRaw(int entityID, object dataRaw) => Instance = (T)dataRaw;
|
||||
object IEcsPool.GetRaw(int entityID) => Instance;
|
||||
void IEcsPool.SetRaw(int entityID, object dataRaw) => Instance = (T)dataRaw;
|
||||
#endregion
|
||||
|
||||
#region Listeners
|
||||
public void AddListener(IEcsPoolEventListener listener)
|
||||
{
|
||||
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||
_listeners.Add(listener);
|
||||
}
|
||||
public void RemoveListener(IEcsPoolEventListener listener)
|
||||
{
|
||||
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||
_listeners.Remove(listener);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerator - IntelliSense hack
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
|
||||
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
|
||||
#endregion
|
||||
}
|
||||
/// <summary>Singleton component</summary>
|
||||
public interface IEcsSingleComponent { }
|
||||
public static class EcsSinglePoolExt
|
||||
{
|
||||
public static EcsSinglePool<TSingleComponent> GetPool<TSingleComponent>(this EcsWorld self)
|
||||
where TSingleComponent : struct, IEcsSingleComponent
|
||||
{
|
||||
return self.GetPool<TSingleComponent, EcsSinglePool<TSingleComponent>>();
|
||||
}
|
||||
|
||||
public static EcsSinglePool<TSingleComponent> Include<TSingleComponent>(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent
|
||||
{
|
||||
return self.Include<TSingleComponent, EcsSinglePool<TSingleComponent>>();
|
||||
}
|
||||
public static EcsSinglePool<TSingleComponent> Exclude<TSingleComponent>(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent
|
||||
{
|
||||
return self.Exclude<TSingleComponent, EcsSinglePool<TSingleComponent>>();
|
||||
}
|
||||
public static EcsSinglePool<TSingleComponent> Optional<TSingleComponent>(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent
|
||||
{
|
||||
return self.Optional<TSingleComponent, EcsSinglePool<TSingleComponent>>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
namespace DCFApixels.DragonECS.Utils
|
||||
{
|
||||
internal static class ArrayUtility
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
namespace DCFApixels.DragonECS.Utils
|
||||
{
|
||||
internal sealed class IntDispenser
|
||||
{
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public static class Extensions
|
||||
public static class IntExtensions
|
||||
{
|
||||
public static entlong ToEntityLong(this int self, EcsWorld world)
|
||||
{
|
||||
@ -6,7 +6,7 @@ using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
namespace DCFApixels.DragonECS.Utils
|
||||
{
|
||||
public class SparseArray<TValue>
|
||||
{
|
||||
|
||||
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
namespace DCFApixels.DragonECS.Utils
|
||||
{
|
||||
public class SparseSet : IEnumerable<int>, ICollection<int>, IReadOnlyCollection<int>
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user