experimenting with filtering relations
parent
93ed5c8dd2
commit
5a2c8851ee
|
@ -9,7 +9,7 @@ namespace MoonTools.ECS
|
|||
internal EntityStorage EntityStorage => World.EntityStorage;
|
||||
internal ComponentDepot ComponentDepot => World.ComponentDepot;
|
||||
internal RelationDepot RelationDepot => World.RelationDepot;
|
||||
protected FilterBuilder FilterBuilder => new FilterBuilder(FilterStorage, ComponentTypeIndices);
|
||||
protected FilterBuilder FilterBuilder => new FilterBuilder(FilterStorage, ComponentTypeIndices, RelationTypeIndices);
|
||||
internal FilterStorage FilterStorage => World.FilterStorage;
|
||||
internal TypeIndices ComponentTypeIndices => World.ComponentTypeIndices;
|
||||
internal TypeIndices RelationTypeIndices => World.RelationTypeIndices;
|
||||
|
|
|
@ -8,10 +8,15 @@ namespace MoonTools.ECS
|
|||
internal FilterSignature Signature;
|
||||
private FilterStorage FilterStorage;
|
||||
|
||||
internal Filter(FilterStorage filterStorage, HashSet<int> included, HashSet<int> excluded)
|
||||
{
|
||||
internal Filter(
|
||||
FilterStorage filterStorage,
|
||||
HashSet<int> included,
|
||||
HashSet<int> excluded,
|
||||
HashSet<int> inRelations,
|
||||
HashSet<int> outRelations
|
||||
) {
|
||||
FilterStorage = filterStorage;
|
||||
Signature = new FilterSignature(included, excluded);
|
||||
Signature = new FilterSignature(included, excluded, inRelations, outRelations);
|
||||
}
|
||||
|
||||
public ReverseSpanEnumerator<Entity> Entities => FilterStorage.FilterEntities(Signature);
|
||||
|
|
|
@ -6,41 +6,72 @@ namespace MoonTools.ECS
|
|||
public struct FilterBuilder
|
||||
{
|
||||
private TypeIndices ComponentTypeIndices;
|
||||
private TypeIndices RelationTypeIndices;
|
||||
private FilterStorage FilterStorage;
|
||||
private HashSet<int> Included;
|
||||
private HashSet<int> Excluded;
|
||||
private HashSet<int> InRelations;
|
||||
private HashSet<int> OutRelations;
|
||||
|
||||
internal FilterBuilder(FilterStorage filterStorage, TypeIndices componentTypeIndices)
|
||||
{
|
||||
internal FilterBuilder(
|
||||
FilterStorage filterStorage,
|
||||
TypeIndices componentTypeIndices,
|
||||
TypeIndices relationTypeIndices
|
||||
) {
|
||||
FilterStorage = filterStorage;
|
||||
ComponentTypeIndices = componentTypeIndices;
|
||||
RelationTypeIndices = relationTypeIndices;
|
||||
Included = new HashSet<int>();
|
||||
Excluded = new HashSet<int>();
|
||||
InRelations = new HashSet<int>();
|
||||
OutRelations = new HashSet<int>();
|
||||
}
|
||||
|
||||
private FilterBuilder(FilterStorage filterStorage, TypeIndices componentTypeIndices, HashSet<int> included, HashSet<int> excluded)
|
||||
{
|
||||
private FilterBuilder(
|
||||
FilterStorage filterStorage,
|
||||
TypeIndices componentTypeIndices,
|
||||
TypeIndices relationTypeIndices,
|
||||
HashSet<int> included,
|
||||
HashSet<int> excluded,
|
||||
HashSet<int> inRelations,
|
||||
HashSet<int> outRelations
|
||||
) {
|
||||
FilterStorage = filterStorage;
|
||||
ComponentTypeIndices = componentTypeIndices;
|
||||
RelationTypeIndices = relationTypeIndices;
|
||||
Included = included;
|
||||
Excluded = excluded;
|
||||
InRelations = inRelations;
|
||||
OutRelations = outRelations;
|
||||
}
|
||||
|
||||
public FilterBuilder Include<TComponent>() where TComponent : unmanaged
|
||||
{
|
||||
Included.Add(ComponentTypeIndices.GetIndex<TComponent>());
|
||||
return new FilterBuilder(FilterStorage, ComponentTypeIndices, Included, Excluded);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FilterBuilder Exclude<TComponent>() where TComponent : unmanaged
|
||||
{
|
||||
Excluded.Add(ComponentTypeIndices.GetIndex<TComponent>());
|
||||
return new FilterBuilder(FilterStorage, ComponentTypeIndices, Included, Excluded);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FilterBuilder WithInRelation<TRelation>() where TRelation : unmanaged
|
||||
{
|
||||
InRelations.Add(RelationTypeIndices.GetIndex<TRelation>());
|
||||
return this;
|
||||
}
|
||||
|
||||
public FilterBuilder WithOutRelation<TRelation>() where TRelation : unmanaged
|
||||
{
|
||||
OutRelations.Add(RelationTypeIndices.GetIndex<TRelation>());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Filter Build()
|
||||
{
|
||||
return FilterStorage.CreateFilter(Included, Excluded);
|
||||
return FilterStorage.CreateFilter(Included, Excluded, InRelations, OutRelations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,23 @@ using System.Collections.Generic;
|
|||
|
||||
namespace MoonTools.ECS
|
||||
{
|
||||
public struct FilterSignature : IEquatable<FilterSignature>
|
||||
internal struct FilterSignature : IEquatable<FilterSignature>
|
||||
{
|
||||
public readonly HashSet<int> Included;
|
||||
public readonly HashSet<int> Excluded;
|
||||
public readonly HashSet<int> InRelations;
|
||||
public readonly HashSet<int> OutRelations;
|
||||
|
||||
public FilterSignature(HashSet<int> included, HashSet<int> excluded)
|
||||
{
|
||||
public FilterSignature(
|
||||
HashSet<int> included,
|
||||
HashSet<int> excluded,
|
||||
HashSet<int> inRelations,
|
||||
HashSet<int> outRelations
|
||||
) {
|
||||
Included = included;
|
||||
Excluded = excluded;
|
||||
InRelations = inRelations;
|
||||
OutRelations = outRelations;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
|
@ -21,7 +29,11 @@ namespace MoonTools.ECS
|
|||
|
||||
public bool Equals(FilterSignature other)
|
||||
{
|
||||
return Included.SetEquals(other.Included) && Excluded.SetEquals(other.Excluded);
|
||||
return
|
||||
Included.SetEquals(other.Included) &&
|
||||
Excluded.SetEquals(other.Excluded) &&
|
||||
InRelations.SetEquals(other.InRelations) &&
|
||||
OutRelations.SetEquals(other.OutRelations);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
|
@ -38,6 +50,16 @@ namespace MoonTools.ECS
|
|||
hashcode = HashCode.Combine(hashcode, type);
|
||||
}
|
||||
|
||||
foreach (var type in InRelations)
|
||||
{
|
||||
hashcode = HashCode.Combine(hashcode, type);
|
||||
}
|
||||
|
||||
foreach (var type in OutRelations)
|
||||
{
|
||||
hashcode = HashCode.Combine(hashcode, type);
|
||||
}
|
||||
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,44 +6,78 @@ namespace MoonTools.ECS
|
|||
internal class FilterStorage
|
||||
{
|
||||
private EntityStorage EntityStorage;
|
||||
private RelationDepot RelationDepot;
|
||||
private TypeIndices ComponentTypeIndices;
|
||||
private TypeIndices RelationTypeIndices;
|
||||
private Dictionary<FilterSignature, IndexableSet<Entity>> filterSignatureToEntityIDs = new Dictionary<FilterSignature, IndexableSet<Entity>>();
|
||||
private Dictionary<int, HashSet<FilterSignature>> typeToFilterSignatures = new Dictionary<int, HashSet<FilterSignature>>();
|
||||
private Dictionary<int, HashSet<FilterSignature>> componentTypeToFilterSignatures = new Dictionary<int, HashSet<FilterSignature>>();
|
||||
private Dictionary<int, HashSet<FilterSignature>> relationTypeToFilterSignatures = new Dictionary<int, HashSet<FilterSignature>>();
|
||||
|
||||
public FilterStorage(EntityStorage entityStorage, TypeIndices componentTypeIndices)
|
||||
{
|
||||
public FilterStorage(
|
||||
EntityStorage entityStorage,
|
||||
RelationDepot relationDepot,
|
||||
TypeIndices componentTypeIndices,
|
||||
TypeIndices relationTypeIndices
|
||||
) {
|
||||
EntityStorage = entityStorage;
|
||||
RelationDepot = relationDepot;
|
||||
ComponentTypeIndices = componentTypeIndices;
|
||||
RelationTypeIndices = relationTypeIndices;
|
||||
}
|
||||
|
||||
public Filter CreateFilter(HashSet<int> included, HashSet<int> excluded)
|
||||
{
|
||||
var filterSignature = new FilterSignature(included, excluded);
|
||||
public Filter CreateFilter(
|
||||
HashSet<int> included,
|
||||
HashSet<int> excluded,
|
||||
HashSet<int> inRelations,
|
||||
HashSet<int> outRelations
|
||||
) {
|
||||
var filterSignature = new FilterSignature(included, excluded, inRelations, outRelations);
|
||||
if (!filterSignatureToEntityIDs.ContainsKey(filterSignature))
|
||||
{
|
||||
filterSignatureToEntityIDs.Add(filterSignature, new IndexableSet<Entity>());
|
||||
|
||||
foreach (var type in included)
|
||||
{
|
||||
if (!typeToFilterSignatures.ContainsKey(type))
|
||||
if (!componentTypeToFilterSignatures.ContainsKey(type))
|
||||
{
|
||||
typeToFilterSignatures.Add(type, new HashSet<FilterSignature>());
|
||||
componentTypeToFilterSignatures.Add(type, new HashSet<FilterSignature>());
|
||||
}
|
||||
|
||||
typeToFilterSignatures[type].Add(filterSignature);
|
||||
componentTypeToFilterSignatures[type].Add(filterSignature);
|
||||
}
|
||||
|
||||
foreach (var type in excluded)
|
||||
{
|
||||
if (!typeToFilterSignatures.ContainsKey(type))
|
||||
if (!componentTypeToFilterSignatures.ContainsKey(type))
|
||||
{
|
||||
typeToFilterSignatures.Add(type, new HashSet<FilterSignature>());
|
||||
componentTypeToFilterSignatures.Add(type, new HashSet<FilterSignature>());
|
||||
}
|
||||
|
||||
typeToFilterSignatures[type].Add(filterSignature);
|
||||
componentTypeToFilterSignatures[type].Add(filterSignature);
|
||||
}
|
||||
|
||||
foreach (var type in inRelations)
|
||||
{
|
||||
if (!relationTypeToFilterSignatures.ContainsKey(type))
|
||||
{
|
||||
relationTypeToFilterSignatures.Add(type, new HashSet<FilterSignature>());
|
||||
}
|
||||
|
||||
relationTypeToFilterSignatures[type].Add(filterSignature);
|
||||
}
|
||||
|
||||
foreach (var type in outRelations)
|
||||
{
|
||||
if (!relationTypeToFilterSignatures.ContainsKey(type))
|
||||
{
|
||||
relationTypeToFilterSignatures.Add(type, new HashSet<FilterSignature>());
|
||||
}
|
||||
|
||||
relationTypeToFilterSignatures[type].Add(filterSignature);
|
||||
}
|
||||
}
|
||||
return new Filter(this, included, excluded);
|
||||
|
||||
return new Filter(this, included, excluded, inRelations, outRelations);
|
||||
}
|
||||
|
||||
public ReverseSpanEnumerator<Entity> FilterEntities(FilterSignature filterSignature)
|
||||
|
@ -72,9 +106,20 @@ namespace MoonTools.ECS
|
|||
return filterSignatureToEntityIDs[filterSignature].Count;
|
||||
}
|
||||
|
||||
public void Check(int entityID, int componentTypeIndex)
|
||||
public void CheckComponentChange(int entityID, int componentTypeIndex)
|
||||
{
|
||||
if (typeToFilterSignatures.TryGetValue(componentTypeIndex, out var filterSignatures))
|
||||
if (componentTypeToFilterSignatures.TryGetValue(componentTypeIndex, out var filterSignatures))
|
||||
{
|
||||
foreach (var filterSignature in filterSignatures)
|
||||
{
|
||||
CheckFilter(entityID, filterSignature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckRelationChange(int entityID, int relationTypeIndex)
|
||||
{
|
||||
if (relationTypeToFilterSignatures.TryGetValue(relationTypeIndex, out var filterSignatures))
|
||||
{
|
||||
foreach (var filterSignature in filterSignatures)
|
||||
{
|
||||
|
@ -85,7 +130,7 @@ namespace MoonTools.ECS
|
|||
|
||||
public void Check<TComponent>(int entityID) where TComponent : unmanaged
|
||||
{
|
||||
Check(entityID, ComponentTypeIndices.GetIndex<TComponent>());
|
||||
CheckComponentChange(entityID, ComponentTypeIndices.GetIndex<TComponent>());
|
||||
}
|
||||
|
||||
public bool CheckSatisfied(int entityID, FilterSignature filterSignature)
|
||||
|
@ -106,35 +151,40 @@ namespace MoonTools.ECS
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var type in filterSignature.InRelations)
|
||||
{
|
||||
if (!RelationDepot.HasInRelation(entityID, type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var type in filterSignature.OutRelations)
|
||||
{
|
||||
if (!RelationDepot.HasOutRelation(entityID, type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CheckFilter(int entityID, FilterSignature filterSignature)
|
||||
{
|
||||
foreach (var type in filterSignature.Included)
|
||||
if (CheckSatisfied(entityID, filterSignature))
|
||||
{
|
||||
if (!EntityStorage.HasComponent(entityID, type))
|
||||
{
|
||||
filterSignatureToEntityIDs[filterSignature].Remove(entityID);
|
||||
return;
|
||||
}
|
||||
filterSignatureToEntityIDs[filterSignature].Remove(entityID);
|
||||
}
|
||||
|
||||
foreach (var type in filterSignature.Excluded)
|
||||
else
|
||||
{
|
||||
if (EntityStorage.HasComponent(entityID, type))
|
||||
{
|
||||
filterSignatureToEntityIDs[filterSignature].Remove(entityID);
|
||||
return;
|
||||
}
|
||||
filterSignatureToEntityIDs[filterSignature].Remove(entityID);
|
||||
}
|
||||
|
||||
filterSignatureToEntityIDs[filterSignature].Add(entityID);
|
||||
}
|
||||
|
||||
public void RemoveEntity(int entityID, int componentTypeIndex)
|
||||
{
|
||||
if (typeToFilterSignatures.TryGetValue(componentTypeIndex, out var filterSignatures))
|
||||
if (componentTypeToFilterSignatures.TryGetValue(componentTypeIndex, out var filterSignatures))
|
||||
{
|
||||
foreach (var filterSignature in filterSignatures)
|
||||
{
|
||||
|
|
|
@ -86,6 +86,11 @@ namespace MoonTools.ECS
|
|||
return Lookup<TRelationKind>().HasOutRelation(entityID);
|
||||
}
|
||||
|
||||
public bool HasOutRelation(int entityID, int typeIndex)
|
||||
{
|
||||
return storages[typeIndex].HasOutRelation(entityID);
|
||||
}
|
||||
|
||||
public ReverseSpanEnumerator<Entity> InRelations<TRelationKind>(int entityID) where TRelationKind : unmanaged
|
||||
{
|
||||
return Lookup<TRelationKind>().InRelations(entityID);
|
||||
|
@ -101,6 +106,11 @@ namespace MoonTools.ECS
|
|||
return Lookup<TRelationKind>().HasInRelation(entityID);
|
||||
}
|
||||
|
||||
public bool HasInRelation(int entityID, int typeIndex)
|
||||
{
|
||||
return storages[typeIndex].HasInRelation(entityID);
|
||||
}
|
||||
|
||||
public int InRelationCount<TRelationKind>(int entityID) where TRelationKind : unmanaged
|
||||
{
|
||||
return Lookup<TRelationKind>().InRelationCount(entityID);
|
||||
|
|
|
@ -5,6 +5,8 @@ namespace MoonTools.ECS
|
|||
{
|
||||
internal abstract class RelationStorage
|
||||
{
|
||||
public abstract bool HasInRelation(int entityID);
|
||||
public abstract bool HasOutRelation(int entityID);
|
||||
public abstract unsafe void Set(int entityA, int entityB, void* relationData);
|
||||
public abstract int GetStorageIndex(int entityA, int entityB);
|
||||
public abstract unsafe void* Get(int relationStorageIndex);
|
||||
|
@ -101,7 +103,7 @@ namespace MoonTools.ECS
|
|||
return outRelations[entityID][0];
|
||||
}
|
||||
|
||||
public bool HasOutRelation(int entityID)
|
||||
public override bool HasOutRelation(int entityID)
|
||||
{
|
||||
return outRelations.ContainsKey(entityID) && outRelations[entityID].Count > 0;
|
||||
}
|
||||
|
@ -135,7 +137,7 @@ namespace MoonTools.ECS
|
|||
return inRelations[entityID][0];
|
||||
}
|
||||
|
||||
public bool HasInRelation(int entityID)
|
||||
public override bool HasInRelation(int entityID)
|
||||
{
|
||||
return inRelations.ContainsKey(entityID) && inRelations[entityID].Count > 0;
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace MoonTools.ECS
|
|||
foreach (var componentTypeIndex in SnapshotEntityStorage.ComponentTypeIndices(i))
|
||||
{
|
||||
World.EntityStorage.SetComponent(entity.ID, componentTypeIndex);
|
||||
World.FilterStorage.Check(entity.ID, componentTypeIndex);
|
||||
World.FilterStorage.CheckComponentChange(entity.ID, componentTypeIndex);
|
||||
World.ComponentDepot.Set(entity.ID, componentTypeIndex, SnapshotComponentDepot.UntypedGet(i, componentTypeIndex));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace MoonTools.ECS
|
|||
internal readonly MessageDepot MessageDepot = new MessageDepot();
|
||||
internal readonly RelationDepot RelationDepot;
|
||||
internal readonly FilterStorage FilterStorage;
|
||||
public FilterBuilder FilterBuilder => new FilterBuilder(FilterStorage, ComponentTypeIndices);
|
||||
public FilterBuilder FilterBuilder => new FilterBuilder(FilterStorage, ComponentTypeIndices, RelationTypeIndices);
|
||||
|
||||
internal readonly TemplateStorage TemplateStorage = new TemplateStorage();
|
||||
internal readonly ComponentDepot TemplateComponentDepot;
|
||||
|
@ -20,7 +20,7 @@ namespace MoonTools.ECS
|
|||
{
|
||||
ComponentDepot = new ComponentDepot(ComponentTypeIndices);
|
||||
RelationDepot = new RelationDepot(RelationTypeIndices);
|
||||
FilterStorage = new FilterStorage(EntityStorage, ComponentTypeIndices);
|
||||
FilterStorage = new FilterStorage(EntityStorage, RelationDepot, ComponentTypeIndices, RelationTypeIndices);
|
||||
TemplateComponentDepot = new ComponentDepot(ComponentTypeIndices);
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ namespace MoonTools.ECS
|
|||
foreach (var componentTypeIndex in TemplateStorage.ComponentTypeIndices(template.ID))
|
||||
{
|
||||
EntityStorage.SetComponent(entity.ID, componentTypeIndex);
|
||||
FilterStorage.Check(entity.ID, componentTypeIndex);
|
||||
FilterStorage.CheckComponentChange(entity.ID, componentTypeIndex);
|
||||
ComponentDepot.Set(entity.ID, componentTypeIndex, TemplateComponentDepot.UntypedGet(template.ID, componentTypeIndex));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue