fixes & update

This commit is contained in:
Mikhail 2024-01-31 04:25:48 +08:00
parent 22d873ed38
commit 9c50a88266
6 changed files with 325 additions and 204 deletions

View File

@ -1,4 +1,11 @@
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public sealed class EcsArcWorld : EcsWorld { } public abstract class EcsArcWorld : EcsWorld { }
public sealed class EcsLoopArcWorld<TWorld> : EcsArcWorld
where TWorld : EcsWorld
{ }
public sealed class EcsArcWorld<TStartWorld, TEndWorld> : EcsArcWorld
where TStartWorld : EcsWorld
where TEndWorld : EcsWorld
{ }
} }

View File

@ -1,4 +1,5 @@
using System; using DCFApixels.DragonECS.Relations.Internal;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static DCFApixels.DragonECS.Relations.Utils.EcsJoin; using static DCFApixels.DragonECS.Relations.Utils.EcsJoin;
@ -41,7 +42,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _source.IsLoopArc; } get { return _source.IsLoopArc; }
} }
public EnumerableArcEnd this[int startEntityID] public EnumerableRelEnd this[int startEntityID]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _source[startEntityID]; } get { return _source[startEntityID]; }
@ -61,7 +62,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasEnd(int endEntityID) { return _source.HasEnd(endEntityID); } public bool HasEnd(int endEntityID) { return _source.HasEnd(endEntityID); }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EnumerableArcEnd GetRelEnds(int startEntityID) { return _source.GetRelEnds(startEntityID); } public EnumerableRelEnd GetRelEnds(int startEntityID) { return _source.GetRelEnds(startEntityID); }
#endregion #endregion
#region Internal #region Internal
@ -92,7 +93,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
private readonly BasketList _startBaskets; private readonly BasketList _startBaskets;
private readonly BasketList _endBaskets; private readonly BasketList _endBaskets;
private readonly RelInfo[] _relMapping; private readonly RelNodesInfo[] _relNodesMapping;
#region Properties #region Properties
public EcsReadonlyJoin Readonly public EcsReadonlyJoin Readonly
@ -131,7 +132,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
get { return _isLoop; } get { return _isLoop; }
} }
public EnumerableArcEnd this[int startEntityID] public EnumerableRelEnd this[int startEntityID]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return GetRelEnds(startEntityID); } get { return GetRelEnds(startEntityID); }
@ -145,60 +146,52 @@ namespace DCFApixels.DragonECS.Relations.Utils
_isLoop = arc.IsLoop; _isLoop = arc.IsLoop;
_startBaskets = new BasketList(); _startBaskets = new BasketList();
if (_isLoop) //if (_isLoop)
{ //{
_endBaskets = _startBaskets; // _endBaskets = _startBaskets;
} //}
else //else
{ //{
// _endBaskets = new BasketList();
//}
_endBaskets = new BasketList(); _endBaskets = new BasketList();
}
_relMapping = new RelInfo[arc.ArcWorld.Capacity]; _relNodesMapping = new RelNodesInfo[arc.ArcWorld.Capacity];
} }
#endregion #endregion
#region Add/Del #region Add/Del
public void Add(int relEntityID) public void Add(int relEntityID)
{ {
var (startEntityID, endEntityID) = _source.GetRelInfo(relEntityID); var (startEntityID, endEntityID) = _source.GetRelationInfo(relEntityID);
ref RelInfo arcInfo = ref _relMapping[relEntityID]; ref RelNodesInfo arcInfo = ref _relNodesMapping[relEntityID];
arcInfo.startNodeIndex = _startBaskets.AddToBasket(startEntityID, relEntityID); arcInfo.startNodeIndex = _startBaskets.AddToBasket(startEntityID, relEntityID);
if (_isLoop) //if (_isLoop)
{
arcInfo.endNodeIndex = arcInfo.startNodeIndex;
}
else
{
arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID);
}
//arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID);
//if (!_isLoop)
//{ //{
// arcInfo.startNodeIndex = _startBaskets.AddToBasket(startEntityID, relEntityID); // arcInfo.endNodeIndex = arcInfo.startNodeIndex;
//} //}
//else //else
//{ //{
// arcInfo.startNodeIndex = arcInfo.endNodeIndex; arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID);
//} //}
} }
public void Del(int relEntityID) public void Del(int relEntityID)
{ {
var (startEntityID, endEntityID) = _source.GetRelInfo(relEntityID); var (startEntityID, endEntityID) = _source.GetRelationInfo(relEntityID);
ref RelInfo relInfo = ref _relMapping[relEntityID]; ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
_startBaskets.RemoveFromBasket(startEntityID, relInfo.startNodeIndex); _startBaskets.RemoveFromBasket(startEntityID, relInfo.startNodeIndex);
if (!_isLoop) //if (!_isLoop)
{ //{
_startBaskets.RemoveFromBasket(endEntityID, relInfo.endNodeIndex); _startBaskets.RemoveFromBasket(endEntityID, relInfo.endNodeIndex);
} //}
} }
public void DelStart(int startEntityID) public void DelStart(int startEntityID)
{ {
foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID)) foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID))
{ {
var endEntityID = _source.GetRelEnd(relEntityID); var endEntityID = _source.GetRelEnd(relEntityID);
ref RelInfo relInfo = ref _relMapping[relEntityID]; ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
_endBaskets.RemoveFromBasket(endEntityID, relInfo.startNodeIndex); _endBaskets.RemoveFromBasket(endEntityID, relInfo.startNodeIndex);
} }
_startBaskets.RemoveBasket(startEntityID); _startBaskets.RemoveBasket(startEntityID);
@ -208,17 +201,75 @@ namespace DCFApixels.DragonECS.Relations.Utils
foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID)) foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID))
{ {
var startEntityID = _source.GetRelStart(relEntityID); var startEntityID = _source.GetRelStart(relEntityID);
ref RelInfo relInfo = ref _relMapping[relEntityID]; ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
_startBaskets.RemoveFromBasket(startEntityID, relInfo.endNodeIndex); _startBaskets.RemoveFromBasket(startEntityID, relInfo.endNodeIndex);
} }
_endBaskets.RemoveBasket(endEntityID); _endBaskets.RemoveBasket(endEntityID);
} }
private void DelStartAndDelRelEntities(int startEntityID, EcsArc arc)
{
foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID))
{
int endEntityID = _source.GetRelEnd(relEntityID);
int endNodeIndex = _relNodesMapping[relEntityID].endNodeIndex;
int revereceRelEntitiy = _endBaskets.Get(endNodeIndex);
//_endBaskets.RemoveFromBasket(endEntityID, endNodeIndex);
arc.ArcWorld.DelEntity(relEntityID);
//if(!_isLoop)
arc.ArcWorld.DelEntity(revereceRelEntitiy);
}
//_startBaskets.RemoveBasket(startEntityID);
}
private void DelEndAndDelRelEntities(int endEntityID, EcsArc arc)
{
foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID))
{
int startEntityID = _source.GetRelStart(relEntityID);
int startNodeIndex = _relNodesMapping[relEntityID].startNodeIndex;
int revereceRelEntitiy = _startBaskets.Get(startNodeIndex);
//_startBaskets.RemoveFromBasket(startEntityID, startNodeIndex);
arc.ArcWorld.DelEntity(relEntityID);
//if(!_isLoop)
arc.ArcWorld.DelEntity(revereceRelEntitiy);
}
//_endBaskets.RemoveBasket(endEntityID);
}
public struct FriendEcsArc
{
private EcsJoin _join;
public FriendEcsArc(EcsArc arc, EcsJoin join)
{
if (arc.IsInit_Internal != false)
{
Throw.UndefinedException();
}
_join = join;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DelStartAndDelRelEntities(int startEntityID, EcsArc arc)
{
_join.DelStartAndDelRelEntities(startEntityID, arc);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DelEndAndDelRelEntities(int endEntityID, EcsArc arc)
{
_join.DelEndAndDelRelEntities(endEntityID, arc);
}
}
#endregion #endregion
#region Has #region Has
public bool Has(int relEntityID) public bool Has(int relEntityID)
{ {
return _relMapping[relEntityID] != RelInfo.Empty; return _relNodesMapping[relEntityID] != RelNodesInfo.Empty;
} }
public bool HasStart(int startEntityID) public bool HasStart(int startEntityID)
{ {
@ -243,19 +294,19 @@ namespace DCFApixels.DragonECS.Relations.Utils
#region GetRelEnds #region GetRelEnds
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EnumerableArcEnd GetRelEnds(int startEntityID) public EnumerableRelEnd GetRelEnds(int startEntityID)
{ {
return new EnumerableArcEnd(_source, _startBaskets.GetBasketIterator(startEntityID).GetEnumerator()); return new EnumerableRelEnd(_source, _startBaskets.GetBasketIterator(startEntityID).GetEnumerator());
} }
#endregion #endregion
#region EnumerableArcEnd #region EnumerableArcEnd
public readonly ref struct EnumerableArcEnd //: IEnumerable<RelEnd> public readonly ref struct EnumerableRelEnd //: IEnumerable<RelEnd>
{ {
private readonly EcsArc _arc; private readonly EcsArc _arc;
private readonly BasketList.BasketIterator.Enumerator _iterator; private readonly BasketList.BasketIterator.Enumerator _iterator;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EnumerableArcEnd(EcsArc arc, BasketList.BasketIterator.Enumerator iterator) internal EnumerableRelEnd(EcsArc arc, BasketList.BasketIterator.Enumerator iterator)
{ {
_arc = arc; _arc = arc;
_iterator = iterator; _iterator = iterator;
@ -295,19 +346,19 @@ namespace DCFApixels.DragonECS.Relations.Utils
#endregion #endregion
#region ArcInfo #region ArcInfo
private struct RelInfo : IEquatable<RelInfo> private struct RelNodesInfo : IEquatable<RelNodesInfo>
{ {
public readonly static RelInfo Empty = default; public readonly static RelNodesInfo Empty = default;
public int startNodeIndex; public int startNodeIndex;
public int endNodeIndex; public int endNodeIndex;
#region Object #region Object
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is RelInfo && Equals((RelInfo)obj); return obj is RelNodesInfo && Equals((RelNodesInfo)obj);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RelInfo other) public bool Equals(RelNodesInfo other)
{ {
return startNodeIndex == other.startNodeIndex && return startNodeIndex == other.startNodeIndex &&
endNodeIndex == other.endNodeIndex; endNodeIndex == other.endNodeIndex;
@ -321,9 +372,9 @@ namespace DCFApixels.DragonECS.Relations.Utils
#region operators #region operators
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(RelInfo a, RelInfo b) => a.startNodeIndex == b.startNodeIndex && a.endNodeIndex == b.endNodeIndex; public static bool operator ==(RelNodesInfo a, RelNodesInfo b) => a.startNodeIndex == b.startNodeIndex && a.endNodeIndex == b.endNodeIndex;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(RelInfo a, RelInfo b) => a.startNodeIndex != b.startNodeIndex || a.endNodeIndex != b.endNodeIndex; public static bool operator !=(RelNodesInfo a, RelNodesInfo b) => a.startNodeIndex != b.startNodeIndex || a.endNodeIndex != b.endNodeIndex;
#endregion #endregion
} }
#endregion #endregion

View File

@ -1,4 +1,5 @@
using DCFApixels.DragonECS.Relations.Utils; using DCFApixels.DragonECS.Relations.Internal;
using DCFApixels.DragonECS.Relations.Utils;
using Leopotam.EcsLite; using Leopotam.EcsLite;
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -22,12 +23,20 @@ namespace DCFApixels.DragonECS
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>(); private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
private EcsJoin _joinEntities; private EcsJoin _joinEntities;
private EcsJoin.FriendEcsArc _joinEntitiesFriend;
private EcsGroup _relEntities; private EcsGroup _relEntities;
private RelEntityInfo[] _relEntityInfos; //N * (N - 1) / 2 private RelEntityInfo[] _relEntityInfos; //N * (N - 1) / 2
private bool _isLoop; private bool _isLoop;
private bool _isInit = false;
#region Properties #region Properties
internal bool IsInit_Internal
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _isInit; }
}
public EcsWorld StartWorld public EcsWorld StartWorld
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -65,7 +74,7 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
#region Constructors #region Constructors/Destroy
internal EcsArc(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld arcWorld) internal EcsArc(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld arcWorld)
{ {
_startWorld = startWorld; _startWorld = startWorld;
@ -85,15 +94,27 @@ namespace DCFApixels.DragonECS
_relEntities = EcsGroup.New(_arcWorld); _relEntities = EcsGroup.New(_arcWorld);
_joinEntities = new EcsJoin(this); _joinEntities = new EcsJoin(this);
_joinEntitiesFriend = new EcsJoin.FriendEcsArc(this, _joinEntities);
_isInit = true;
}
public void Destroy()
{
_startWorldHandler.Destroy();
_arcWorldHandler.Destroy();
//if (!_isLoop)
//{
_endWorldHandler.Destroy();
//}
} }
#endregion #endregion
#region New/Del #region New/Del
public int NewRelation(int startEntityID, int endEntityID) public int NewRelation(int startEntityID, int endEntityID)
{ {
if (Has(startEntityID, endEntityID)) if (HasRelation(startEntityID, endEntityID))
{ {
throw new EcsRelationException(); Throw.UndefinedRelationException();
} }
int relEntity = _arcWorld.NewEntity(); int relEntity = _arcWorld.NewEntity();
@ -106,61 +127,99 @@ namespace DCFApixels.DragonECS
} }
public void DelRelation(int startEntityID, int endEntityID) public void DelRelation(int startEntityID, int endEntityID)
{ {
if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity)) if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity))
{ {
throw new EcsRelationException();
}
_joinEntities.Del(relEntity);
_relationsMatrix.Remove(startEntityID, endEntityID);
_arcWorld.DelEntity(relEntity); _arcWorld.DelEntity(relEntity);
}
else
{
Throw.UndefinedRelationException();
}
//if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity))
//{
// Throw.UndefinedRelationException();
//}
//_joinEntities.Del(relEntity);
//
//_relationsMatrix.Remove(startEntityID, endEntityID);
//_arcWorld.DelEntity(relEntity);
//
//_relEntityInfos[relEntity] = RelEntityInfo.Empty;
//_relEntities.Remove(relEntity);
}
_relEntityInfos[relEntity] = RelEntityInfo.Empty; private void ClearRelation_Internal(int startEntityID, int endEntityID)
{
if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity))
{
_relEntities.Remove(relEntity); _relEntities.Remove(relEntity);
_joinEntities.Del(relEntity);
_relationsMatrix.Remove(startEntityID, endEntityID);
_relEntityInfos[relEntity] = RelEntityInfo.Empty;
}
} }
#endregion #endregion
#region Get/Has #region GetRelation/HasRelation
public bool Has(int startEntityID, int endEntityID) public bool HasRelation(int startEntityID, int endEntityID)
{ {
return _relationsMatrix.Contains(startEntityID, endEntityID); return _relationsMatrix.Contains(startEntityID, endEntityID);
} }
public int Get(int startEntityID, int endEntityID) public int GetRelation(int startEntityID, int endEntityID)
{ {
if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int arcEntityID)) if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntityID))
throw new EcsRelationException(); {
return arcEntityID; Throw.UndefinedRelationException();
} }
public bool TryGet(int startEntityID, int endEntityID, out int arcEntityID) return relEntityID;
}
public bool TryGetRelation(int startEntityID, int endEntityID, out int relEntityID)
{ {
return _relationsMatrix.TryGetValue(startEntityID, endEntityID, out arcEntityID); return _relationsMatrix.TryGetValue(startEntityID, endEntityID, out relEntityID);
} }
#endregion #endregion
#region ArcEntityInfo #region ArcEntityInfo
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsRel(int arcEntityID) public bool IsRelation(int relEntityID)
{
if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length)
{ {
if (arcEntityID <= 0 || arcEntityID >= _relEntityInfos.Length)
return false; return false;
return !_relEntityInfos[arcEntityID].IsEmpty; }
return !_relEntityInfos[relEntityID].IsEmpty;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public RelEntityInfo GetRelInfo(int arcEntityID) public RelEntityInfo GetRelationInfo(int relEntityID)
{ {
if (arcEntityID <= 0 || arcEntityID >= _relEntityInfos.Length) if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length)
throw new Exception(); {
return _relEntityInfos[arcEntityID]; Throw.UndefinedException();
}
return _relEntityInfos[relEntityID];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetRelStart(int arcEntityID) public int GetRelStart(int relEntityID)
{ {
return GetRelInfo(arcEntityID).start; return GetRelationInfo(relEntityID).start;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetRelEnd(int arcEntityID) public int GetRelEnd(int relEntityID)
{ {
return GetRelInfo(arcEntityID).end; return GetRelationInfo(relEntityID).end;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetInversedRelation(int relEntityID)
{
var (startEntityID, endEntityID) = GetRelationInfo(relEntityID);
return GetRelation(endEntityID, startEntityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetInversedRelation(int relEntityID, out int inversedRelEntityID)
{
var (startEntityID, endEntityID) = GetRelationInfo(relEntityID);
return TryGetRelation(endEntityID, startEntityID, out inversedRelEntityID);
} }
#endregion #endregion
@ -177,87 +236,84 @@ namespace DCFApixels.DragonECS
#region VertexWorldHandler #region VertexWorldHandler
private class ArcWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener private class ArcWorldHandler : IEcsWorldEventListener
{ {
private readonly EcsArc _arc; private readonly EcsArc _arc;
public ArcWorldHandler(EcsArc arc) public ArcWorldHandler(EcsArc arc)
{ {
_arc = arc; _arc = arc;
EcsArcWorld arcWorld = arc.ArcWorld; _arc.ArcWorld.AddListener(this);
arcWorld.AddListener(worldEventListener: this); }
arcWorld.AddListener(entityEventListener: this); public void Destroy()
{
_arc.ArcWorld.RemoveListener(this);
} }
#region Callbacks #region Callbacks
public void OnDelEntity(int entityID) { } public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> relEntityBuffer)
public void OnNewEntity(int entityID) { }
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
{ {
foreach (var relEntityID in buffer) foreach (var relEntityID in relEntityBuffer)
{ {
ref RelEntityInfo rel = ref _arc._relEntityInfos[relEntityID]; var (startEntityID, endEntityID) = _arc._relEntityInfos[relEntityID];
if (_arc._relationsMatrix.Contains(rel.start, rel.end)) _arc.ClearRelation_Internal(startEntityID, endEntityID);
{
_arc.DelRelation(rel.start, rel.end);
} }
} }
_arc._arcWorld.ReleaseDelEntityBuffer(buffer.Length);
}
public void OnWorldDestroy() { } public void OnWorldDestroy() { }
public void OnWorldResize(int newSize) public void OnWorldResize(int arcWorldNewSize)
{ {
Array.Resize(ref _arc._relEntityInfos, newSize); Array.Resize(ref _arc._relEntityInfos, arcWorldNewSize);
} }
#endregion #endregion
} }
private class StartWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener private class StartWorldHandler : IEcsWorldEventListener
{ {
private readonly EcsArc _arc; private readonly EcsArc _arc;
public StartWorldHandler(EcsArc arc) public StartWorldHandler(EcsArc arc)
{ {
_arc = arc; _arc = arc;
EcsWorld startWorld = arc.StartWorld; _arc.StartWorld.AddListener(this);
startWorld.AddListener(worldEventListener: this); }
startWorld.AddListener(entityEventListener: this); public void Destroy()
{
_arc.StartWorld.RemoveListener(this);
} }
#region Callbacks #region Callbacks
public void OnDelEntity(int startEntityID) { } public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
public void OnNewEntity(int startEntityID) { }
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
{ {
foreach (var startEntityID in buffer) foreach (var startEntityID in startEntityBuffer)
{ {
_arc._joinEntities.DelStart(startEntityID); //_arc._joinEntities.DelStart(startEntityID);
_arc._joinEntitiesFriend.DelStartAndDelRelEntities(startEntityID, _arc);
} }
_arc._arcWorld.ReleaseDelEntityBuffer(startEntityBuffer.Length);
} }
public void OnWorldDestroy() { } public void OnWorldDestroy() { }
public void OnWorldResize(int newSize) { } public void OnWorldResize(int startWorldNewSize) { }
#endregion #endregion
} }
private class EndWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener private class EndWorldHandler : IEcsWorldEventListener
{ {
private readonly EcsArc _arc; private readonly EcsArc _arc;
public EndWorldHandler(EcsArc arc) public EndWorldHandler(EcsArc arc)
{ {
_arc = arc; _arc = arc;
EcsWorld endWorld = arc.EndWorld; _arc.EndWorld.AddListener(this);
endWorld.AddListener(worldEventListener: this); }
endWorld.AddListener(entityEventListener: this); public void Destroy()
{
_arc.EndWorld.RemoveListener(this);
} }
#region Callbacks #region Callbacks
public void OnDelEntity(int endEntityID) { } public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> endEntityBuffer)
public void OnNewEntity(int endEntityID) { }
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
{ {
foreach (var endEntityID in buffer) foreach (var endEntityID in endEntityBuffer)
{ {
_arc._joinEntities.DelEnd(endEntityID); //_arc._joinEntities.DelEnd(endEntityID);
_arc._joinEntitiesFriend.DelEndAndDelRelEntities(endEntityID, _arc);
} }
_arc._arcWorld.ReleaseDelEntityBuffer(endEntityBuffer.Length);
} }
public void OnWorldDestroy() { } public void OnWorldDestroy() { }
public void OnWorldResize(int newSize) { } public void OnWorldResize(int endWorldNewSize) { }
#endregion #endregion
} }
#endregion #endregion

View File

@ -32,6 +32,10 @@ namespace DCFApixels.DragonECS
_arcsMapping[arcWorldID] = arc; _arcsMapping[arcWorldID] = arc;
return arc; return arc;
} }
public static bool IsRegistered(EcsArc arc)
{
return Has(arc.StartWorld.id, arc.EndWorld.id);
}
private static void Unregister(EcsWorld startWorld, EcsWorld endWorld) private static void Unregister(EcsWorld startWorld, EcsWorld endWorld)
{ {
int startWorldID = startWorld.id; int startWorldID = startWorld.id;
@ -39,6 +43,7 @@ namespace DCFApixels.DragonECS
EcsArc arc = _matrix[startWorldID, endWorldID]; EcsArc arc = _matrix[startWorldID, endWorldID];
_arcsMapping[arc.ArcWorld.id] = null; _arcsMapping[arc.ArcWorld.id] = null;
_matrix.Remove(startWorldID, endWorldID); _matrix.Remove(startWorldID, endWorldID);
arc.Destroy();
} }
#endregion #endregion
@ -63,8 +68,14 @@ namespace DCFApixels.DragonECS
#endif #endif
return _matrix[startWorld.id, otherWorld.id]; return _matrix[startWorld.id, otherWorld.id];
} }
private static bool Has(EcsWorld startWorld, EcsWorld endWorld) => Has(startWorld.id, endWorld.id); private static bool Has(EcsWorld startWorld, EcsWorld endWorld)
private static bool Has(int startWorldID, int endWorldID) => _matrix.Contains(startWorldID, endWorldID); {
return Has(startWorld.id, endWorld.id);
}
private static bool Has(int startWorldID, int endWorldID)
{
return _matrix.Contains(startWorldID, endWorldID);
}
#endregion #endregion
#region Extension #region Extension
@ -92,15 +103,45 @@ namespace DCFApixels.DragonECS
} }
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self, out EcsLoopArcWorld<TWorld> arcWorld)
public static EcsArc SetLoopArcAuto(this EcsWorld self) => SetArcAuto(self, self); where TWorld : EcsWorld
public static EcsArc SetArcAuto(this EcsWorld start, EcsWorld end) {
if (self == null)
{
Throw.ArgumentNull();
}
if (typeof(TWorld) != self.GetType())
{
EcsDebug.PrintWarning($"{nameof(TWorld)} is not {self.GetType().Name}");
}
arcWorld = new EcsLoopArcWorld<TWorld>();
return Register(self, self, arcWorld);
}
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end, out EcsArcWorld<TStartWorld, TEndWorld> arcWorld)
where TStartWorld : EcsWorld
where TEndWorld : EcsWorld
{ {
if (start == null || end == null) if (start == null || end == null)
{ {
Throw.ArgumentNull(); Throw.ArgumentNull();
} }
return Register(start, end, new EcsArcWorld()); if (typeof(TStartWorld) == typeof(EcsWorld) && typeof(TEndWorld) == typeof(EcsWorld))
{
EcsDebug.PrintWarning($"{nameof(TStartWorld)} is not {start.GetType().Name} or {nameof(TEndWorld)} is not {end.GetType().Name}");
}
arcWorld = new EcsArcWorld<TStartWorld, TEndWorld>();
return Register(start, end, arcWorld);
}
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self)
where TWorld : EcsWorld
{
return SetLoopArcAuto(self, out _);
}
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end)
where TStartWorld : EcsWorld
where TEndWorld : EcsWorld
{
return SetArcAuto(start, end, out _);
} }
public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld arc) => SetArc(self, self, arc); public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld arc) => SetArc(self, self, arc);

View File

@ -1,4 +1,5 @@
using System; using DCFApixels.DragonECS.Relations.Internal;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -42,16 +43,6 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private void Resize(int newSize) private void Resize(int newSize)
{ {
//int oldSize = _nodes.Length;
//Array.Resize(ref _nodes, newSize);
//int leftNode = newSize - 1;
//for (int i = newSize - 1, n = oldSize; i >= n; i--)
//{
// Link(i, leftNode);
// leftNode = i;
//}
//LinkToRecycled(newSize - 1, oldSize);
int oldSize = _nodes.Length; int oldSize = _nodes.Length;
Array.Resize(ref _nodes, newSize); Array.Resize(ref _nodes, newSize);
int leftNode = newSize - 1; int leftNode = newSize - 1;
@ -65,15 +56,6 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private void Initialize(int newSize) private void Initialize(int newSize)
{ {
//_nodes = new Node[newSize];
//int leftNode = newSize - 1;
//for (int i = newSize - 1, n = 1; i >= n; i--)
//{
// Link(i, leftNode);
// leftNode = i;
//}
//LinkToRecycled(newSize - 1, 1);
_nodes = new Node[newSize]; _nodes = new Node[newSize];
int leftNode = newSize - 1; int leftNode = newSize - 1;
for (int i = 1; i < newSize; i++) for (int i = 1; i < newSize; i++)
@ -101,13 +83,6 @@ namespace DCFApixels.DragonECS
{ {
return _nodes[nodeIndex].value; return _nodes[nodeIndex].value;
} }
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public ref readonly Node GetNode(int nodeIndex)
//{
// return ref _nodes[nodeIndex];
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -116,10 +91,15 @@ namespace DCFApixels.DragonECS
#if DEBUG #if DEBUG
if (nodeIndex <= 0) if (nodeIndex <= 0)
{ {
throw new ArgumentOutOfRangeException(); //Throw.ArgumentOutOfRange();
} }
#endif #endif
ref BasketInfo basketInfo = ref _baskets[basketIndex]; ref BasketInfo basketInfo = ref _baskets[basketIndex];
if (basketInfo.count <= 4)
{
}
ref var node = ref _nodes[nodeIndex]; ref var node = ref _nodes[nodeIndex];
int nextNode = node.next; int nextNode = node.next;
@ -208,20 +188,18 @@ namespace DCFApixels.DragonECS
} }
ref Node endNode = ref _nodes[endNodeIndex]; ref Node endNode = ref _nodes[endNodeIndex];
if (_recycledListLast != -1) LinkToRecycled(startNodeIndex, endNodeIndex);
{
//_nodes[_recycledListLast].next = startNodeIndex; //link recycled nodes;
//startNode.prev = _recycledListLast;
//_recycledListLast = endNodeIndex;
Link(_recycledListLast, startNodeIndex);
}
_recycledListLast = endNodeIndex;
Link(startNode.prev, endNode.next); Link(startNode.prev, endNode.next);
basket.count = 0; basket.count = 0;
} }
[MethodImpl(MethodImplOptions.NoInlining)]
private void UpBasketsSize(int minSize)
{
int newSize = GetHighBitNumber((uint)minSize) << 1;
Array.Resize(ref _baskets, newSize);
}
private static int GetHighBitNumber(uint bits) private static int GetHighBitNumber(uint bits)
{ {
if (bits == 0) if (bits == 0)
@ -256,32 +234,6 @@ namespace DCFApixels.DragonECS
return bit; return bit;
} }
//public int NewBasket()
//{
// int newBasketIndex;
// if(_recycledBusketsCount > 0)
// {
// newBasketIndex = _recycledBuskets[--_recycledBusketsCount];
// }
// else
// {
// newBasketIndex = _basketsCount;
// if(_basketsCount >= _baskets.Length)
// {
// Array.Resize(ref _baskets, _baskets.Length << 1);
// }
// }
// _basketsCount++;
// _baskets[newBasketIndex] = BasketInfo.Empty;
// return newBasketIndex;
//}
public static void CreateCrossRef(int leftBasketIndex, int rightBasketIndex)
{
}
#region Node #region Node
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
public struct Node public struct Node
@ -324,8 +276,7 @@ namespace DCFApixels.DragonECS
{ {
if (_baskets.Length <= basketIndex) if (_baskets.Length <= basketIndex)
{ {
int newSize = GetHighBitNumber((uint)basketIndex) << 1; UpBasketsSize(basketIndex);
Array.Resize(ref _baskets, newSize);
} }
return new BasketIterator(this, basketIndex); return new BasketIterator(this, basketIndex);
} }

View File

@ -11,6 +11,21 @@ namespace DCFApixels.DragonECS.Relations.Internal
{ {
throw new ArgumentNullException(); throw new ArgumentNullException();
} }
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void UndefinedException()
{
throw new Exception();
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void ArgumentOutOfRange()
{
throw new ArgumentOutOfRangeException();
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void UndefinedRelationException()
{
throw new EcsRelationException();
}
} }
} }