relations can now contain data
parent
833c60003b
commit
5243259acb
|
@ -37,7 +37,7 @@ namespace MoonTools.ECS
|
|||
{
|
||||
// TODO: is it possible to optimize this?
|
||||
Register<TComponent>();
|
||||
return storages[typeof(TComponent)] as ComponentStorage<TComponent>;
|
||||
return (ComponentStorage<TComponent>) storages[typeof(TComponent)];
|
||||
}
|
||||
|
||||
public bool Some<TComponent>() where TComponent : struct
|
||||
|
|
|
@ -60,22 +60,22 @@ namespace MoonTools.ECS
|
|||
return EntityStorage.Exists(entity);
|
||||
}
|
||||
|
||||
protected IEnumerable<Relation> Relations<TRelationKind>()
|
||||
protected IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : struct
|
||||
{
|
||||
return RelationDepot.Relations<TRelationKind>();
|
||||
}
|
||||
|
||||
protected bool Related<TRelationKind>(in Entity a, in Entity b)
|
||||
protected bool Related<TRelationKind>(in Entity a, in Entity b) where TRelationKind : struct
|
||||
{
|
||||
return RelationDepot.Related<TRelationKind>(a.ID, b.ID);
|
||||
}
|
||||
|
||||
protected IEnumerable<Entity> RelatedToA<TRelationKind>(in Entity entity)
|
||||
protected IEnumerable<(Entity, TRelationKind)> RelatedToA<TRelationKind>(in Entity entity) where TRelationKind : struct
|
||||
{
|
||||
return RelationDepot.RelatedToA<TRelationKind>(entity.ID);
|
||||
}
|
||||
|
||||
protected IEnumerable<Entity> RelatedToB<TRelationKind>(in Entity entity)
|
||||
protected IEnumerable<(Entity, TRelationKind)> RelatedToB<TRelationKind>(in Entity entity) where TRelationKind : struct
|
||||
{
|
||||
return RelationDepot.RelatedToB<TRelationKind>(entity.ID);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace MoonTools.ECS
|
||||
{
|
||||
public struct Relation : IEquatable<Relation>
|
||||
internal struct Relation : IEquatable<Relation>
|
||||
{
|
||||
public Entity A { get; }
|
||||
public Entity B { get; }
|
||||
|
@ -26,12 +26,12 @@ namespace MoonTools.ECS
|
|||
|
||||
public bool Equals(Relation other)
|
||||
{
|
||||
return A.Equals(other.A) && B.Equals(other.B);
|
||||
return A.ID == other.A.ID && B.ID == other.B.ID;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(A, B);
|
||||
return HashCode.Combine(A.ID, B.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,26 +7,31 @@ namespace MoonTools.ECS
|
|||
{
|
||||
private Dictionary<Type, RelationStorage> storages = new Dictionary<Type, RelationStorage>();
|
||||
|
||||
private RelationStorage Lookup<TRelationKind>()
|
||||
private void Register<TRelationKind>() where TRelationKind : struct
|
||||
{
|
||||
return storages[typeof(TRelationKind)];
|
||||
if (!storages.ContainsKey(typeof(TRelationKind)))
|
||||
{
|
||||
storages.Add(typeof(TRelationKind), new RelationStorage<TRelationKind>());
|
||||
}
|
||||
}
|
||||
|
||||
public void Register<TRelationKind>()
|
||||
private RelationStorage<TRelationKind> Lookup<TRelationKind>() where TRelationKind : struct
|
||||
{
|
||||
storages[typeof(TRelationKind)] = new RelationStorage();
|
||||
Register<TRelationKind>();
|
||||
return (RelationStorage<TRelationKind>) storages[typeof(TRelationKind)];
|
||||
}
|
||||
|
||||
public void Add<TRelationKind>(Relation relation)
|
||||
public void Add<TRelationKind>(Relation relation, TRelationKind relationData) where TRelationKind : struct
|
||||
{
|
||||
Lookup<TRelationKind>().Add(relation);
|
||||
Lookup<TRelationKind>().Add(relation, relationData);
|
||||
}
|
||||
|
||||
public void Remove<TRelationKind>(Relation relation)
|
||||
public void Remove<TRelationKind>(Relation relation) where TRelationKind : struct
|
||||
{
|
||||
Lookup<TRelationKind>().Remove(relation);
|
||||
}
|
||||
|
||||
// FIXME: optimize this
|
||||
public void OnEntityDestroy(int entityID)
|
||||
{
|
||||
foreach (var storage in storages.Values)
|
||||
|
@ -35,22 +40,22 @@ namespace MoonTools.ECS
|
|||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Relation> Relations<TRelationKind>()
|
||||
public IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : struct
|
||||
{
|
||||
return Lookup<TRelationKind>().All();
|
||||
}
|
||||
|
||||
public bool Related<TRelationKind>(int idA, int idB)
|
||||
public bool Related<TRelationKind>(int idA, int idB) where TRelationKind : struct
|
||||
{
|
||||
return Lookup<TRelationKind>().Has(new Relation(idA, idB));
|
||||
}
|
||||
|
||||
public IEnumerable<Entity> RelatedToA<TRelationKind>(int entityID)
|
||||
public IEnumerable<(Entity, TRelationKind)> RelatedToA<TRelationKind>(int entityID) where TRelationKind : struct
|
||||
{
|
||||
return Lookup<TRelationKind>().RelatedToA(entityID);
|
||||
}
|
||||
|
||||
public IEnumerable<Entity> RelatedToB<TRelationKind>(int entityID)
|
||||
public IEnumerable<(Entity, TRelationKind)> RelatedToB<TRelationKind>(int entityID) where TRelationKind : struct
|
||||
{
|
||||
return Lookup<TRelationKind>().RelatedToB(entityID);
|
||||
}
|
||||
|
|
|
@ -2,24 +2,31 @@
|
|||
|
||||
namespace MoonTools.ECS
|
||||
{
|
||||
internal class RelationStorage
|
||||
internal abstract class RelationStorage
|
||||
{
|
||||
private HashSet<Relation> relations = new HashSet<Relation>(16);
|
||||
public abstract void OnEntityDestroy(int entityID);
|
||||
}
|
||||
|
||||
// Relation is the two entities, A related to B.
|
||||
// TRelation is the data attached to the relation.
|
||||
internal class RelationStorage<TRelation> : RelationStorage where TRelation : struct
|
||||
{
|
||||
private Dictionary<Relation, TRelation> relations = new Dictionary<Relation, TRelation>(16);
|
||||
private Dictionary<int, HashSet<int>> entitiesRelatedToA = new Dictionary<int, HashSet<int>>(16);
|
||||
private Dictionary<int, HashSet<int>> entitiesRelatedToB = new Dictionary<int, HashSet<int>>(16);
|
||||
private Stack<HashSet<int>> listPool = new Stack<HashSet<int>>();
|
||||
|
||||
public IEnumerable<Relation> All()
|
||||
public IEnumerable<(Entity, Entity, TRelation)> All()
|
||||
{
|
||||
foreach (var relation in relations)
|
||||
foreach (var relationData in relations)
|
||||
{
|
||||
yield return relation;
|
||||
yield return (relationData.Key.A, relationData.Key.B, relationData.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(Relation relation)
|
||||
public void Add(Relation relation, TRelation relationData)
|
||||
{
|
||||
if (relations.Contains(relation)) { return; }
|
||||
if (relations.ContainsKey(relation)) { return; }
|
||||
|
||||
var idA = relation.A.ID;
|
||||
var idB = relation.B.ID;
|
||||
|
@ -36,32 +43,35 @@ namespace MoonTools.ECS
|
|||
}
|
||||
entitiesRelatedToB[idB].Add(idA);
|
||||
|
||||
relations.Add(relation);
|
||||
relations.Add(relation, relationData);
|
||||
}
|
||||
|
||||
public bool Has(Relation relation)
|
||||
{
|
||||
return relations.Contains(relation);
|
||||
return relations.ContainsKey(relation);
|
||||
}
|
||||
|
||||
public IEnumerable<Entity> RelatedToA(int entityID)
|
||||
// FIXME: is there a more descriptive name for these?
|
||||
public IEnumerable<(Entity, TRelation)> RelatedToA(int entityID)
|
||||
{
|
||||
if (entitiesRelatedToA.ContainsKey(entityID))
|
||||
{
|
||||
foreach (var id in entitiesRelatedToA[entityID])
|
||||
{
|
||||
yield return new Entity(id);
|
||||
var relation = new Relation(entityID, id);
|
||||
yield return (relation.B, relations[relation]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Entity> RelatedToB(int entityID)
|
||||
public IEnumerable<(Entity, TRelation)> RelatedToB(int entityID)
|
||||
{
|
||||
if (entitiesRelatedToB.ContainsKey(entityID))
|
||||
{
|
||||
foreach (var id in entitiesRelatedToB[entityID])
|
||||
{
|
||||
yield return new Entity(id);
|
||||
var relation = new Relation(id, entityID);
|
||||
yield return (relation.A, relations[relation]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,19 +91,13 @@ namespace MoonTools.ECS
|
|||
return relations.Remove(relation);
|
||||
}
|
||||
|
||||
// this exists so we don't recurse in OnEntityDestroy
|
||||
private bool DestroyRemove(Relation relation)
|
||||
{
|
||||
return relations.Remove(relation);
|
||||
}
|
||||
|
||||
public void OnEntityDestroy(int entityID)
|
||||
public override void OnEntityDestroy(int entityID)
|
||||
{
|
||||
if (entitiesRelatedToA.ContainsKey(entityID))
|
||||
{
|
||||
foreach (var entityB in entitiesRelatedToA[entityID])
|
||||
{
|
||||
DestroyRemove(new Relation(entityID, entityB));
|
||||
Remove(new Relation(entityID, entityB));
|
||||
}
|
||||
|
||||
ReturnHashSetToPool(entitiesRelatedToA[entityID]);
|
||||
|
@ -104,7 +108,7 @@ namespace MoonTools.ECS
|
|||
{
|
||||
foreach (var entityA in entitiesRelatedToB[entityID])
|
||||
{
|
||||
DestroyRemove(new Relation(entityA, entityID));
|
||||
Remove(new Relation(entityA, entityID));
|
||||
}
|
||||
|
||||
ReturnHashSetToPool(entitiesRelatedToB[entityID]);
|
||||
|
@ -124,6 +128,7 @@ namespace MoonTools.ECS
|
|||
|
||||
private void ReturnHashSetToPool(HashSet<int> hashSet)
|
||||
{
|
||||
hashSet.Clear();
|
||||
listPool.Push(hashSet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,12 +76,12 @@ namespace MoonTools.ECS
|
|||
MessageDepot.Add(message);
|
||||
}
|
||||
|
||||
protected void Relate<TRelationKind>(in Entity entityA, in Entity entityB)
|
||||
protected void Relate<TRelationKind>(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : struct
|
||||
{
|
||||
RelationDepot.Add<TRelationKind>(new Relation(entityA, entityB));
|
||||
RelationDepot.Add<TRelationKind>(new Relation(entityA, entityB), relationData);
|
||||
}
|
||||
|
||||
protected void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB)
|
||||
protected void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : struct
|
||||
{
|
||||
RelationDepot.Remove<TRelationKind>(new Relation(entityA, entityB));
|
||||
}
|
||||
|
|
|
@ -22,11 +22,6 @@
|
|||
renderer.RegisterRelationDepot(RelationDepot);
|
||||
}
|
||||
|
||||
public void AddRelationKind<TRelationKind>()
|
||||
{
|
||||
RelationDepot.Register<TRelationKind>();
|
||||
}
|
||||
|
||||
public Entity CreateEntity()
|
||||
{
|
||||
return EntityStorage.Create();
|
||||
|
|
Loading…
Reference in New Issue