DragonECS-Graphs/src/EcsEdge.cs

186 lines
8.2 KiB
C#
Raw Normal View History

2023-06-22 11:01:43 +08:00
using DCFApixels.DragonECS.Relations.Utils;
using System;
2023-06-22 03:54:20 +08:00
using System.Runtime.CompilerServices;
2023-06-19 01:36:36 +08:00
2023-06-22 11:01:43 +08:00
namespace DCFApixels.DragonECS
2023-06-19 01:36:36 +08:00
{
2023-06-29 14:25:51 +08:00
//Edge world
2023-06-22 03:54:20 +08:00
//Relation entity
//Relation
//Relation component
2023-06-29 14:25:51 +08:00
public class EcsEdge : IEcsWorldEventListener, IEcsEntityEventListener
2023-06-19 01:36:36 +08:00
{
2023-06-29 14:25:51 +08:00
private readonly EcsWorld _world;
private readonly EcsWorld _otherWorld;
private readonly EcsEdgeWorld _edgeWorld;
2023-06-19 01:36:36 +08:00
2023-06-23 01:49:13 +08:00
private readonly IdsBasket _basket = new IdsBasket(256);
private readonly IdsBasket _otherBasket = new IdsBasket(256);
2023-06-29 14:25:51 +08:00
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
2023-06-22 03:54:20 +08:00
2023-06-23 01:49:13 +08:00
public readonly ForwardOrientation Forward;
public readonly ReverseOrientation Reverse;
2023-06-19 01:36:36 +08:00
2023-06-22 03:54:20 +08:00
private RelationTargets[] _relationTargets;
public EcsWorld World => _world;
public EcsWorld OtherWorld => _otherWorld;
2023-06-29 14:25:51 +08:00
public EcsEdgeWorld EdgeWorld => _edgeWorld;
2023-06-19 01:36:36 +08:00
public bool IsSolo => _world == _otherWorld;
2023-06-29 14:25:51 +08:00
internal EcsEdge(EcsWorld world, EcsWorld otherWorld, EcsEdgeWorld relationWorld)
2023-06-19 01:36:36 +08:00
{
2023-06-29 14:25:51 +08:00
_edgeWorld = relationWorld;
2023-06-19 01:36:36 +08:00
_world = world;
_otherWorld = otherWorld;
2023-06-22 03:54:20 +08:00
_relationTargets = new RelationTargets[relationWorld.Capacity];
2023-06-29 14:25:51 +08:00
_edgeWorld.AddListener(worldEventListener: this);
_edgeWorld.AddListener(entityEventListener: this);
2023-06-22 03:54:20 +08:00
2023-06-23 01:49:13 +08:00
Forward = new ForwardOrientation(this);
Reverse = new ReverseOrientation(this);
2023-06-19 01:36:36 +08:00
}
2023-06-22 03:54:20 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref readonly RelationTargets GetRelationTargets(int relationEntityID)
2023-06-19 01:36:36 +08:00
{
2023-06-22 03:54:20 +08:00
return ref _relationTargets[relationEntityID];
2023-06-19 01:36:36 +08:00
}
2023-06-23 01:49:13 +08:00
#region Methods
#region New/Del
private int NewRelation(int entityID, int otherEntityID)
{
if (HasRelation(entityID, otherEntityID))
throw new EcsRelationException();
2023-06-29 14:25:51 +08:00
int e = _edgeWorld.NewEmptyEntity();
2023-06-23 01:49:13 +08:00
_basket.AddToHead(entityID, otherEntityID);
_otherBasket.AddToHead(otherEntityID, entityID);
_relationsMatrix.Add(entityID, otherEntityID, e);
_relationTargets[e] = new RelationTargets(entityID, otherEntityID);
return e;
}
2023-06-29 14:25:51 +08:00
private void BindRelation(int relationEntityID, int entityID, int otherEntityID)
{
ref var rel = ref _relationTargets[relationEntityID];
if (HasRelation(entityID, otherEntityID) || rel.IsEmpty)
throw new EcsRelationException();
_basket.AddToHead(entityID, otherEntityID);
_otherBasket.AddToHead(otherEntityID, entityID);
_relationsMatrix.Add(entityID, otherEntityID, relationEntityID);
rel = new RelationTargets(entityID, otherEntityID);
}
2023-06-23 01:49:13 +08:00
private void DelRelation(int entityID, int otherEntityID)
{
if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e))
throw new EcsRelationException();
_relationsMatrix.Remove(entityID, otherEntityID);
_basket.DelHead(entityID);
_otherBasket.Del(entityID);
2023-06-29 14:25:51 +08:00
_edgeWorld.DelEntity(e);
2023-06-23 01:49:13 +08:00
_relationTargets[e] = RelationTargets.Empty;
}
#endregion
#region Has
private bool HasRelation(int entityID, int otherEntityID) => _relationsMatrix.Contains(entityID, otherEntityID);
//public bool HasRelationWith(EcsSubject subject, int entityID, int otherEntityID)
//{
// if (subject.World != _relationWorld)
// throw new ArgumentException();
// return _source._relationsMatrix.TryGetValue(entityID, otherEntityID, out int entity) && subject.IsMatches(entity);
//}
#endregion
#region GetRelation
private int GetRelation(int entityID, int otherEntityID)
{
if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e))
throw new EcsRelationException();
return e;
}
private bool TryGetRelation(int entityID, int otherEntityID, out int entity)
{
return _relationsMatrix.TryGetValue(entityID, otherEntityID, out entity);
}
//public bool TryGetRelation(EcsSubject subject, int entityID, int otherEntityID, out int entity)
//{
// return _source._relationsMatrix.TryGetValue(entityID, otherEntityID, out entity) && subject.IsMatches(entity);
//}
#endregion
2023-06-29 14:25:51 +08:00
#region GetRelations
2023-06-23 01:49:13 +08:00
//#region GetRelations
//private IdsLinkedList.Span GetRelations(int entityID)
//{
// return _basket.GetSpanFor(entityID);
//}
////ReadOnlySpan<int> временная заглушка, потому тут будет спан из линкедлиста
////public ReadOnlySpan<int> GetRelationsWith(EcsSubject subject, int entityID)
////{
//// if (subject.World != _relationWorld)
//// throw new ArgumentException();
//// throw new NotImplementedException();
////}
//#endregion
2023-06-29 14:25:51 +08:00
#endregion
2023-06-23 01:49:13 +08:00
#endregion
2023-06-22 03:54:20 +08:00
#region Callbacks
void IEcsWorldEventListener.OnWorldResize(int newSize)
{
Array.Resize(ref _relationTargets, newSize);
}
2023-06-19 01:36:36 +08:00
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
void IEcsWorldEventListener.OnWorldDestroy() { }
void IEcsEntityEventListener.OnNewEntity(int entityID) { }
void IEcsEntityEventListener.OnDelEntity(int entityID)
{
2023-06-22 03:54:20 +08:00
ref RelationTargets rel = ref _relationTargets[entityID];
if (_relationsMatrix.Contains(rel.entity, rel.otherEntity))
Forward.DelRelation(rel.entity, rel.otherEntity);
}
#endregion
2023-06-19 01:36:36 +08:00
2023-06-22 03:54:20 +08:00
#region Orientation
2023-06-23 01:49:13 +08:00
public readonly struct ForwardOrientation
2023-06-22 03:54:20 +08:00
{
2023-06-29 14:25:51 +08:00
private readonly EcsEdge _source;
internal ForwardOrientation(EcsEdge source) => _source = source;
2023-06-23 01:49:13 +08:00
public int NewRelation(int entityID, int otherEntityID) => _source.NewRelation(entityID, otherEntityID);
2023-06-29 14:25:51 +08:00
public void BindRelation(int relationEntityID, int entityID, int otherEntityID) => _source.BindRelation(relationEntityID, entityID, otherEntityID);
2023-06-23 01:49:13 +08:00
public bool HasRelation(int entityID, int otherEntityID) => _source.HasRelation(entityID, otherEntityID);
public int GetRelation(int entityID, int otherEntityID) => _source.GetRelation(entityID, otherEntityID);
2023-06-29 14:25:51 +08:00
public void DelRelation(int entityID, int otherEntityID) => _source.DelRelation(entityID, otherEntityID);
2023-06-23 01:49:13 +08:00
public bool TryGetRelation(int entityID, int otherEntityID, out int relationEntityID) => _source.TryGetRelation(entityID, otherEntityID, out relationEntityID);
2023-06-23 01:52:51 +08:00
public IdsLinkedList.Span GetRelations(int entityID) => _source._basket.GetSpanFor(entityID);
2023-06-23 01:49:13 +08:00
}
public readonly struct ReverseOrientation
{
2023-06-29 14:25:51 +08:00
private readonly EcsEdge _source;
internal ReverseOrientation(EcsEdge source) => _source = source;
2023-06-23 01:49:13 +08:00
public int NewRelation(int otherEntityID, int entityID) => _source.NewRelation(entityID, otherEntityID);
2023-06-29 14:25:51 +08:00
public void BindRelation(int relationEntityID, int entityID, int otherEntityID) => _source.BindRelation(relationEntityID, otherEntityID, entityID);
2023-06-23 01:49:13 +08:00
public bool HasRelation(int otherEntityID, int entityID) => _source.HasRelation(entityID, otherEntityID);
public int GetRelation(int otherEntityID, int entityID) => _source.GetRelation(entityID, otherEntityID);
2023-06-29 14:25:51 +08:00
public void DelRelation(int otherEntityID, int entityID) => _source.DelRelation(entityID, otherEntityID);
2023-06-23 01:49:13 +08:00
public bool TryGetRelation(int otherEntityID, int entityID, out int relationEntityID) => _source.TryGetRelation(entityID, otherEntityID, out relationEntityID);
2023-06-23 01:52:51 +08:00
public IdsLinkedList.Span GetRelations(int otherEntityID) => _source._otherBasket.GetSpanFor(otherEntityID);
2023-06-19 01:36:36 +08:00
}
2023-06-22 09:10:51 +08:00
public struct RelationsSpan
{
private readonly IdsBasket _basket;
2023-06-22 14:30:10 +08:00
private readonly EcsAspect _aspect;
2023-06-22 09:10:51 +08:00
}
2023-06-22 03:54:20 +08:00
#endregion
2023-06-19 01:36:36 +08:00
}
}