add compatibility structures

rev2
cosmonaut 2023-10-31 14:28:12 -07:00
parent 3d2261f739
commit c7f7d8c362
7 changed files with 137 additions and 12 deletions

View File

@ -0,0 +1,29 @@
namespace MoonTools.ECS.Rev2.Compatibility;
public abstract class EntityComponentReader
{
protected World World;
protected EntityComponentReader(World world)
{
World = world;
}
protected bool Has<T>(in Id entityId) where T : unmanaged => World.Has<T>(entityId);
protected bool Some<T>() where T : unmanaged => World.Some<T>();
protected ref T Get<T>(in Id entityId) where T : unmanaged => ref World.Get<T>(entityId);
protected ref T GetSingleton<T>() where T : unmanaged => ref World.GetSingleton<T>();
protected Id GetSingletonEntity<T>() where T : unmanaged => World.GetSingletonEntity<T>();
protected ReverseSpanEnumerator<(Id, Id)> Relations<T>() where T : unmanaged => World.Relations<T>();
protected bool Related<T>(in Id entityA, in Id entityB) where T : unmanaged => World.Related<T>(entityA, entityB);
protected T GetRelationData<T>(in Id entityA, in Id entityB) where T : unmanaged => World.GetRelationData<T>(entityA, entityB);
protected ReverseSpanEnumerator<Id> OutRelations<T>(in Id entity) where T : unmanaged => World.OutRelations<T>(entity);
protected Id OutRelationSingleton<T>(in Id entity) where T : unmanaged => World.OutRelationSingleton<T>(entity);
protected bool HasOutRelation<T>(in Id entity) where T : unmanaged => World.HasOutRelation<T>(entity);
protected ReverseSpanEnumerator<Id> InRelations<T>(in Id entity) where T : unmanaged => World.InRelations<T>(entity);
protected Id InRelationSingleton<T>(in Id entity) where T : unmanaged => World.InRelationSingleton<T>(entity);
protected bool HasInRelation<T>(in Id entity) where T : unmanaged => World.HasInRelation<T>(entity);
}

View File

@ -0,0 +1,13 @@
namespace MoonTools.ECS.Rev2.Compatibility;
public class Manipulator : EntityComponentReader
{
public Manipulator(World world) : base(world) { }
protected void Set<TComponent>(in Id entity, in TComponent component) where TComponent : unmanaged => World.Set<TComponent>(entity, component);
protected void Remove<TComponent>(in Id entity) where TComponent : unmanaged => World.Remove<TComponent>(entity);
protected void Unrelate<TRelationKind>(in Id entityA, in Id entityB) where TRelationKind : unmanaged => World.Unrelate<TRelationKind>(entityA, entityB);
protected void UnrelateAll<TRelationKind>(in Id entity) where TRelationKind : unmanaged => World.UnrelateAll<TRelationKind>(entity);
protected void Destroy(in Id entity) => World.Destroy(entity);
}

View File

@ -0,0 +1,6 @@
namespace MoonTools.ECS.Rev2.Compatibility;
public class Renderer : EntityComponentReader
{
public Renderer(World world) : base(world) { }
}

View File

@ -0,0 +1,13 @@
using System;
namespace MoonTools.ECS.Rev2.Compatibility;
public class System : Manipulator
{
public System(World world) : base(world) { }
protected ReadOnlySpan<T> ReadMessages<T>() where T : unmanaged => World.ReadMessages<T>();
protected T ReadMessage<T>() where T : unmanaged => World.ReadMessage<T>();
protected bool SomeMessage<T>() where T : unmanaged => World.SomeMessage<T>();
protected void Send<T>(T message) where T : unmanaged => World.Send(message);
}

View File

@ -24,15 +24,13 @@ public ref struct FilterBuilder
public FilterBuilder Include<T>() where T : unmanaged
{
World.GetTypeId<T>();
Included.Add(World.TypeToId[typeof(T)]);
Included.Add(World.GetTypeId<T>());
return new FilterBuilder(World, Included, Excluded);
}
public FilterBuilder Exclude<T>() where T : unmanaged
{
World.GetTypeId<T>();
Excluded.Add(World.TypeToId[typeof(T)]);
Excluded.Add(World.GetTypeId<T>());
return new FilterBuilder(World, Included, Excluded);
}

View File

@ -187,7 +187,7 @@ internal class RelationStorage
return (aEmpty, bEmpty);
}
public void RemoveEntity(Id entity)
public void RemoveEntity(in Id entity)
{
if (outRelations.TryGetValue(entity, out var entityOutRelations))
{

View File

@ -18,9 +18,6 @@ public class World : IDisposable
// Going from EntityId to Archetype and storage row
internal Dictionary<Id, Record> EntityIndex = new Dictionary<Id, Record>();
// Going from ComponentId to Archetype list
Dictionary<Id, List<Archetype>> ComponentIndex = new Dictionary<Id, List<Archetype>>();
// Relation Storages
internal Dictionary<Id, RelationStorage> RelationIndex =
new Dictionary<Id, RelationStorage>();
@ -33,6 +30,9 @@ public class World : IDisposable
private Dictionary<Id, MessageStorage> MessageIndex =
new Dictionary<Id, MessageStorage>();
// Filters with a single Include type for Singleton/Some implementation
private Dictionary<Id, Filter> SingleTypeFilters = new Dictionary<Id, Filter>();
// ID Management
// FIXME: Entity and Type Ids should be separated
internal IdAssigner IdAssigner = new IdAssigner();
@ -60,7 +60,6 @@ public class World : IDisposable
for (int i = 0; i < signature.Count; i += 1)
{
var componentId = signature[i];
ComponentIndex[componentId].Add(archetype);
archetype.ComponentToColumnIndex.Add(componentId, i);
archetype.ComponentColumns[i] = new NativeArray(ElementSizes[componentId]);
}
@ -68,7 +67,7 @@ public class World : IDisposable
return archetype;
}
public Id CreateEntity()
public Id CreateEntity(string tag = "")
{
var entityId = IdAssigner.Assign();
EntityIndex.Add(entityId, new Record(EmptyArchetype, EmptyArchetype.Count));
@ -98,9 +97,9 @@ public class World : IDisposable
private void TryRegisterComponentId<T>() where T : unmanaged
{
var typeId = GetTypeId<T>();
if (!ComponentIndex.ContainsKey(typeId))
if (!SingleTypeFilters.ContainsKey(typeId))
{
ComponentIndex.Add(typeId, new List<Archetype>());
SingleTypeFilters.Add(typeId, FilterBuilder.Include<T>().Build());
}
}
@ -184,6 +183,12 @@ public class World : IDisposable
return record.Archetype.ComponentToColumnIndex.ContainsKey(componentId);
}
public bool Some<T>() where T : unmanaged
{
var componentTypeId = GetComponentId<T>();
return SingleTypeFilters[componentTypeId].Count > 0;
}
// will throw if non-existent
public unsafe ref T Get<T>(Id entityId) where T : unmanaged
{
@ -196,6 +201,37 @@ public class World : IDisposable
return ref ((T*) column.Elements)[record.Row];
}
public ref T GetSingleton<T>() where T : unmanaged
{
var componentId = GetComponentId<T>();
foreach (var archetype in SingleTypeFilters[componentId].Archetypes)
{
if (archetype.Count > 0)
{
var columnIndex = archetype.ComponentToColumnIndex[componentId];
return ref archetype.ComponentColumns[columnIndex].Get<T>(0);
}
}
throw new InvalidOperationException("No component of this type exists!");
}
public Id GetSingletonEntity<T>() where T : unmanaged
{
var componentId = GetComponentId<T>();
foreach (var archetype in SingleTypeFilters[componentId].Archetypes)
{
if (archetype.Count > 0)
{
return archetype.RowToEntity[0];
}
}
throw new InvalidOperationException("No entity with this component type exists!");
}
public unsafe void Set<T>(in Id entityId, in T component) where T : unmanaged
{
TryRegisterComponentId<T>();
@ -301,6 +337,12 @@ public class World : IDisposable
relationStorage.Remove(entityA, entityB);
}
public void UnrelateAll<T>(in Id entity) where T : unmanaged
{
var relationStorage = GetRelationStorage<T>();
relationStorage.RemoveEntity(entity);
}
public bool Related<T>(in Id entityA, in Id entityB) where T : unmanaged
{
var relationStorage = GetRelationStorage<T>();
@ -325,12 +367,36 @@ public class World : IDisposable
return relationStorage.OutRelations(entity);
}
public Id OutRelationSingleton<T>(in Id entity) where T : unmanaged
{
var relationStorage = GetRelationStorage<T>();
return relationStorage.OutFirst(entity);
}
public bool HasOutRelation<T>(in Id entity) where T : unmanaged
{
var relationStorage = GetRelationStorage<T>();
return relationStorage.HasOutRelation(entity);
}
public ReverseSpanEnumerator<Id> InRelations<T>(Id entity) where T : unmanaged
{
var relationStorage = GetRelationStorage<T>();
return relationStorage.InRelations(entity);
}
public Id InRelationSingleton<T>(in Id entity) where T : unmanaged
{
var relationStorage = GetRelationStorage<T>();
return relationStorage.InFirst(entity);
}
public bool HasInRelation<T>(in Id entity) where T : unmanaged
{
var relationStorage = GetRelationStorage<T>();
return relationStorage.HasInRelation(entity);
}
private bool Has(Id entityId, Id typeId)
{
var record = EntityIndex[entityId];