mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-18 20:04:35 +08:00
stash
This commit is contained in:
parent
3c79ea24e3
commit
08b25ed671
@ -1,11 +1,21 @@
|
|||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
public abstract class EcsArcWorld : EcsWorld { }
|
public abstract class EcsArcWorld : EcsWorld
|
||||||
|
{
|
||||||
|
public EcsArcWorld() : base(null) { }
|
||||||
|
public EcsArcWorld(IEcsWorldConfig config) : base(config) { }
|
||||||
|
}
|
||||||
public sealed class EcsLoopArcWorld<TWorld> : EcsArcWorld
|
public sealed class EcsLoopArcWorld<TWorld> : EcsArcWorld
|
||||||
where TWorld : EcsWorld
|
where TWorld : EcsWorld
|
||||||
{ }
|
{
|
||||||
|
public EcsLoopArcWorld() : base(null) { }
|
||||||
|
public EcsLoopArcWorld(IEcsWorldConfig config) : base(config) { }
|
||||||
|
}
|
||||||
public sealed class EcsArcWorld<TStartWorld, TEndWorld> : EcsArcWorld
|
public sealed class EcsArcWorld<TStartWorld, TEndWorld> : EcsArcWorld
|
||||||
where TStartWorld : EcsWorld
|
where TStartWorld : EcsWorld
|
||||||
where TEndWorld : EcsWorld
|
where TEndWorld : EcsWorld
|
||||||
{ }
|
{
|
||||||
|
public EcsArcWorld() : base(null) { }
|
||||||
|
public EcsArcWorld(IEcsWorldConfig config) : base(config) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
using System;
|
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.EcsGraph;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Utils
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
public readonly ref struct EcsReadonlyJoin
|
public readonly ref struct EcsReadonlyGraph
|
||||||
{
|
{
|
||||||
private readonly EcsJoin _source;
|
private readonly EcsGraph _source;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public bool IsNull => _source == null;
|
public bool IsNull => _source == null;
|
||||||
@ -51,7 +51,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public EcsReadonlyJoin(EcsJoin source) { _source = source; }
|
public EcsReadonlyGraph(EcsGraph source) { _source = source; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
@ -67,7 +67,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
|
|
||||||
#region Internal
|
#region Internal
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal EcsJoin GetSource_Internal() => _source;
|
internal EcsGraph GetSource_Internal() => _source;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other
|
#region Other
|
||||||
@ -86,20 +86,20 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
//[DebuggerTypeProxy(typeof(DebuggerProxy))]
|
//[DebuggerTypeProxy(typeof(DebuggerProxy))]
|
||||||
public class EcsJoin
|
public class EcsGraph
|
||||||
{
|
{
|
||||||
private readonly EcsArc _source;
|
private readonly EcsArc _source;
|
||||||
private readonly bool _isLoop;
|
private readonly bool _isLoop;
|
||||||
|
|
||||||
private readonly BasketList _startBaskets;
|
private readonly BasketList _startBaskets;
|
||||||
private readonly BasketList _endBaskets;
|
private readonly BasketList _endBaskets;
|
||||||
private readonly RelNodesInfo[] _relNodesMapping;
|
private RelNodesInfo[] _relNodesMapping;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public EcsReadonlyJoin Readonly
|
public EcsReadonlyGraph Readonly
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return new EcsReadonlyJoin(this); }
|
get { return new EcsReadonlyGraph(this); }
|
||||||
}
|
}
|
||||||
public EcsArc Arc
|
public EcsArc Arc
|
||||||
{
|
{
|
||||||
@ -140,20 +140,12 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
public EcsJoin(EcsArc arc)
|
public EcsGraph(EcsArc arc)
|
||||||
{
|
{
|
||||||
_source = arc;
|
_source = arc;
|
||||||
_isLoop = arc.IsLoop;
|
_isLoop = arc.IsLoop;
|
||||||
|
|
||||||
_startBaskets = new BasketList();
|
_startBaskets = new BasketList();
|
||||||
//if (_isLoop)
|
|
||||||
//{
|
|
||||||
// _endBaskets = _startBaskets;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// _endBaskets = new BasketList();
|
|
||||||
//}
|
|
||||||
_endBaskets = new BasketList();
|
_endBaskets = new BasketList();
|
||||||
|
|
||||||
_relNodesMapping = new RelNodesInfo[arc.ArcWorld.Capacity];
|
_relNodesMapping = new RelNodesInfo[arc.ArcWorld.Capacity];
|
||||||
@ -167,14 +159,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
ref RelNodesInfo arcInfo = ref _relNodesMapping[relEntityID];
|
ref RelNodesInfo arcInfo = ref _relNodesMapping[relEntityID];
|
||||||
|
|
||||||
arcInfo.startNodeIndex = _startBaskets.AddToBasket(startEntityID, relEntityID);
|
arcInfo.startNodeIndex = _startBaskets.AddToBasket(startEntityID, relEntityID);
|
||||||
//if (_isLoop)
|
|
||||||
//{
|
|
||||||
// arcInfo.endNodeIndex = arcInfo.startNodeIndex;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID);
|
arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID);
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
public void Del(int relEntityID)
|
public void Del(int relEntityID)
|
||||||
{
|
{
|
||||||
@ -214,59 +199,21 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
|
|
||||||
foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID))
|
foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID))
|
||||||
{
|
{
|
||||||
//int endEntityID = _source.GetRelEnd(relEntityID);
|
arc.ArcWorld.TryDelEntity(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);
|
|
||||||
//}
|
|
||||||
|
|
||||||
arc.ArcWorld.DelEntity(relEntityID);
|
|
||||||
//if (_isLoop)
|
|
||||||
//{
|
|
||||||
// int endNodeIndex = _relNodesMapping[relEntityID].endNodeIndex;
|
|
||||||
// int revereceRelEntitiy = _endBaskets.Get(endNodeIndex);
|
|
||||||
// arc.ArcWorld.DelEntity(revereceRelEntitiy);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
//_startBaskets.RemoveBasket(startEntityID);
|
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void DelEndAndDelRelEntities(int endEntityID, EcsArc arc)
|
private void DelEndAndDelRelEntities(int endEntityID, EcsArc arc)
|
||||||
{
|
{
|
||||||
foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID))
|
foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID))
|
||||||
{
|
{
|
||||||
//int startEntityID = _source.GetRelStart(relEntityID);
|
arc.ArcWorld.TryDelEntity(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);
|
|
||||||
//}
|
|
||||||
|
|
||||||
arc.ArcWorld.DelEntity(relEntityID);
|
|
||||||
//if (_isLoop)
|
|
||||||
//{
|
|
||||||
// int startNodeIndex = _relNodesMapping[relEntityID].startNodeIndex;
|
|
||||||
// int revereceRelEntitiy = _startBaskets.Get(startNodeIndex);
|
|
||||||
// arc.ArcWorld.DelEntity(revereceRelEntitiy);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
//_endBaskets.RemoveBasket(endEntityID);
|
|
||||||
}
|
}
|
||||||
public struct FriendEcsArc
|
public struct FriendEcsArc
|
||||||
{
|
{
|
||||||
private EcsJoin _join;
|
private EcsGraph _join;
|
||||||
public FriendEcsArc(EcsArc arc, EcsJoin join)
|
public FriendEcsArc(EcsArc arc, EcsGraph join)
|
||||||
{
|
{
|
||||||
if (arc.IsInit_Internal != false)
|
if (arc.IsInit_Internal != false)
|
||||||
{
|
{
|
||||||
@ -403,7 +350,22 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
|
|
||||||
#region Operators
|
#region Operators
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static implicit operator EcsReadonlyJoin(EcsJoin a) => a.Readonly;
|
public static implicit operator EcsReadonlyGraph(EcsGraph a) => a.Readonly;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UpSize
|
||||||
|
public void UpArcSize(int minSize)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _relNodesMapping, minSize);
|
||||||
|
}
|
||||||
|
public void UpStartSize(int minSize)
|
||||||
|
{
|
||||||
|
_startBaskets.UpBasketsSize(minSize);
|
||||||
|
}
|
||||||
|
public void UpEndSize(int minSize)
|
||||||
|
{
|
||||||
|
_endBaskets.UpBasketsSize(minSize);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region DebuggerProxy
|
#region DebuggerProxy
|
@ -1,6 +1,5 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Internal;
|
using DCFApixels.DragonECS.Relations.Internal;
|
||||||
using DCFApixels.DragonECS.Relations.Utils;
|
using DCFApixels.DragonECS.Relations.Utils;
|
||||||
using Leopotam.EcsLite;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@ -23,8 +22,8 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
||||||
|
|
||||||
private EcsJoin _joinEntities;
|
private EcsGraph _entitiesGraph;
|
||||||
private EcsJoin.FriendEcsArc _joinEntitiesFriend;
|
private EcsGraph.FriendEcsArc _entitiesGraphFriend;
|
||||||
|
|
||||||
private EcsGroup _relEntities;
|
private EcsGroup _relEntities;
|
||||||
private RelEntityInfo[] _relEntityInfos; //N * (N - 1) / 2
|
private RelEntityInfo[] _relEntityInfos; //N * (N - 1) / 2
|
||||||
@ -63,10 +62,10 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _relEntities.Readonly; }
|
get { return _relEntities.Readonly; }
|
||||||
}
|
}
|
||||||
public EcsReadonlyJoin JoinEntities
|
public EcsReadonlyGraph EntitiesGraph
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _joinEntities.Readonly; }
|
get { return _entitiesGraph.Readonly; }
|
||||||
}
|
}
|
||||||
public bool IsLoop
|
public bool IsLoop
|
||||||
{
|
{
|
||||||
@ -86,8 +85,13 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
_relEntityInfos = new RelEntityInfo[arcWorld.Capacity];
|
_relEntityInfos = new RelEntityInfo[arcWorld.Capacity];
|
||||||
|
|
||||||
_arcWorldHandler = new ArcWorldHandler(this);
|
|
||||||
|
|
||||||
|
_relEntities = EcsGroup.New(_arcWorld);
|
||||||
|
_entitiesGraph = new EcsGraph(this);
|
||||||
|
|
||||||
|
_entitiesGraphFriend = new EcsGraph.FriendEcsArc(this, _entitiesGraph);
|
||||||
|
|
||||||
|
_arcWorldHandler = new ArcWorldHandler(this);
|
||||||
if (_isLoop)
|
if (_isLoop)
|
||||||
{
|
{
|
||||||
_loopWorldHandler = new LoopWorldHandler(this);
|
_loopWorldHandler = new LoopWorldHandler(this);
|
||||||
@ -98,11 +102,6 @@ namespace DCFApixels.DragonECS
|
|||||||
_endWorldHandler = new EndWorldHandler(this);
|
_endWorldHandler = new EndWorldHandler(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_relEntities = EcsGroup.New(_arcWorld);
|
|
||||||
_joinEntities = new EcsJoin(this);
|
|
||||||
|
|
||||||
_joinEntitiesFriend = new EcsJoin.FriendEcsArc(this, _joinEntities);
|
|
||||||
_isInit = true;
|
_isInit = true;
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
@ -126,7 +125,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
if (HasRelation(startEntityID, endEntityID))
|
if (HasRelation(startEntityID, endEntityID))
|
||||||
{
|
{
|
||||||
Throw.UndefinedRelationException();
|
Throw.RelationAlreadyExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
int relEntity = _arcWorld.NewEntity();
|
int relEntity = _arcWorld.NewEntity();
|
||||||
@ -134,7 +133,7 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
_relEntityInfos[relEntity] = new RelEntityInfo(startEntityID, endEntityID);
|
_relEntityInfos[relEntity] = new RelEntityInfo(startEntityID, endEntityID);
|
||||||
_relEntities.Add(relEntity);
|
_relEntities.Add(relEntity);
|
||||||
_joinEntities.Add(relEntity);
|
_entitiesGraph.Add(relEntity);
|
||||||
return relEntity;
|
return relEntity;
|
||||||
}
|
}
|
||||||
public void DelRelation(int startEntityID, int endEntityID)
|
public void DelRelation(int startEntityID, int endEntityID)
|
||||||
@ -147,17 +146,6 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
Throw.UndefinedRelationException();
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearRelation_Internal(int startEntityID, int endEntityID)
|
private void ClearRelation_Internal(int startEntityID, int endEntityID)
|
||||||
@ -165,7 +153,7 @@ namespace DCFApixels.DragonECS
|
|||||||
if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity))
|
if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity))
|
||||||
{
|
{
|
||||||
_relEntities.Remove(relEntity);
|
_relEntities.Remove(relEntity);
|
||||||
_joinEntities.Del(relEntity);
|
_entitiesGraph.Del(relEntity);
|
||||||
_relationsMatrix.Remove(startEntityID, endEntityID);
|
_relationsMatrix.Remove(startEntityID, endEntityID);
|
||||||
_relEntityInfos[relEntity] = RelEntityInfo.Empty;
|
_relEntityInfos[relEntity] = RelEntityInfo.Empty;
|
||||||
}
|
}
|
||||||
@ -273,6 +261,7 @@ namespace DCFApixels.DragonECS
|
|||||||
public void OnWorldResize(int arcWorldNewSize)
|
public void OnWorldResize(int arcWorldNewSize)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _arc._relEntityInfos, arcWorldNewSize);
|
Array.Resize(ref _arc._relEntityInfos, arcWorldNewSize);
|
||||||
|
_arc._entitiesGraph.UpArcSize(arcWorldNewSize);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@ -283,6 +272,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.StartWorld.AddListener(this);
|
_arc.StartWorld.AddListener(this);
|
||||||
|
OnWorldResize(_arc.StartWorld.Capacity);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
@ -293,12 +283,15 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
foreach (var startEntityID in startEntityBuffer)
|
foreach (var startEntityID in startEntityBuffer)
|
||||||
{
|
{
|
||||||
_arc._joinEntitiesFriend.DelStartAndDelRelEntities(startEntityID, _arc);
|
_arc._entitiesGraphFriend.DelStartAndDelRelEntities(startEntityID, _arc);
|
||||||
}
|
}
|
||||||
_arc._arcWorld.ReleaseDelEntityBuffer(startEntityBuffer.Length);
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int startWorldNewSize) { }
|
public void OnWorldResize(int startWorldNewSize)
|
||||||
|
{
|
||||||
|
_arc._entitiesGraph.UpStartSize(startWorldNewSize);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
private class EndWorldHandler : IEcsWorldEventListener
|
private class EndWorldHandler : IEcsWorldEventListener
|
||||||
@ -308,6 +301,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.EndWorld.AddListener(this);
|
_arc.EndWorld.AddListener(this);
|
||||||
|
OnWorldResize(_arc.EndWorld.Capacity);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
@ -318,12 +312,15 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
foreach (var endEntityID in endEntityBuffer)
|
foreach (var endEntityID in endEntityBuffer)
|
||||||
{
|
{
|
||||||
_arc._joinEntitiesFriend.DelEndAndDelRelEntities(endEntityID, _arc);
|
_arc._entitiesGraphFriend.DelEndAndDelRelEntities(endEntityID, _arc);
|
||||||
}
|
}
|
||||||
_arc._arcWorld.ReleaseDelEntityBuffer(endEntityBuffer.Length);
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int endWorldNewSize) { }
|
public void OnWorldResize(int endWorldNewSize)
|
||||||
|
{
|
||||||
|
_arc._entitiesGraph.UpEndSize(endWorldNewSize);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
private class LoopWorldHandler : IEcsWorldEventListener
|
private class LoopWorldHandler : IEcsWorldEventListener
|
||||||
@ -333,6 +330,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.StartWorld.AddListener(this);
|
_arc.StartWorld.AddListener(this);
|
||||||
|
OnWorldResize(_arc.StartWorld.Capacity);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
@ -343,13 +341,17 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
foreach (var startEntityID in startEntityBuffer)
|
foreach (var startEntityID in startEntityBuffer)
|
||||||
{
|
{
|
||||||
_arc._joinEntitiesFriend.DelStartAndDelRelEntities(startEntityID, _arc);
|
_arc._entitiesGraphFriend.DelStartAndDelRelEntities(startEntityID, _arc);
|
||||||
_arc._joinEntitiesFriend.DelEndAndDelRelEntities(startEntityID, _arc);
|
_arc._entitiesGraphFriend.DelEndAndDelRelEntities(startEntityID, _arc);
|
||||||
}
|
}
|
||||||
_arc._arcWorld.ReleaseDelEntityBuffer(startEntityBuffer.Length);
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int startWorldNewSize) { }
|
public void OnWorldResize(int startWorldNewSize)
|
||||||
|
{
|
||||||
|
_arc._entitiesGraph.UpStartSize(startWorldNewSize);
|
||||||
|
_arc._entitiesGraph.UpEndSize(startWorldNewSize);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
10
src/EcsWorldConfig.cs
Normal file
10
src/EcsWorldConfig.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public static class EcsWorldConfigRelationsExtensions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
public static class EcsWorldGraph
|
public static class EcsWorldGraph
|
||||||
{
|
{
|
||||||
private static readonly SparseArray64<EcsArc> _matrix = new SparseArray64<EcsArc>(4);
|
private static readonly SparseArray<EcsArc> _matrix = new SparseArray<EcsArc>(4);
|
||||||
private static EcsArc[] _arcsMapping = new EcsArc[4];
|
private static EcsArc[] _arcsMapping = new EcsArc[4];
|
||||||
|
|
||||||
#region Register/Unregister
|
#region Register/Unregister
|
||||||
@ -103,7 +103,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self, out EcsLoopArcWorld<TWorld> arcWorld)
|
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self, out EcsLoopArcWorld<TWorld> arcWorld, IEcsWorldConfig config = null)
|
||||||
where TWorld : EcsWorld
|
where TWorld : EcsWorld
|
||||||
{
|
{
|
||||||
if (self == null)
|
if (self == null)
|
||||||
@ -114,10 +114,10 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
EcsDebug.PrintWarning($"{nameof(TWorld)} is not {self.GetType().Name}");
|
EcsDebug.PrintWarning($"{nameof(TWorld)} is not {self.GetType().Name}");
|
||||||
}
|
}
|
||||||
arcWorld = new EcsLoopArcWorld<TWorld>();
|
arcWorld = new EcsLoopArcWorld<TWorld>(config);
|
||||||
return Register(self, self, arcWorld);
|
return Register(self, self, arcWorld);
|
||||||
}
|
}
|
||||||
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end, out EcsArcWorld<TStartWorld, TEndWorld> arcWorld)
|
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end, out EcsArcWorld<TStartWorld, TEndWorld> arcWorld, IEcsWorldConfig config = null)
|
||||||
where TStartWorld : EcsWorld
|
where TStartWorld : EcsWorld
|
||||||
where TEndWorld : EcsWorld
|
where TEndWorld : EcsWorld
|
||||||
{
|
{
|
||||||
@ -129,19 +129,19 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
EcsDebug.PrintWarning($"{nameof(TStartWorld)} is not {start.GetType().Name} or {nameof(TEndWorld)} is not {end.GetType().Name}");
|
EcsDebug.PrintWarning($"{nameof(TStartWorld)} is not {start.GetType().Name} or {nameof(TEndWorld)} is not {end.GetType().Name}");
|
||||||
}
|
}
|
||||||
arcWorld = new EcsArcWorld<TStartWorld, TEndWorld>();
|
arcWorld = new EcsArcWorld<TStartWorld, TEndWorld>(config);
|
||||||
return Register(start, end, arcWorld);
|
return Register(start, end, arcWorld);
|
||||||
}
|
}
|
||||||
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self)
|
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self, IEcsWorldConfig config = null)
|
||||||
where TWorld : EcsWorld
|
where TWorld : EcsWorld
|
||||||
{
|
{
|
||||||
return SetLoopArcAuto(self, out _);
|
return SetLoopArcAuto(self, out _, config);
|
||||||
}
|
}
|
||||||
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end)
|
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end, IEcsWorldConfig config = null)
|
||||||
where TStartWorld : EcsWorld
|
where TStartWorld : EcsWorld
|
||||||
where TEndWorld : EcsWorld
|
where TEndWorld : EcsWorld
|
||||||
{
|
{
|
||||||
return SetArcAuto(start, end, out _);
|
return SetArcAuto(start, end, out _, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1,15 +1,185 @@
|
|||||||
namespace DCFApixels.DragonECS.Relations.Utils
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Relations.Internal
|
||||||
{
|
{
|
||||||
internal static class ArrayUtility
|
internal static class ArrayUtility
|
||||||
{
|
{
|
||||||
|
private static int GetHighBitNumber(uint bits)
|
||||||
|
{
|
||||||
|
if (bits == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int bit = 0;
|
||||||
|
if ((bits & 0xFFFF0000) != 0)
|
||||||
|
{
|
||||||
|
bits >>= 16;
|
||||||
|
bit |= 16;
|
||||||
|
}
|
||||||
|
if ((bits & 0xFF00) != 0)
|
||||||
|
{
|
||||||
|
bits >>= 8;
|
||||||
|
bit |= 8;
|
||||||
|
}
|
||||||
|
if ((bits & 0xF0) != 0)
|
||||||
|
{
|
||||||
|
bits >>= 4;
|
||||||
|
bit |= 4;
|
||||||
|
}
|
||||||
|
if ((bits & 0xC) != 0)
|
||||||
|
{
|
||||||
|
bits >>= 2;
|
||||||
|
bit |= 2;
|
||||||
|
}
|
||||||
|
if ((bits & 0x2) != 0)
|
||||||
|
{
|
||||||
|
bit |= 1;
|
||||||
|
}
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
public static int NormalizeSizeToPowerOfTwo(int minSize)
|
||||||
|
{
|
||||||
|
return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1);
|
||||||
|
}
|
||||||
public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1)
|
public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1)
|
||||||
{
|
{
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
|
{
|
||||||
length = array.Length;
|
length = array.Length;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
length = startIndex + length;
|
length = startIndex + length;
|
||||||
|
}
|
||||||
for (int i = startIndex; i < length; i++)
|
for (int i = startIndex; i < length; i++)
|
||||||
|
{
|
||||||
array[i] = value;
|
array[i] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal readonly struct EnumerableInt : IEnumerable<int>
|
||||||
|
{
|
||||||
|
public readonly int start;
|
||||||
|
public readonly int length;
|
||||||
|
private EnumerableInt(int start, int length)
|
||||||
|
{
|
||||||
|
this.start = start;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
public static EnumerableInt Range(int start, int length) => new EnumerableInt(start, length);
|
||||||
|
public static EnumerableInt StartEnd(int start, int end) => new EnumerableInt(start, end - start);
|
||||||
|
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Enumerator GetEnumerator() => new Enumerator(start, start + length);
|
||||||
|
public struct Enumerator : IEnumerator<int>
|
||||||
|
{
|
||||||
|
private readonly int _max;
|
||||||
|
private int _current;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Enumerator(int max, int current)
|
||||||
|
{
|
||||||
|
_max = max;
|
||||||
|
_current = current - 1;
|
||||||
|
}
|
||||||
|
public int Current
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _current;
|
||||||
|
}
|
||||||
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool MoveNext() => ++_current < _max;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Reset() { }
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal static unsafe class UnmanagedArrayUtility
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static T* New<T>(int capacity) where T : unmanaged
|
||||||
|
{
|
||||||
|
return (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void New<T>(out T* ptr, int capacity) where T : unmanaged
|
||||||
|
{
|
||||||
|
ptr = (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>(default) * capacity).ToPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static T* NewAndInit<T>(int capacity) where T : unmanaged
|
||||||
|
{
|
||||||
|
int newSize = Marshal.SizeOf(typeof(T)) * capacity;
|
||||||
|
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
||||||
|
|
||||||
|
for (int i = 0; i < newSize; i++)
|
||||||
|
*(newPointer + i) = 0;
|
||||||
|
|
||||||
|
return (T*)newPointer;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void NewAndInit<T>(out T* ptr, int capacity) where T : unmanaged
|
||||||
|
{
|
||||||
|
int newSize = Marshal.SizeOf(typeof(T)) * capacity;
|
||||||
|
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
||||||
|
|
||||||
|
for (int i = 0; i < newSize; i++)
|
||||||
|
*(newPointer + i) = 0;
|
||||||
|
|
||||||
|
ptr = (T*)newPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Free(void* pointer)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(new IntPtr(pointer));
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Free<T>(ref T* pointer, ref int length) where T : unmanaged
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(new IntPtr(pointer));
|
||||||
|
pointer = null;
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static T* Clone<T>(T* sourcePtr, int length) where T : unmanaged
|
||||||
|
{
|
||||||
|
T* clone = New<T>(length);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
clone[i] = sourcePtr[i];
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static T* Resize<T>(void* oldPointer, int newCount) where T : unmanaged
|
||||||
|
{
|
||||||
|
return (T*)(Marshal.ReAllocHGlobal(
|
||||||
|
new IntPtr(oldPointer),
|
||||||
|
new IntPtr(Marshal.SizeOf<T>(default) * newCount))).ToPointer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CollectionUtility
|
||||||
|
{
|
||||||
|
public static string EntitiesToString(IEnumerable<int> range, string name)
|
||||||
|
{
|
||||||
|
return $"{name}({range.Count()}) {{{string.Join(", ", range.OrderBy(o => o))}}})";
|
||||||
|
}
|
||||||
|
public static string AutoToString<T>(IEnumerable<T> range, string name)
|
||||||
|
{
|
||||||
|
return $"{name}({range.Count()}) {{{string.Join(", ", range.Select(o => o.ToString()))}}})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,7 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Internal;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
@ -192,11 +190,14 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private void UpBasketsSize(int minSize)
|
public void UpBasketsSize(int minSize)
|
||||||
{
|
{
|
||||||
int newSize = GetHighBitNumber((uint)minSize) << 1;
|
if (minSize > _baskets.Length)
|
||||||
|
{
|
||||||
|
int newSize = 1 << (GetHighBitNumber((uint)minSize - 1) + 1);
|
||||||
Array.Resize(ref _baskets, newSize);
|
Array.Resize(ref _baskets, newSize);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private static int GetHighBitNumber(uint bits)
|
private static int GetHighBitNumber(uint bits)
|
||||||
{
|
{
|
||||||
if (bits == 0)
|
if (bits == 0)
|
||||||
@ -271,10 +272,6 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public BasketIterator GetBasketIterator(int basketIndex)
|
public BasketIterator GetBasketIterator(int basketIndex)
|
||||||
{
|
{
|
||||||
if (_baskets.Length <= basketIndex)
|
|
||||||
{
|
|
||||||
UpBasketsSize(basketIndex);
|
|
||||||
}
|
|
||||||
return new BasketIterator(this, basketIndex);
|
return new BasketIterator(this, basketIndex);
|
||||||
}
|
}
|
||||||
public readonly struct BasketIterator : IEnumerable<int>
|
public readonly struct BasketIterator : IEnumerable<int>
|
||||||
|
@ -26,6 +26,11 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
{
|
{
|
||||||
throw new EcsRelationException();
|
throw new EcsRelationException();
|
||||||
}
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
internal static void RelationAlreadyExists()
|
||||||
|
{
|
||||||
|
throw new EcsRelationException("This relation already exists.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//SparseArray64. Analogous to Dictionary<long, T>, but faster.
|
//SparseArray64. Analogous to Dictionary<long, T>, but faster.
|
||||||
//Benchmark result of indexer.get speed test with 300 elements:
|
//Benchmark result of indexer.get speed test with 300 elements:
|
||||||
//[Dictinary: 6.705us] [SparseArray64: 2.512us].
|
//[Dictinary: 6.705us] [SparseArray64: 2.512us].
|
||||||
|
using DCFApixels.DragonECS.Relations.Internal;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
@ -9,14 +10,15 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Utils
|
namespace DCFApixels.DragonECS.Relations.Utils
|
||||||
{
|
{
|
||||||
internal class SparseArray64<TValue>
|
internal unsafe class SparseArray64<TValue>
|
||||||
|
where TValue : unmanaged
|
||||||
{
|
{
|
||||||
public const int MIN_CAPACITY_BITS_OFFSET = 4;
|
public const int MIN_CAPACITY_BITS_OFFSET = 4;
|
||||||
public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET;
|
public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET;
|
||||||
private const int EMPTY = -1;
|
private const int EMPTY = -1;
|
||||||
|
|
||||||
private int[] _buckets = Array.Empty<int>();
|
private UnsafeArray<int> _buckets;
|
||||||
private Entry[] _entries = Array.Empty<Entry>();
|
private UnsafeArray<Entry> _entries;
|
||||||
|
|
||||||
private int _count;
|
private int _count;
|
||||||
|
|
||||||
@ -28,26 +30,45 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
#region Properties
|
#region Properties
|
||||||
public TValue this[long keyX, long keyY]
|
public TValue this[long keyX, long keyY]
|
||||||
{
|
{
|
||||||
get => _entries[FindEntry(keyX + (keyY << 32))].value;
|
get
|
||||||
set => Insert(keyX + (keyY << 32), value);
|
{
|
||||||
|
//TODO Проверить необходимость проверки на Null
|
||||||
|
return _entries.ptr[FindEntry(keyX + (keyY << 32))].value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Insert(keyX + (keyY << 32), value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public TValue this[long key]
|
public TValue this[long key]
|
||||||
{
|
{
|
||||||
get => _entries[FindEntry(key)].value;
|
get
|
||||||
set => Insert(key, value);
|
{
|
||||||
|
//TODO Проверить необходимость проверки на Null
|
||||||
|
return _entries.ptr[FindEntry(key)].value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Insert(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count => _count;
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _count; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
public SparseArray64(int minCapacity = MIN_CAPACITY)
|
public SparseArray64(int minCapacity = MIN_CAPACITY)
|
||||||
{
|
{
|
||||||
minCapacity = NormalizeCapacity(minCapacity);
|
minCapacity = NormalizeCapacity(minCapacity);
|
||||||
_buckets = new int[minCapacity];
|
_buckets = new UnsafeArray<int>(minCapacity);
|
||||||
for (int i = 0; i < minCapacity; i++)
|
for (int i = 0; i < minCapacity; i++)
|
||||||
|
{
|
||||||
_buckets[i] = EMPTY;
|
_buckets[i] = EMPTY;
|
||||||
_entries = new Entry[minCapacity];
|
}
|
||||||
|
_entries = new UnsafeArray<Entry>(minCapacity);
|
||||||
_modBitMask = (minCapacity - 1) & 0x7FFFFFFF;
|
_modBitMask = (minCapacity - 1) & 0x7FFFFFFF;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -148,7 +169,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
value = default;
|
value = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
value = _entries[index].value;
|
value = _entries.ptr[index].value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public bool TryGetValue(long keyX, long keyY, out TValue value)
|
public bool TryGetValue(long keyX, long keyY, out TValue value)
|
||||||
@ -159,7 +180,7 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
value = default;
|
value = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
value = _entries[index].value;
|
value = _entries.ptr[index].value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -184,7 +205,10 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
{
|
{
|
||||||
_buckets[i] = -1;
|
_buckets[i] = -1;
|
||||||
}
|
}
|
||||||
Array.Clear(_entries, 0, _count);
|
for (int i = 0; i < _count; i++)
|
||||||
|
{
|
||||||
|
_entries[i] = default;
|
||||||
|
}
|
||||||
_count = 0;
|
_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,12 +221,15 @@ namespace DCFApixels.DragonECS.Relations.Utils
|
|||||||
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
||||||
|
|
||||||
Contract.Assert(newSize >= _entries.Length);
|
Contract.Assert(newSize >= _entries.Length);
|
||||||
int[] newBuckets = new int[newSize];
|
UnsafeArray<int> newBuckets = new UnsafeArray<int>(newSize);
|
||||||
for (int i = 0; i < newBuckets.Length; i++)
|
for (int i = 0; i < newBuckets.Length; i++)
|
||||||
newBuckets[i] = EMPTY;
|
newBuckets[i] = EMPTY;
|
||||||
|
|
||||||
Entry[] newEntries = new Entry[newSize];
|
UnsafeArray<Entry> newEntries = UnsafeArray<Entry>.Resize(_entries, newSize);
|
||||||
Array.Copy(_entries, 0, newEntries, 0, _count);
|
//UnsafeArray<Entry> newEntries = new UnsafeArray<Entry>(newSize);
|
||||||
|
//Array.Copy(_entries, 0, newEntries, 0, _count);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < _count; i++)
|
for (int i = 0; i < _count; i++)
|
||||||
{
|
{
|
||||||
if (newEntries[i].hashKey >= 0)
|
if (newEntries[i].hashKey >= 0)
|
||||||
|
119
src/Utils/UnsafeArray.cs
Normal file
119
src/Utils/UnsafeArray.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
using DCFApixels.DragonECS.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Relations.Internal
|
||||||
|
{
|
||||||
|
[DebuggerTypeProxy(typeof(UnsafeArray<>.DebuggerProxy))]
|
||||||
|
internal unsafe struct UnsafeArray<T> : IDisposable, IEnumerable<T>
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
internal T* ptr;
|
||||||
|
internal int Length;
|
||||||
|
|
||||||
|
public ref T this[int index]
|
||||||
|
{
|
||||||
|
get { return ref ptr[index]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public UnsafeArray(int length)
|
||||||
|
{
|
||||||
|
UnmanagedArrayUtility.New(out ptr, length);
|
||||||
|
Length = length;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public UnsafeArray(int length, bool isInit)
|
||||||
|
{
|
||||||
|
UnmanagedArrayUtility.NewAndInit(out ptr, length);
|
||||||
|
Length = length;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private UnsafeArray(T* ptr, int length)
|
||||||
|
{
|
||||||
|
this.ptr = ptr;
|
||||||
|
Length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public UnsafeArray<T> Clone()
|
||||||
|
{
|
||||||
|
return new UnsafeArray<T>(UnmanagedArrayUtility.Clone(ptr, Length), Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
UnmanagedArrayUtility.Free(ref ptr, ref Length);
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
T* ptr = this.ptr;
|
||||||
|
return CollectionUtility.AutoToString(EnumerableInt.Range(0, Length).Select(i => ptr[i]), "ua");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Resize(ref UnsafeArray<T> array, int newSize)
|
||||||
|
{
|
||||||
|
array.ptr = UnmanagedArrayUtility.Resize<T>(array.ptr, newSize);
|
||||||
|
array.Length = newSize;
|
||||||
|
}
|
||||||
|
public static UnsafeArray<T> Resize(UnsafeArray<T> array, int newSize)
|
||||||
|
{
|
||||||
|
return new UnsafeArray<T>(UnmanagedArrayUtility.Resize<T>(array.ptr, newSize), newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Enumerator GetEnumerator() => new Enumerator(ptr, Length);
|
||||||
|
public struct Enumerator : IEnumerator<T>
|
||||||
|
{
|
||||||
|
private readonly T* _ptr;
|
||||||
|
private readonly int _length;
|
||||||
|
private int _index;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Enumerator(T* ptr, int length)
|
||||||
|
{
|
||||||
|
_ptr = ptr;
|
||||||
|
_length = length;
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
public T Current
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _ptr[_index];
|
||||||
|
}
|
||||||
|
object IEnumerator.Current => Current;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool MoveNext() => ++_index < _length;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Reset() { }
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DebuggerProxy
|
||||||
|
{
|
||||||
|
public T[] elements;
|
||||||
|
public int length;
|
||||||
|
public DebuggerProxy(UnsafeArray<T> instance)
|
||||||
|
{
|
||||||
|
elements = EnumerableInt.Range(0, instance.Length).Select(i => instance.ptr[i]).ToArray();
|
||||||
|
length = instance.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class UnsafeArrayExtentions
|
||||||
|
{
|
||||||
|
public static void Resize<T>(ref UnsafeArray<T> self, int newSize)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
UnsafeArray<T>.Resize(ref self, newSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user