more untyped storage granularity

filter_relations
cosmonaut 2022-12-07 13:53:23 -08:00
parent 9bc6822f38
commit 8d1274cba0
7 changed files with 81 additions and 52 deletions

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace MoonTools.ECS namespace MoonTools.ECS
@ -57,8 +58,6 @@ namespace MoonTools.ECS
Lookup<TComponent>().Set(entityID, component); Lookup<TComponent>().Set(entityID, component);
} }
public Entity GetSingletonEntity<TComponent>() where TComponent : unmanaged public Entity GetSingletonEntity<TComponent>() where TComponent : unmanaged
{ {
return Lookup<TComponent>().FirstEntity(); return Lookup<TComponent>().FirstEntity();
@ -92,14 +91,12 @@ namespace MoonTools.ECS
// these methods used to implement snapshots, templates, and debugging // these methods used to implement snapshots, templates, and debugging
// FIXME: use unsafe pointers instead of object internal unsafe void* UntypedGet(int entityID, int componentTypeIndex)
internal object UntypedGet(int entityID, int componentTypeIndex)
{ {
return storages[componentTypeIndex].UntypedGet(entityID); return storages[componentTypeIndex].UntypedGet(entityID);
} }
// FIXME: use unsafe pointers instead of object internal unsafe void Set(int entityID, int componentTypeIndex, void* component)
internal void Set(int entityID, int componentTypeIndex, object component)
{ {
storages[componentTypeIndex].Set(entityID, component); storages[componentTypeIndex].Set(entityID, component);
} }
@ -114,5 +111,19 @@ namespace MoonTools.ECS
} }
} }
} }
// this method is used to iterate components of an entity, only for use with a debug inspector
#if DEBUG
public object Debug_Get(int entityID, int componentTypeIndex)
{
return storages[componentTypeIndex].Debug_Get(entityID);
}
public IEnumerable<int> Debug_GetEntityIDs(int componentTypeIndex)
{
return storages[componentTypeIndex].Debug_GetEntityIDs();
}
#endif
} }
} }

View File

@ -1,19 +1,22 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonTools.ECS namespace MoonTools.ECS
{ {
internal abstract class ComponentStorage internal abstract class ComponentStorage
{ {
internal abstract void Set(int entityID, object component); internal abstract unsafe void Set(int entityID, void* component);
public abstract bool Remove(int entityID); public abstract bool Remove(int entityID);
public abstract void Clear(); public abstract void Clear();
// used for debugging and template instantiation // used for debugging and template instantiation
internal abstract object UntypedGet(int entityID); internal abstract unsafe void* UntypedGet(int entityID);
// used to create correctly typed storage on snapshot // used to create correctly typed storage on snapshot
public abstract ComponentStorage CreateStorage(); public abstract ComponentStorage CreateStorage();
#if DEBUG
internal abstract object Debug_Get(int entityID);
internal abstract IEnumerable<int> Debug_GetEntityIDs();
#endif
} }
internal class ComponentStorage<TComponent> : ComponentStorage where TComponent : unmanaged internal class ComponentStorage<TComponent> : ComponentStorage where TComponent : unmanaged
@ -33,9 +36,12 @@ namespace MoonTools.ECS
return ref components[entityIDToStorageIndex[entityID]]; return ref components[entityIDToStorageIndex[entityID]];
} }
internal override object UntypedGet(int entityID) internal override unsafe void* UntypedGet(int entityID)
{ {
return components[entityIDToStorageIndex[entityID]]; fixed (void* p = &components[entityIDToStorageIndex[entityID]])
{
return p;
}
} }
public ref readonly TComponent GetFirst() public ref readonly TComponent GetFirst()
@ -69,9 +75,9 @@ namespace MoonTools.ECS
components[entityIDToStorageIndex[entityID]] = component; components[entityIDToStorageIndex[entityID]] = component;
} }
internal override void Set(int entityID, object component) internal override unsafe void Set(int entityID, void* component)
{ {
Set(entityID, (TComponent) component); Set(entityID, *((TComponent*) component));
} }
// Returns true if the entity had this component. // Returns true if the entity had this component.
@ -127,5 +133,17 @@ namespace MoonTools.ECS
{ {
return new ComponentStorage<TComponent>(); return new ComponentStorage<TComponent>();
} }
#if DEBUG
internal override object Debug_Get(int entityID)
{
return components[entityIDToStorageIndex[entityID]];
}
internal override IEnumerable<int> Debug_GetEntityIDs()
{
return entityIDToStorageIndex.Keys;
}
#endif
} }
} }

View File

@ -9,27 +9,24 @@ namespace MoonTools.ECS
{ {
public abstract class DebugSystem : System public abstract class DebugSystem : System
{ {
private Dictionary<Type, Filter> singleComponentFilters = new Dictionary<Type, Filter>();
protected DebugSystem(World world) : base(world) protected DebugSystem(World world) : base(world)
{ {
} }
protected IEnumerable<object> Debug_GetAllComponents(Entity entity) protected IEnumerable<dynamic> Debug_GetAllComponents(Entity entity)
{ {
foreach (var typeIndex in EntityStorage.ComponentTypeIndices(entity.ID)) foreach (var typeIndex in EntityStorage.ComponentTypeIndices(entity.ID))
{ {
yield return ComponentDepot.UntypedGet(entity.ID, typeIndex); yield return ComponentDepot.Debug_Get(entity.ID, typeIndex);
} }
} }
protected IEnumerable<Entity> Debug_GetEntities(Type componentType) protected IEnumerable<Entity> Debug_GetEntities(Type componentType)
{ {
if (!singleComponentFilters.ContainsKey(componentType)) foreach (var entityID in ComponentDepot.Debug_GetEntityIDs(ComponentTypeIndices.GetIndex(componentType)))
{ {
singleComponentFilters.Add(componentType, new Filter(FilterStorage, new HashSet<int>(ComponentTypeIndices.GetIndex(componentType)), new HashSet<int>())); yield return new Entity(entityID);
} }
return singleComponentFilters[componentType].Entities;
} }
protected IEnumerable<Type> Debug_SearchComponentType(string typeString) protected IEnumerable<Type> Debug_SearchComponentType(string typeString)

View File

@ -103,24 +103,24 @@ namespace MoonTools.ECS
// untyped methods used for destroying and snapshots // untyped methods used for destroying and snapshots
public void Set(int entityA, int entityB, int relationTypeIndex, object relationData) public unsafe void Set(int entityA, int entityB, int relationTypeIndex, void* relationData)
{ {
storages[relationTypeIndex].Set(entityA, entityB, relationData); storages[relationTypeIndex].Set(entityA, entityB, relationData);
} }
public unsafe void* Get(int relationTypeIndex, int relationStorageIndex)
{
return storages[relationTypeIndex].Get(relationStorageIndex);
}
public void UnrelateAll(int entityID, int relationTypeIndex) public void UnrelateAll(int entityID, int relationTypeIndex)
{ {
storages[relationTypeIndex].UnrelateAll(entityID); storages[relationTypeIndex].UnrelateAll(entityID);
} }
public IEnumerable<(int, object)> InRelations(int entityID, int relationTypeIndex) public IEnumerable<(int, int)> OutRelationIndices(int entityID, int relationTypeIndex)
{ {
return storages[relationTypeIndex].UntypedInRelations(entityID); return storages[relationTypeIndex].OutRelationIndices(entityID);
}
public IEnumerable<(int, object)> OutRelations(int entityID, int relationTypeIndex)
{
return storages[relationTypeIndex].UntypedOutRelations(entityID);
} }
public void Clear() public void Clear()

View File

@ -5,11 +5,10 @@ namespace MoonTools.ECS
{ {
internal abstract class RelationStorage internal abstract class RelationStorage
{ {
public abstract void Set(int entityA, int entityB, object relationData); public abstract unsafe void Set(int entityA, int entityB, void* relationData);
public abstract unsafe void* Get(int relationStorageIndex);
public abstract void UnrelateAll(int entityID); public abstract void UnrelateAll(int entityID);
public abstract IEnumerable<(int, object)> UntypedInRelations(int entityID); public abstract IEnumerable<(int, int)> OutRelationIndices(int entityID);
public abstract IEnumerable<(int, object)> UntypedOutRelations(int entityID);
// used to create correctly typed storage on snapshot
public abstract RelationStorage CreateStorage(); public abstract RelationStorage CreateStorage();
public abstract void Clear(); public abstract void Clear();
} }
@ -208,9 +207,17 @@ namespace MoonTools.ECS
// untyped methods used for internal implementation // untyped methods used for internal implementation
public override void Set(int entityA, int entityB, object relationData) public override unsafe void Set(int entityA, int entityB, void* relationData)
{ {
Set(new Relation(entityA, entityB), (TRelation) relationData); Set(new Relation(entityA, entityB), *((TRelation*) relationData));
}
public override unsafe void* Get(int relationStorageIndex)
{
fixed (void* p = &relations[relationStorageIndex])
{
return p;
}
} }
public override void UnrelateAll(int entityID) public override void UnrelateAll(int entityID)
@ -238,19 +245,15 @@ namespace MoonTools.ECS
} }
} }
public override IEnumerable<(int, object)> UntypedInRelations(int entityID) public override IEnumerable<(int, int)> OutRelationIndices(int entityID)
{ {
foreach (var (entity, relationData) in InRelations(entityID)) if (outRelations.ContainsKey(entityID))
{ {
yield return (entity.ID, relationData); foreach (var id in outRelations[entityID])
} {
} var relation = new Relation(entityID, id);
yield return (id, indices[relation]);
public override IEnumerable<(int, object)> UntypedOutRelations(int entityID) }
{
foreach (var (entity, relationData) in OutRelations(entityID))
{
yield return (entity.ID, relationData);
} }
} }

View File

@ -23,7 +23,7 @@ namespace MoonTools.ECS
SnapshotRelationDepot = new RelationDepot(World.RelationTypeIndices); SnapshotRelationDepot = new RelationDepot(World.RelationTypeIndices);
} }
public void Take(Filter filter) public unsafe void Take(Filter filter)
{ {
Clear(); Clear();
Filter = filter; Filter = filter;
@ -50,7 +50,7 @@ namespace MoonTools.ECS
{ {
SnapshotEntityStorage.AddRelationKind(snapshotEntityID, relationTypeIndex); SnapshotEntityStorage.AddRelationKind(snapshotEntityID, relationTypeIndex);
foreach (var (otherEntityID, relationData) in World.RelationDepot.OutRelations(worldEntity.ID, relationTypeIndex)) foreach (var (otherEntityID, relationStorageIndex) in World.RelationDepot.OutRelationIndices(worldEntity.ID, relationTypeIndex))
{ {
#if DEBUG #if DEBUG
if (!World.FilterStorage.CheckSatisfied(otherEntityID, Filter.Signature)) if (!World.FilterStorage.CheckSatisfied(otherEntityID, Filter.Signature))
@ -60,13 +60,13 @@ namespace MoonTools.ECS
#endif #endif
var otherSnapshotID = WorldToSnapshotID[otherEntityID]; var otherSnapshotID = WorldToSnapshotID[otherEntityID];
SnapshotEntityStorage.AddRelationKind(otherSnapshotID, relationTypeIndex); SnapshotEntityStorage.AddRelationKind(otherSnapshotID, relationTypeIndex);
SnapshotRelationDepot.Set(snapshotEntityID, otherSnapshotID, relationTypeIndex, relationData); SnapshotRelationDepot.Set(snapshotEntityID, otherSnapshotID, relationTypeIndex, World.RelationDepot.Get(relationTypeIndex, relationStorageIndex));
} }
} }
} }
} }
public void Restore() public unsafe void Restore()
{ {
if (Filter == null) if (Filter == null)
{ {
@ -99,10 +99,10 @@ namespace MoonTools.ECS
{ {
World.EntityStorage.AddRelationKind(worldID, relationTypeIndex); World.EntityStorage.AddRelationKind(worldID, relationTypeIndex);
foreach (var (otherEntityID, relationData) in SnapshotRelationDepot.OutRelations(i, relationTypeIndex)) foreach (var (otherEntityID, relationStorageIndex) in SnapshotRelationDepot.OutRelationIndices(i, relationTypeIndex))
{ {
var otherEntityWorldID = SnapshotToWorldID[otherEntityID]; var otherEntityWorldID = SnapshotToWorldID[otherEntityID];
World.RelationDepot.Set(worldID, otherEntityWorldID, relationTypeIndex, relationData); World.RelationDepot.Set(worldID, otherEntityWorldID, relationTypeIndex, SnapshotRelationDepot.Get(relationTypeIndex, relationStorageIndex));
} }
} }
} }

View File

@ -59,7 +59,7 @@ namespace MoonTools.ECS
ComponentDepot.Register<TComponent>(componentTypeIndex); ComponentDepot.Register<TComponent>(componentTypeIndex);
} }
public Entity Instantiate(in Template template) public unsafe Entity Instantiate(in Template template)
{ {
var entity = EntityStorage.Create(); var entity = EntityStorage.Create();