Debug methods on World

rev2
cosmonaut 2023-11-01 16:34:24 -07:00
parent 4f7307d29e
commit 2a2d8efc5f
6 changed files with 108 additions and 14 deletions

View File

@ -34,6 +34,11 @@ internal unsafe class NativeArray : IDisposable
return ref ((T*) Elements)[i]; return ref ((T*) Elements)[i];
} }
public void* Get(int i)
{
return (void*)(Elements + ElementSize * i);
}
private void Resize() private void Resize()
{ {
Capacity *= 2; Capacity *= 2;

View File

@ -0,0 +1,17 @@
// NOTE: these methods are very inefficient
// this class should only be used in debugging contexts!!
#if DEBUG
using System;
using System.Collections.Generic;
namespace MoonTools.ECS.Rev2.Compatibility;
public abstract class DebugSystem : System
{
protected DebugSystem(World world) : base(world) { }
protected World.ComponentEnumerator Debug_GetAllComponents(EntityId entity) => World.Debug_GetAllComponents(entity);
protected Filter.EntityEnumerator Debug_GetEntities(Type componentType) => World.Debug_GetEntities(componentType);
protected IEnumerable<Type> Debug_SearchComponentType(string typeString) => World.Debug_SearchComponentType(typeString);
}
#endif

View File

@ -3,6 +3,7 @@
public abstract class EntityComponentReader public abstract class EntityComponentReader
{ {
protected World World; protected World World;
public FilterBuilder FilterBuilder => World.FilterBuilder;
protected EntityComponentReader(World world) protected EntityComponentReader(World world)
{ {

View File

@ -4,8 +4,6 @@ namespace MoonTools.ECS.Rev2.Compatibility;
public abstract class System : Manipulator public abstract class System : Manipulator
{ {
public FilterBuilder FilterBuilder => World.FilterBuilder;
protected System(World world) : base(world) { } protected System(World world) : base(world) { }
public abstract void Update(); public abstract void Update();

View File

@ -119,7 +119,7 @@ public class Snapshot
{ {
if (!ArchetypeSnapshots.TryGetValue(archetype.Signature, out var archetypeSnapshot)) if (!ArchetypeSnapshots.TryGetValue(archetype.Signature, out var archetypeSnapshot))
{ {
archetypeSnapshot = new ArchetypeSnapshot(archetype.Signature); archetypeSnapshot = new ArchetypeSnapshot(archetype);
ArchetypeSnapshots.Add(archetype.Signature, archetypeSnapshot); ArchetypeSnapshots.Add(archetype.Signature, archetypeSnapshot);
} }
@ -130,7 +130,7 @@ public class Snapshot
{ {
if (!RelationSnapshots.TryGetValue(typeId, out var snapshot)) if (!RelationSnapshots.TryGetValue(typeId, out var snapshot))
{ {
snapshot = new RelationSnapshot(World.ElementSizes[typeId]); snapshot = new RelationSnapshot(relationStorage.relationDatas.ElementSize);
RelationSnapshots.Add(typeId, snapshot); RelationSnapshots.Add(typeId, snapshot);
} }
@ -144,15 +144,14 @@ public class Snapshot
public int Count => RowToEntity.Count; public int Count => RowToEntity.Count;
public ArchetypeSnapshot(ArchetypeSignature signature) public ArchetypeSnapshot(Archetype archetype)
{ {
ComponentColumns = new NativeArray[signature.Count]; ComponentColumns = new NativeArray[archetype.ComponentColumns.Length];
RowToEntity = new NativeArray<EntityId>(); RowToEntity = new NativeArray<EntityId>();
for (int i = 0; i < signature.Count; i += 1) for (int i = 0; i < archetype.ComponentColumns.Length; i += 1)
{ {
var componentId = signature[i]; ComponentColumns[i] = new NativeArray(archetype.ComponentColumns[i].ElementSize);
ComponentColumns[i] = new NativeArray(World.ElementSizes[componentId]);
} }
} }

View File

@ -3,14 +3,23 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using MoonTools.ECS.Collections; using MoonTools.ECS.Collections;
#if DEBUG
using System.Reflection;
#endif
namespace MoonTools.ECS.Rev2; namespace MoonTools.ECS.Rev2;
public class World : IDisposable public class World : IDisposable
{ {
// Get TypeId from a Type // Get TypeId from a Type
internal static Dictionary<Type, TypeId> TypeToId = new Dictionary<Type, TypeId>(); internal Dictionary<Type, TypeId> TypeToId = new Dictionary<Type, TypeId>();
#if DEBUG
private Dictionary<TypeId, Type> IdToType = new Dictionary<TypeId, Type>();
#endif
// Get element size from a TypeId // Get element size from a TypeId
internal static Dictionary<TypeId, int> ElementSizes = new Dictionary<TypeId, int>(); private Dictionary<TypeId, int> ElementSizes = new Dictionary<TypeId, int>();
// Lookup from ArchetypeSignature to Archetype // Lookup from ArchetypeSignature to Archetype
internal Dictionary<ArchetypeSignature, Archetype> ArchetypeIndex = new Dictionary<ArchetypeSignature, Archetype>(); internal Dictionary<ArchetypeSignature, Archetype> ArchetypeIndex = new Dictionary<ArchetypeSignature, Archetype>();
@ -31,11 +40,11 @@ public class World : IDisposable
new Dictionary<TypeId, MessageStorage>(); new Dictionary<TypeId, MessageStorage>();
// Filters with a single Include type for Singleton/Some implementation // Filters with a single Include type for Singleton/Some implementation
private Dictionary<TypeId, Filter> SingleTypeFilters = new Dictionary<TypeId, Filter>(); internal Dictionary<TypeId, Filter> SingleTypeFilters = new Dictionary<TypeId, Filter>();
// ID Management // Entity ID Management
internal IdAssigner EntityIdAssigner = new IdAssigner(); internal IdAssigner EntityIdAssigner = new IdAssigner();
internal IdAssigner TypeIdAssigner = new IdAssigner(); private IdAssigner TypeIdAssigner = new IdAssigner();
internal readonly Archetype EmptyArchetype; internal readonly Archetype EmptyArchetype;
@ -91,6 +100,10 @@ public class World : IDisposable
var typeId = new TypeId(TypeIdAssigner.Assign()); var typeId = new TypeId(TypeIdAssigner.Assign());
TypeToId.Add(typeof(T), typeId); TypeToId.Add(typeof(T), typeId);
ElementSizes.Add(typeId, Unsafe.SizeOf<T>()); ElementSizes.Add(typeId, Unsafe.SizeOf<T>());
#if DEBUG
IdToType.Add(typeId, typeof(T));
#endif
return typeId; return typeId;
} }
@ -544,6 +557,67 @@ public class World : IDisposable
} }
} }
// DEBUG
// NOTE: these methods are very inefficient
// they should only be used in debugging contexts!!
#if DEBUG
public ComponentEnumerator Debug_GetAllComponents(EntityId entity)
{
return new ComponentEnumerator(this, EntityIndex[entity]);
}
public Filter.EntityEnumerator Debug_GetEntities(Type componentType)
{
var typeId = TypeToId[componentType];
return SingleTypeFilters[typeId].Entities;
}
public IEnumerable<Type> Debug_SearchComponentType(string typeString)
{
foreach (var type in TypeToId.Keys)
{
if (type.ToString().ToLower().Contains(typeString.ToLower()))
{
yield return type;
}
}
}
public ref struct ComponentEnumerator
{
private World World;
private Record Record;
private int ComponentIndex;
public ComponentEnumerator GetEnumerator() => this;
internal ComponentEnumerator(
World world,
Record record
)
{
World = world;
Record = record;
ComponentIndex = -1;
}
public bool MoveNext()
{
ComponentIndex += 1;
return ComponentIndex < Record.Archetype.ComponentColumns.Length;
}
public unsafe object Current
{
get
{
var elt = Record.Archetype.ComponentColumns[ComponentIndex].Get(Record.Row);
return Pointer.Box(elt, World.IdToType[Record.Archetype.Signature[ComponentIndex]]);
}
}
}
#endif
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (!IsDisposed) if (!IsDisposed)