From 2a2d8efc5f8628df791fa37beaf68e13758b043a Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 1 Nov 2023 16:34:24 -0700 Subject: [PATCH] Debug methods on World --- src/Collections/NativeArrayUntyped.cs | 5 ++ src/Rev2/Compatibility/DebugSystem.cs | 17 ++++ .../Compatibility/EntityComponentReader.cs | 1 + src/Rev2/Compatibility/System.cs | 2 - src/Rev2/Snapshot.cs | 13 ++- src/Rev2/World.cs | 84 +++++++++++++++++-- 6 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 src/Rev2/Compatibility/DebugSystem.cs diff --git a/src/Collections/NativeArrayUntyped.cs b/src/Collections/NativeArrayUntyped.cs index 5cf2fd8..112860f 100644 --- a/src/Collections/NativeArrayUntyped.cs +++ b/src/Collections/NativeArrayUntyped.cs @@ -34,6 +34,11 @@ internal unsafe class NativeArray : IDisposable return ref ((T*) Elements)[i]; } + public void* Get(int i) + { + return (void*)(Elements + ElementSize * i); + } + private void Resize() { Capacity *= 2; diff --git a/src/Rev2/Compatibility/DebugSystem.cs b/src/Rev2/Compatibility/DebugSystem.cs new file mode 100644 index 0000000..8a477fe --- /dev/null +++ b/src/Rev2/Compatibility/DebugSystem.cs @@ -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 Debug_SearchComponentType(string typeString) => World.Debug_SearchComponentType(typeString); +} +#endif diff --git a/src/Rev2/Compatibility/EntityComponentReader.cs b/src/Rev2/Compatibility/EntityComponentReader.cs index 300d0e5..3b72177 100644 --- a/src/Rev2/Compatibility/EntityComponentReader.cs +++ b/src/Rev2/Compatibility/EntityComponentReader.cs @@ -3,6 +3,7 @@ public abstract class EntityComponentReader { protected World World; + public FilterBuilder FilterBuilder => World.FilterBuilder; protected EntityComponentReader(World world) { diff --git a/src/Rev2/Compatibility/System.cs b/src/Rev2/Compatibility/System.cs index 71233dc..09603b3 100644 --- a/src/Rev2/Compatibility/System.cs +++ b/src/Rev2/Compatibility/System.cs @@ -4,8 +4,6 @@ namespace MoonTools.ECS.Rev2.Compatibility; public abstract class System : Manipulator { - public FilterBuilder FilterBuilder => World.FilterBuilder; - protected System(World world) : base(world) { } public abstract void Update(); diff --git a/src/Rev2/Snapshot.cs b/src/Rev2/Snapshot.cs index 50dafa6..57e1313 100644 --- a/src/Rev2/Snapshot.cs +++ b/src/Rev2/Snapshot.cs @@ -119,7 +119,7 @@ public class Snapshot { if (!ArchetypeSnapshots.TryGetValue(archetype.Signature, out var archetypeSnapshot)) { - archetypeSnapshot = new ArchetypeSnapshot(archetype.Signature); + archetypeSnapshot = new ArchetypeSnapshot(archetype); ArchetypeSnapshots.Add(archetype.Signature, archetypeSnapshot); } @@ -130,7 +130,7 @@ public class Snapshot { if (!RelationSnapshots.TryGetValue(typeId, out var snapshot)) { - snapshot = new RelationSnapshot(World.ElementSizes[typeId]); + snapshot = new RelationSnapshot(relationStorage.relationDatas.ElementSize); RelationSnapshots.Add(typeId, snapshot); } @@ -144,15 +144,14 @@ public class Snapshot 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(); - 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(World.ElementSizes[componentId]); + ComponentColumns[i] = new NativeArray(archetype.ComponentColumns[i].ElementSize); } } diff --git a/src/Rev2/World.cs b/src/Rev2/World.cs index 76c0598..de6bd64 100644 --- a/src/Rev2/World.cs +++ b/src/Rev2/World.cs @@ -3,14 +3,23 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using MoonTools.ECS.Collections; +#if DEBUG +using System.Reflection; +#endif + namespace MoonTools.ECS.Rev2; public class World : IDisposable { // Get TypeId from a Type - internal static Dictionary TypeToId = new Dictionary(); + internal Dictionary TypeToId = new Dictionary(); + + #if DEBUG + private Dictionary IdToType = new Dictionary(); + #endif + // Get element size from a TypeId - internal static Dictionary ElementSizes = new Dictionary(); + private Dictionary ElementSizes = new Dictionary(); // Lookup from ArchetypeSignature to Archetype internal Dictionary ArchetypeIndex = new Dictionary(); @@ -31,11 +40,11 @@ public class World : IDisposable new Dictionary(); // Filters with a single Include type for Singleton/Some implementation - private Dictionary SingleTypeFilters = new Dictionary(); + internal Dictionary SingleTypeFilters = new Dictionary(); - // ID Management + // Entity ID Management internal IdAssigner EntityIdAssigner = new IdAssigner(); - internal IdAssigner TypeIdAssigner = new IdAssigner(); + private IdAssigner TypeIdAssigner = new IdAssigner(); internal readonly Archetype EmptyArchetype; @@ -91,6 +100,10 @@ public class World : IDisposable var typeId = new TypeId(TypeIdAssigner.Assign()); TypeToId.Add(typeof(T), typeId); ElementSizes.Add(typeId, Unsafe.SizeOf()); + + #if DEBUG + IdToType.Add(typeId, typeof(T)); + #endif 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 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) { if (!IsDisposed)