diff --git a/src/Immersion/Immersion.csproj b/src/Immersion/Immersion.csproj
index 75cfde8..21832d4 100644
--- a/src/Immersion/Immersion.csproj
+++ b/src/Immersion/Immersion.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Immersion/ManagedComponentTest.cs b/src/Immersion/ManagedComponentTest.cs
index 931717d..cb9e6c4 100644
--- a/src/Immersion/ManagedComponentTest.cs
+++ b/src/Immersion/ManagedComponentTest.cs
@@ -1,5 +1,6 @@
using System;
using gaemstone.ECS;
+using gaemstone.ECS.Utility;
namespace Immersion;
@@ -13,9 +14,9 @@ public partial class ManagedComponentTest
}
[System]
- public static void CreateLotsOfGarbageData(World world)
+ public static void CreateLotsOfGarbageData(World world)
{
- var game = world.LookupByPathOrThrow("/Game");
+ var game = world.LookupPathOrThrow("/Game");
game.Remove();
game.Set(new BigManagedData());
// This is to make sure the number of objects kept alive stays stable.
diff --git a/src/Immersion/ObserverTest.cs b/src/Immersion/ObserverTest.cs
index 89ecdb5..3940632 100644
--- a/src/Immersion/ObserverTest.cs
+++ b/src/Immersion/ObserverTest.cs
@@ -1,7 +1,7 @@
using System;
using gaemstone.ECS;
-using gaemstone.Flecs;
using static gaemstone.Bloxel.Components.CoreComponents;
+using static gaemstone.Flecs.Core;
namespace Immersion;
@@ -10,7 +10,7 @@ namespace Immersion;
[DependsOn]
public partial class ObserverTest
{
- [Observer]
+ [Observer]
[Expression("[in] Chunk, [none] (MeshHandle, *)")]
public static void DoObserver(in Chunk chunk)
=> Console.WriteLine($"Chunk at {chunk.Position} now has a Mesh!");
diff --git a/src/Immersion/Program.cs b/src/Immersion/Program.cs
index 4674b60..4a0109f 100644
--- a/src/Immersion/Program.cs
+++ b/src/Immersion/Program.cs
@@ -5,7 +5,6 @@ using System.Numerics;
using System.Threading;
using gaemstone;
using gaemstone.Bloxel;
-using gaemstone.ECS;
using gaemstone.Utility;
using Silk.NET.Windowing;
using static gaemstone.Bloxel.Components.CoreComponents;
@@ -20,15 +19,16 @@ var culture = CultureInfo.InvariantCulture;
Thread.CurrentThread.CurrentCulture = culture;
CultureInfo.DefaultThreadCurrentCulture = culture;
-var universe = new Universe();
-var game = universe.LookupByTypeOrThrow();
+var universe = new Universe();
+var world = universe.World;
+// TODO: Figure out a nice way to get rid of "compile errors" here.
universe.Modules.Register();
universe.Modules.Register();
var window = Window.Create(WindowOptions.Default with {
Title = "gæmstone",
- Size = new(1280, 720),
+ Size = new(1280, 720),
PreferredDepthBufferBits = 24,
});
window.Initialize();
@@ -57,19 +57,24 @@ universe.Modules.Register();
universe.Modules.Register();
universe.Modules.Register();
-game.Set(new Canvas(Silk.NET.OpenGL.ContextSourceExtensions.CreateOpenGL(window)));
-game.Set(new GameWindow(window));
+foreach (var module in universe.Modules)
+ if (!module.IsInitialized) throw new InvalidOperationException(
+ $"Module '{module.Entity.Path}' is not initialized");
-universe.New("MainCamera")
+// Initialize Canvas and GameWindow singletons with actual values.
+world.Entity().Set(new Canvas(Silk.NET.OpenGL.ContextSourceExtensions.CreateOpenGL(window)));
+world.Entity().Set(new GameWindow(window));
+
+world.New("MainCamera")
.Set(Camera.Default3D)
.Set((GlobalTransform)Matrix4x4.CreateTranslation(0.0F, 2.0F, 0.0F))
.Set(new CameraController { MouseSensitivity = 12.0F })
.Build();
-var heartMesh = universe.New("/Immersion/Resources/heart.glb").Add().Build();
-var swordMesh = universe.New("/Immersion/Resources/sword.glb").Add().Build();
+var heartMesh = world.New("/Immersion/Resources/heart.glb").Add().Build();
+var swordMesh = world.New("/Immersion/Resources/sword.glb").Add().Build();
-var entities = universe.New("Entities").Build();
+var entities = world.New("Entities").Build();
var rnd = new Random();
for (var x = -12; x <= 12; x++)
for (var z = -12; z <= 12; z++) {
@@ -86,13 +91,13 @@ universe.Modules.Register();
universe.Modules.Register();
universe.Modules.Register();
-var texture = universe.New("/Immersion/Resources/terrain.png").Add().Build();
+var texture = world.New("/Immersion/Resources/terrain.png").Add().Build();
-var stone = universe.New("Stone").Set(TextureCoords4.FromGrid(4, 4, 1, 0)).Build();
-var dirt = universe.New("Dirt" ).Set(TextureCoords4.FromGrid(4, 4, 2, 0)).Build();
-var grass = universe.New("Grass").Set(TextureCoords4.FromGrid(4, 4, 3, 0)).Build();
+var stone = world.New("Stone").Set(TextureCoords4.FromGrid(4, 4, 1, 0)).Build();
+var dirt = world.New("Dirt" ).Set(TextureCoords4.FromGrid(4, 4, 2, 0)).Build();
+var grass = world.New("Grass").Set(TextureCoords4.FromGrid(4, 4, 3, 0)).Build();
-var chunks = universe.New("Chunks").Build();
+var chunks = world.New("Chunks").Build();
var sizeH = 4; var sizeY = 2;
for (var cx = -sizeH; cx < sizeH; cx++)
for (var cy = -sizeY; cy < sizeY; cy++)
@@ -110,12 +115,12 @@ for (var cz = -sizeH; cz < sizeH; cz++) {
// universe.Modules.Register();
var stopwatch = Stopwatch.StartNew();
-var minFrameTime = TimeSpan.FromSeconds(1) / 30;
+var minFrameTime = TimeSpan.FromSeconds(1) / 60;
window.Run(() => {
var delta = stopwatch.Elapsed;
stopwatch.Restart();
- if (!universe.Progress(delta))
+ if (!world.Progress(delta))
window.Close();
var requiredTime = stopwatch.Elapsed;
diff --git a/src/gaemstone.Bloxel/ChunkPaletteStorage.cs b/src/gaemstone.Bloxel/ChunkPaletteStorage.cs
index 5e29d98..0dda8ad 100644
--- a/src/gaemstone.Bloxel/ChunkPaletteStorage.cs
+++ b/src/gaemstone.Bloxel/ChunkPaletteStorage.cs
@@ -168,9 +168,9 @@ public class ChunkPaletteStorage
}
private int GetIndex(int x, int y, int z)
- => (x |
- y << Constants.ChunkBitShift |
- z << (Constants.ChunkBitShift * 2)) * _indicesLength;
+ => (x | y << Constants.ChunkBitShift
+ | z << (Constants.ChunkBitShift * 2))
+ * _indicesLength;
private struct PaletteEntry
diff --git a/src/gaemstone.Bloxel/Client/Systems/ChunkMeshGenerator.cs b/src/gaemstone.Bloxel/Client/Systems/ChunkMeshGenerator.cs
index 7d9b9c3..5fffbcc 100644
--- a/src/gaemstone.Bloxel/Client/Systems/ChunkMeshGenerator.cs
+++ b/src/gaemstone.Bloxel/Client/Systems/ChunkMeshGenerator.cs
@@ -2,7 +2,9 @@ using System;
using System.Numerics;
using gaemstone.Client.Systems;
using gaemstone.ECS;
+using Silk.NET.OpenGL;
using static gaemstone.Bloxel.Components.CoreComponents;
+using static gaemstone.Bloxel.Systems.BasicWorldGenerator;
using static gaemstone.Client.Components.RenderingComponents;
using static gaemstone.Client.Components.ResourceComponents;
using static gaemstone.Client.Systems.Windowing;
@@ -10,6 +12,11 @@ using static gaemstone.Client.Systems.Windowing;
namespace gaemstone.Bloxel.Client.Systems;
[Module]
+[DependsOn]
+[DependsOn]
+[DependsOn]
+[DependsOn]
+[DependsOn]
public partial class ChunkMeshGenerator
{
private const int StartingCapacity = 1024;
@@ -20,29 +27,32 @@ public partial class ChunkMeshGenerator
new Vector3[]{ new(1,1,0), new(0,1,0), new(0,1,1), new(1,1,1) }, // Up (+Y)
new Vector3[]{ new(1,0,1), new(0,0,1), new(0,0,0), new(1,0,0) }, // Down (-Y)
new Vector3[]{ new(0,1,1), new(0,0,1), new(1,0,1), new(1,1,1) }, // South (+Z)
- new Vector3[]{ new(1,1,0), new(1,0,0), new(0,0,0), new(0,1,0) } // North (-Z)
+ new Vector3[]{ new(1,1,0), new(1,0,0), new(0,0,0), new(0,1,0) }, // North (-Z)
};
private static readonly int[] TriangleIndices
= { 0, 1, 3, 1, 2, 3 };
-
- private ushort[] _indices = new ushort[StartingCapacity];
- private Vector3[] _vertices = new Vector3[StartingCapacity];
- private Vector3[] _normals = new Vector3[StartingCapacity];
- private Vector2[] _uvs = new Vector2[StartingCapacity];
+ // TODO: Turn these into a component on the module.
+ private static ushort [] _indices = new ushort [StartingCapacity];
+ private static Vector3[] _vertices = new Vector3[StartingCapacity];
+ private static Vector3[] _normals = new Vector3[StartingCapacity];
+ private static Vector2[] _uvs = new Vector2[StartingCapacity];
[System]
- [Expression("[in] Chunk, ChunkStoreBlocks, HasBasicWorldGeneration, !(Mesh, *)")]
- public void GenerateChunkMeshes(Universe universe, EntityRef entity,
- in Chunk chunk, ChunkStoreBlocks blocks)
+ public static void GenerateChunkMeshes(
+ World world, Canvas canvas,
+ Entity entity, in Chunk chunk, ChunkStoreBlocks blocks,
+ Has _1, Not _2)
{
- if (Generate(universe, chunk.Position, blocks) is MeshHandle handle)
- entity.Add(entity.NewChild("Mesh").Set(handle).Build());
- else entity.Delete();
+ var result = Generate(world, canvas.GL, chunk.Position, blocks);
+ if (result is MeshHandle handle) {
+ var mesh = entity.NewChild("Mesh").Set(handle).Build();
+ entity.Add(mesh);
+ } else entity.Delete();
}
- public MeshHandle? Generate(Universe universe,
+ public static MeshHandle? Generate(World world, GL GL,
ChunkPos chunkPos, ChunkStoreBlocks centerBlocks)
{
// TODO: We'll need a way to get neighbors again.
@@ -59,47 +69,45 @@ public partial class ChunkMeshGenerator
var indexCount = 0;
var vertexCount = 0;
for (var x = 0; x < 16; x++)
- for (var y = 0; y < 16; y++)
- for (var z = 0; z < 16; z++) {
- var block = universe.LookupAlive(centerBlocks[x, y, z]);
- if (block == null) continue;
-
- var blockVertex = new Vector3(x, y, z);
- var textureCell = block.GetOrThrow();
-
- foreach (var facing in BlockFacings.All) {
- if (!IsNeighborEmpty(storages, x, y, z, facing)) continue;
-
- if (_indices.Length <= indexCount + 6)
- Array.Resize(ref _indices, _indices.Length << 1);
- if (_vertices.Length <= vertexCount + 4) {
- Array.Resize(ref _vertices, _vertices.Length << 1);
- Array.Resize(ref _normals , _vertices.Length << 1);
- Array.Resize(ref _uvs , _vertices.Length << 1);
- }
-
- for (var i = 0; i < TriangleIndices.Length; i++)
- _indices[indexCount++] = (ushort)(vertexCount + TriangleIndices[i]);
-
- var normal = facing.ToVector3();
- for (var i = 0; i < 4; i++) {
- var offset = OffsetPerFacing[(int)facing][i];
- _vertices[vertexCount] = blockVertex + offset;
- _normals[vertexCount] = normal;
- _uvs[vertexCount] = i switch {
- 0 => textureCell.TopLeft,
- 1 => textureCell.BottomLeft,
- 2 => textureCell.BottomRight,
- 3 => textureCell.TopRight,
- _ => throw new InvalidOperationException()
- };
- vertexCount++;
+ for (var y = 0; y < 16; y++)
+ for (var z = 0; z < 16; z++) {
+ var maybeBlock = world.LookupAliveOrNull(centerBlocks[x, y, z]);
+ if (maybeBlock is not Entity block) continue;
+
+ var blockVertex = new Vector3(x, y, z);
+ var textureCell = block.GetOrThrow();
+
+ foreach (var facing in BlockFacings.All) {
+ if (!IsNeighborEmpty(storages, x, y, z, facing)) continue;
+
+ if (_indices.Length <= indexCount + 6)
+ Array.Resize(ref _indices, _indices.Length << 1);
+ if (_vertices.Length <= vertexCount + 4) {
+ Array.Resize(ref _vertices, _vertices.Length << 1);
+ Array.Resize(ref _normals , _vertices.Length << 1);
+ Array.Resize(ref _uvs , _vertices.Length << 1);
+ }
+
+ for (var i = 0; i < TriangleIndices.Length; i++)
+ _indices[indexCount++] = (ushort)(vertexCount + TriangleIndices[i]);
+
+ var normal = facing.ToVector3();
+ for (var i = 0; i < 4; i++) {
+ var offset = OffsetPerFacing[(int)facing][i];
+ _vertices[vertexCount] = blockVertex + offset;
+ _normals[vertexCount] = normal;
+ _uvs[vertexCount] = i switch {
+ 0 => textureCell.TopLeft,
+ 1 => textureCell.BottomLeft,
+ 2 => textureCell.BottomRight,
+ 3 => textureCell.TopRight,
+ _ => throw new InvalidOperationException()
+ };
+ vertexCount++;
+ }
+ }
}
- }
- }
- // TODO: Should dynamically generating meshes require getting GL this way?
- var GL = universe.LookupByTypeOrThrow().GetOrThrow().GL;
return (indexCount > 0)
? MeshManager.Create(GL,
_indices.AsSpan(0, indexCount), _vertices.AsSpan(0, vertexCount),
diff --git a/src/gaemstone.Bloxel/Systems/BasicWorldGenerator.cs b/src/gaemstone.Bloxel/Systems/BasicWorldGenerator.cs
index 398032b..f7b7eeb 100644
--- a/src/gaemstone.Bloxel/Systems/BasicWorldGenerator.cs
+++ b/src/gaemstone.Bloxel/Systems/BasicWorldGenerator.cs
@@ -6,14 +6,15 @@ using static gaemstone.Bloxel.Constants;
namespace gaemstone.Bloxel.Systems;
-[Public, Module]
+[Module]
[DependsOn]
public partial class BasicWorldGenerator
{
- private readonly FastNoiseLite _noise;
- private readonly Random _rnd = new();
+ // TODO: Turn these into a component on the module.
+ private static readonly FastNoiseLite _noise;
+ private static readonly Random _rnd = new();
- public BasicWorldGenerator()
+ static BasicWorldGenerator()
{
_noise = new(new Random().Next());
_noise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
@@ -23,16 +24,17 @@ public partial class BasicWorldGenerator
}
[Tag]
- public struct HasBasicWorldGeneration { }
+ public struct BasicWorldGenerationDone { }
[System]
- public void Populate(World world, EntityRef entity,
+ public static void Populate(
+ World world, Entity entity,
in Chunk chunk, ChunkStoreBlocks blocks,
- [Not] HasBasicWorldGeneration _)
+ Not _)
{
- var stone = world.LookupByPathOrThrow("Stone");
- var dirt = world.LookupByPathOrThrow("Dirt");
- var grass = world.LookupByPathOrThrow("Grass");
+ var stone = world.LookupPathOrThrow("Stone");
+ var dirt = world.LookupPathOrThrow("Dirt");
+ var grass = world.LookupPathOrThrow("Grass");
for (var localX = 0; localX < ChunkLength; localX++)
for (var localY = 0; localY < ChunkLength; localY++)
for (var localZ = 0; localZ < ChunkLength; localZ++) {
@@ -43,6 +45,6 @@ public partial class BasicWorldGenerator
if (_noise.GetNoise(globalX, globalY, globalZ) > bias)
blocks[localX, localY, localZ] = _rnd.Pick(stone, dirt, grass);
}
- entity.Add();
+ entity.Add();
}
}
diff --git a/src/gaemstone.Bloxel/gaemstone.Bloxel.csproj b/src/gaemstone.Bloxel/gaemstone.Bloxel.csproj
index 26ad828..184ab65 100644
--- a/src/gaemstone.Bloxel/gaemstone.Bloxel.csproj
+++ b/src/gaemstone.Bloxel/gaemstone.Bloxel.csproj
@@ -5,6 +5,7 @@
net7.0
disable
enable
+ true
diff --git a/src/gaemstone.Client/Systems/EntityInspector.cs b/src/gaemstone.Client/Systems/EntityInspector.cs
index 622ec60..914c000 100644
--- a/src/gaemstone.Client/Systems/EntityInspector.cs
+++ b/src/gaemstone.Client/Systems/EntityInspector.cs
@@ -7,7 +7,6 @@ using gaemstone.ECS;
using gaemstone.Flecs;
using ImGuiNET;
using static gaemstone.Client.Systems.ImGuiManager;
-using static gaemstone.Flecs.Core;
using Icon = gaemstone.Client.Utility.ForkAwesome;
using ImGuiInternal = ImGuiNET.Internal.ImGui;
@@ -22,7 +21,7 @@ public partial class EntityInspector
public struct InspectorWindow { }
[Relation, Exclusive]
- [Add]
+ [Add]
public struct Selected { }
[Tag]
@@ -44,17 +43,16 @@ public partial class EntityInspector
public Entry? Prev { get; set; }
public Entry? Next { get; set; }
- public Entry(EntityRef entity, Entry? prev, Entry? next)
+ public Entry(Entity entity, EntityPath path, Entry? prev, Entry? next)
{
Entity = entity;
- Path = entity.GetFullPath();
+ Path = path;
if ((Prev = prev) != null) Prev.Next = this;
if ((Next = next) != null) Next.Prev = this;
}
}
}
-
[Component]
public struct DocPriority { public float Value; }
@@ -64,10 +62,10 @@ public partial class EntityInspector
private const string DefaultWindowTitle = "Inspector Gadget";
- public void Initialize(EntityRef module)
+ public static void Initialize(Entity module)
{
void SetDocInfo(string path, float priority, string icon, float r, float g, float b)
- => module.World.LookupByPathOrThrow(path)
+ => module.World.LookupPathOrThrow(path)
.Add()
.Set(new DocPriority { Value = priority })
.Set(new DocIcon { Value = icon[0] })
@@ -78,17 +76,18 @@ public partial class EntityInspector
SetDocInfo("/flecs/core/Observer" , 2 , Icon.Eye , 1.0f, 0.8f, 0.8f);
SetDocInfo("/gaemstone/Doc/Relation" , 3 , Icon.ShareAlt , 0.7f, 1.0f, 0.8f);
SetDocInfo("/flecs/core/Component" , 4 , Icon.PencilSquare , 0.6f, 0.6f, 1.0f);
+ // TODO: Handle tags like Flecs does.
SetDocInfo("/flecs/core/Tag" , 5 , Icon.Tag , 0.7f, 0.8f, 1.0f);
SetDocInfo("/flecs/core/Prefab" , 6 , Icon.Cube , 0.9f, 0.8f, 1.0f);
}
[System]
- public void ShowUIButton(World world, ImGuiData _)
+ public static void ShowUIButton(World world, ImGuiData _)
{
var hasAnyInspector = false;
- var inspectorWindow = world.LookupByTypeOrThrow();
- foreach (var entity in Iterator.FromTerm(world, new(inspectorWindow)))
+ var inspectorWindow = world.Entity();
+ foreach (var entity in Iterator.FromTerm(world, new(inspectorWindow)))
{ hasAnyInspector = true; break; }
if (ImGuiUtility.UIButton(0, Icon.Search, DefaultWindowTitle, hasAnyInspector))
@@ -96,7 +95,7 @@ public partial class EntityInspector
}
[System]
- public void ShowInspectorWindow(EntityRef window, InspectorWindow _, History? history)
+ public static void ShowInspectorWindow(Entity window, InspectorWindow _, History? history)
{
var isOpen = true;
var fontSize = ImGui.GetFontSize();
@@ -105,7 +104,7 @@ public partial class EntityInspector
ImGui.SetNextWindowSize(new(fontSize * 40, fontSize * 25), ImGuiCond.Appearing);
ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[1]);
var title = window.GetDocName() ?? DefaultWindowTitle;
- if (ImGui.Begin($"{Icon.Search} {title}###{window.Id}",
+ if (ImGui.Begin($"{Icon.Search} {title}###{window.NumericId}",
ref isOpen, ImGuiWindowFlags.NoScrollbar)) {
ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[0]);
@@ -121,7 +120,7 @@ public partial class EntityInspector
ExplorerView(window, history, selected);
ImGui.EndChild();
- void Tab(string name, Action contentMethod)
+ void Tab(string name, Action, History?, Entity?> contentMethod)
{
if (!ImGui.BeginTabItem(name)) return;
ImGui.BeginChild($"{name}Tab", new(-float.Epsilon, -float.Epsilon));
@@ -150,16 +149,14 @@ public partial class EntityInspector
if (!isOpen) window.Delete();
}
- [Observer]
- public void ClearStorageOnRemove(EntityRef _1, InspectorWindow _2)
+ [Observer]
+ public static void ClearStorageOnRemove(Entity _1, InspectorWindow _2)
{
// TODO: Clear out settings store for the window.
}
- private void ActionBarAndPath(EntityRef window, History? history, EntityRef? selected)
+ private static void ActionBarAndPath(Entity window, History? history, Entity? selected)
{
- var world = window.World;
-
static bool IconButtonWithToolTip(string icon, string tooltip, bool enabled = true) {
if (!enabled) ImGui.BeginDisabled();
var clicked = ImGui.Button(icon);
@@ -176,9 +173,9 @@ public partial class EntityInspector
ImGui.TableSetupColumn("Entity", ImGuiTableColumnFlags.WidthFixed);
ImGui.TableNextColumn();
- var hasExpanded = window.Has();
+ var hasExpanded = window.Has();
if (IconButtonWithToolTip(Icon.Outdent, "Collapse all items in the Explorer View", hasExpanded))
- window.Remove();
+ window.Remove();
if (history != null) {
var hasPrev = ((selected != null) ? history.Current?.Prev : history.Current) != null;
@@ -201,9 +198,7 @@ public partial class EntityInspector
ImGui.TableNextColumn();
if (IconButtonWithToolTip(Icon.PlusCircle, "Create a new child entity", (selected != null)))
- // FIXME: Replace this once Flecs has been fixed.
- SetSelected(window, history, world.New().Build().ChildOf(selected));
- // SelectAndScrollTo(windowEntity, windowData, selected!.NewChild().Build(), selected);
+ SetSelected(window, history, selected?.NewChild().Build());
ImGui.SameLine();
if (IconButtonWithToolTip(Icon.Pencil, "Rename the current entity", false && (selected != null)))
@@ -214,26 +209,26 @@ public partial class EntityInspector
var icon = !isDisabled ? Icon.BellSlash : Icon.Bell;
var tooltip = $"{(!isDisabled ? "Disable" : "Enable")} the current entity";
if (IconButtonWithToolTip(icon, tooltip, (selected != null)))
- { if (isDisabled) selected!.Enable(); else selected!.Disable(); }
+ { if (isDisabled) selected?.Enable(); else selected?.Disable(); }
ImGui.SameLine();
if (IconButtonWithToolTip(Icon.Trash, "Delete the current entity", (selected != null))) {
// TODO: Delete history for deleted entity?
- SetSelected(window, history, selected!.Parent);
- selected.Delete(); // TODO: Confirmation dialog?
+ SetSelected(window, history, selected?.Parent);
+ selected?.Delete(); // TODO: Confirmation dialog?
}
ImGui.EndTable();
ImGui.PopStyleVar();
}
- private void PathInput(EntityRef window, History? history, EntityRef? selected, float availableWidth)
+ private static void PathInput(Entity window, History? history, Entity? selected, float availableWidth)
{
var style = ImGui.GetStyle();
ImGui.AlignTextToFramePadding();
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1, style.ItemSpacing.Y));
- var path = selected?.GetFullPath() ?? null;
+ var path = selected?.Path ?? null;
if (path != null) {
var visiblePath = path.GetParts().ToList();
@@ -261,8 +256,10 @@ public partial class EntityInspector
ImGui.EndDisabled();
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
ImGui.SetTooltip(path[1..(numHiddenItems+2)].ToString());
- } else if (ImGui.Button(visiblePath[i]))
- SetSelected(window, history, window.World.LookupByPath(path[..(actualIndex+1)]));
+ } else if (ImGui.Button(visiblePath[i])) {
+ var toSelect = window.World.LookupPathOrNull(path[..(actualIndex + 1)]);
+ SetSelected(window, history, toSelect);
+ }
ImGui.SameLine();
}
}
@@ -275,12 +272,27 @@ public partial class EntityInspector
ImGui.PopStyleVar();
}
- private class ExplorerEntry
- : IComparable
+ private interface IExplorerEntry
+ : IComparable
{
- private readonly EntityInspector _module;
+ public Entity Entity { get; }
+ public int NumChildren { get; }
+ public bool HasChildren { get; }
+ public bool IsExpanded { get; }
+ public bool IsDisabled { get; }
+
+ public string? Name { get; }
+ public string? DocName { get; }
- public EntityRef Entity { get; }
+ public float Priority { get; }
+ public Entity? Type { get; }
+ }
+
+ private class ExplorerEntry
+ : IExplorerEntry
+ {
+ public Entity Entity { get; }
+ Entity IExplorerEntry.Entity => Entity;
public int NumChildren { get; }
public bool HasChildren => (NumChildren > 0);
public bool IsExpanded { get; }
@@ -292,65 +304,67 @@ public partial class EntityInspector
public string? DocName => (_docNameCached++ > 0) ? _docName : _docName = Entity.GetDocName();
private float? _priority;
- private EntityRef? _type;
- public float Priority => EnsureTypeCached()._priority!.Value;
- public EntityRef? Type => EnsureTypeCached()._type;
+ private Entity? _type;
+ public float Priority => EnsureTypeCached()._priority!.Value;
+ public Entity? Type => EnsureTypeCached()._type;
- public ExplorerEntry(EntityInspector module, EntityRef entity,
- int numChildren, bool isExpanded, bool isDisabled)
+ public ExplorerEntry(Entity entity,
+ int numChildren, bool isExpanded, bool isDisabled)
{
- _module = module;
Entity = entity;
NumChildren = numChildren;
IsExpanded = (isExpanded && HasChildren);
IsDisabled = isDisabled;
}
- private ExplorerEntry EnsureTypeCached()
+ private ExplorerEntry EnsureTypeCached()
{
if (_priority != null) return this;
- (_type, _priority) = _module.FindDisplayType(Entity);
+ (_type, _priority) = FindDisplayType(Entity);
return this;
}
- public int CompareTo(ExplorerEntry? other)
+ public int CompareTo(IExplorerEntry? other)
{
if (other == null) return -1;
+
return Compare(Priority, other.Priority)
?? Compare(Name, other.Name)
?? Compare(DocName, other.DocName)
- ?? Compare(Entity.Id, other.Entity.Id)
+ ?? Compare(Entity.NumericId, other.Entity.NumericId)
?? 0;
- static int? Compare(T x, T y) {
+
+ static int? Compare(TCompare x, TCompare y)
+ {
if (x is null) { if (y is null) return null; else return 1; }
else if (y is null) return -1;
- var result = Comparer.Default.Compare(x, y);
+ var result = Comparer.Default.Compare(x, y);
return (result != 0) ? result : null;
}
}
}
- private void ExplorerView(EntityRef window, History? history, EntityRef? selected)
+ private static void ExplorerView(Entity window, History? history, Entity? selected)
{
// For some reason, the analyzer thinks world can be
// nullable, so let's be explicit about the type here.
- World world = window.World;
+ var world = window.World;
- var Wildcard = world.LookupByTypeOrThrow().Entity;
- var Any = world.LookupByTypeOrThrow().Entity;
- var This = world.LookupByTypeOrThrow().Entity;
- var Var = world.LookupByTypeOrThrow().Entity;
+ var Wildcard = world.Entity().Value;
+ var Any = world.Entity().Value;
+ var This = world.Entity().Value;
+ var Variable = world.Entity().Value;
bool IsSpecialEntity(Entity entity)
=> (entity == Wildcard) || (entity == Any)
- || (entity == This) || (entity == Var);
-
- var expId = world.LookupByTypeOrThrow().Id;
- List GetEntries(Entity? parent) {
- var result = new List();
- using var rule = new Rule(world, new(
- $"(ChildOf, {parent?.Id ?? 0})" // Must be child of parent, or root entity.
- + $",?{expId}({window.Id}, $This)" // Whether entity is expanded in explorer view.
- + $",?Disabled" // Don't filter out disabled entities.
+ || (entity == This) || (entity == Variable);
+
+ var expId = world.Entity().NumericId;
+ List GetEntries(Entity? parent) {
+ var result = new List();
+ using var rule = new Rule(world, new(
+ $"(ChildOf, {parent?.NumericId ?? 0})" // Must be child of parent, or root entity.
+ + $",?{expId}({window.NumericId}, $This)" // Whether entity is expanded in explorer view.
+ + $",?Disabled" // Don't filter out disabled entities.
));
foreach (var iter in rule.Iter()) {
var isExpanded = iter.FieldIsSet(2);
@@ -358,8 +372,8 @@ public partial class EntityInspector
for (var i = 0; i < iter.Count; i++) {
var entity = iter.Entity(i);
var count = IsSpecialEntity(entity) ? 0
- : IdRef.Pair(entity).Count;
- result.Add(new(this, entity, count, isExpanded, isDisabled));
+ : world.Pair(entity).Count;
+ result.Add(new ExplorerEntry(entity, count, isExpanded, isDisabled));
}
}
return result;
@@ -373,8 +387,8 @@ public partial class EntityInspector
float GetIndent(int depth) => depth * (nodeHeight + spacingX);
- bool RenderNode(ExplorerEntry entry, int? depth) {
- var entity = entry.Entity;
+ bool RenderNode(IExplorerEntry entry, int? depth) {
+ var entity = Entity.GetOrThrow(world, entry.Entity);
var startY = ImGui.GetCursorPosY();
var isVisible = ImGui.IsRectVisible(new(nodeHeight, nodeHeight));
var isSelected = (entity == selected);
@@ -384,7 +398,7 @@ public partial class EntityInspector
// Button for expanding the child entries.
if (entry.HasChildren && !entry.IsExpanded) {
ImGui.SetCursorPosX(GetIndent(depth!.Value));
- if (ImGui.Button($"##Expand{entity.Id}", new(nodeHeight)))
+ if (ImGui.Button($"##Expand{entity.NumericId}", new(nodeHeight)))
window.Add(entity);
}
@@ -427,7 +441,7 @@ public partial class EntityInspector
var fullHeight = ImGui.GetCursorPosY() - startY - spacingY;
ImGui.SetCursorPos(new(GetIndent(depth!.Value), startY));
- if (ImGui.Button($"##Expand{entity.Id}", new(nodeHeight, fullHeight)))
+ if (ImGui.Button($"##Expand{entity.NumericId}", new(nodeHeight, fullHeight)))
window.Remove(entity);
return true;
@@ -439,33 +453,33 @@ public partial class EntityInspector
RenderNode(child, 0);
}
- private void ComponentsTab(EntityRef window, History? history, EntityRef? selected)
+ private static void ComponentsTab(Entity window, History? history, Entity? sel)
{
- if (selected == null) return;
- var ChildOf = window.World.LookupByTypeOrThrow();
+ if (sel is not Entity selected) return;
+ var ChildOf = window.World.Entity();
foreach (var id in selected.Type) {
// Hide ChildOf relations, as they are visible in the explorer.
- if (id.IsPair && (id.Id.RelationUnsafe == ChildOf)) continue;
+ if (id.IsPair && (id.Value.RelationUnsafe == ChildOf)) continue;
RenderIdentifier(window, history, id);
}
}
- private void ReferencesTab(EntityRef window, History? history, EntityRef? selected)
+ private static void ReferencesTab(Entity window, History? history, Entity? sel)
{
- if (selected == null) return;
+ if (sel is not Entity selected) return;
var world = window.World;
- var ChildOf = world.LookupByTypeOrThrow();
- var Wildcard = world.LookupByTypeOrThrow();
+ var ChildOf = world.Entity();
+ var Wildcard = world.Entity();
- if (ImGui.CollapsingHeader($"As {Icon.Tag} Entity", ImGuiTreeNodeFlags.DefaultOpen))
- foreach (var iter in Iterator.FromTerm(world, new(selected)))
+ if (ImGui.CollapsingHeader($"As {Icon.Tag} Component", ImGuiTreeNodeFlags.DefaultOpen))
+ foreach (var iter in Iterator.FromTerm(world, new(selected)))
for (var i = 0; i < iter.Count; i++)
RenderEntity(window, history, iter.Entity(i));
if (ImGui.CollapsingHeader($"As {Icon.ShareAlt} Relation", ImGuiTreeNodeFlags.DefaultOpen))
- foreach (var iter in Iterator.FromTerm(world, new(selected, Wildcard))) {
+ foreach (var iter in Iterator.FromTerm(world, new(selected, Wildcard))) {
var id = iter.FieldId(1);
- if (id.AsPair() is not (EntityRef relation, EntityRef target)) throw new InvalidOperationException();
+ if (id.AsPair() is not (Entity relation, Entity target)) throw new InvalidOperationException();
if (relation == ChildOf) continue; // Hide ChildOf relations.
for (var i = 0; i < iter.Count; i++) {
@@ -476,9 +490,9 @@ public partial class EntityInspector
}
if (ImGui.CollapsingHeader($"As {Icon.Bullseye} Target", ImGuiTreeNodeFlags.DefaultOpen))
- foreach (var iter in Iterator.FromTerm(world, new(Wildcard, selected))) {
+ foreach (var iter in Iterator.FromTerm(world, new(Wildcard, selected))) {
var id = iter.FieldId(1);
- if (id.AsPair() is not (EntityRef relation, EntityRef target)) throw new InvalidOperationException();
+ if (id.AsPair() is not (Entity relation, Entity target)) throw new InvalidOperationException();
if (relation == ChildOf) continue; // Hide ChildOf relations.
for (var i = 0; i < iter.Count; i++) {
@@ -489,7 +503,7 @@ public partial class EntityInspector
}
}
- private void DocumentationTab(EntityRef _1, History? _2, EntityRef? selected)
+ private static void DocumentationTab(Entity _1, History? _2, Entity? selected)
{
var hasSelected = (selected != null);
@@ -515,7 +529,7 @@ public partial class EntityInspector
if (!hasSelected) ImGui.BeginDisabled();
var name = selected?.GetDocName(false) ?? "";
if (ImGui.InputText("##Name", ref name, 256))
- selected!.SetDocName((name.Length > 0) ? name : null);
+ selected?.SetDocName((name.Length > 0) ? name : null);
if (!hasSelected) ImGui.EndDisabled();
Column($"{Icon.Comment} Description",
@@ -523,7 +537,7 @@ public partial class EntityInspector
if (!hasSelected) ImGui.BeginDisabled();
var brief = selected?.GetDocBrief() ?? "";
if (ImGui.InputText("##Brief", ref brief, 256))
- selected!.SetDocBrief((brief.Length > 0) ? brief : null);
+ selected?.SetDocBrief((brief.Length > 0) ? brief : null);
if (!hasSelected) ImGui.EndDisabled();
Column($"{Icon.FileText} Documentation", """
@@ -539,7 +553,7 @@ public partial class EntityInspector
// TODO: Needs wordwrap.
if (ImGui.InputTextMultiline("##Detail", ref detail, 2048,
new(-float.Epsilon, Math.Max(minHeight, availHeight))))
- selected!.SetDocDetail((detail.Length > 0) ? detail : null);
+ selected?.SetDocDetail((detail.Length > 0) ? detail : null);
if (!hasSelected) ImGui.EndDisabled();
Column($"{Icon.Link} Link", """
@@ -549,7 +563,7 @@ public partial class EntityInspector
if (!hasSelected) ImGui.BeginDisabled();
var link = selected?.GetDocLink() ?? "";
if (ImGui.InputText("##Link", ref link, 256))
- selected!.SetDocLink((link.Length > 0) ? link : null);
+ selected?.SetDocLink((link.Length > 0) ? link : null);
if (!hasSelected) ImGui.EndDisabled();
Column($"{Icon.PaintBrush} Color", """
@@ -561,15 +575,15 @@ public partial class EntityInspector
var hasColor = (maybeColor != null);
var color = maybeColor ?? Color.White;
if (ImGui.Checkbox("##HasColor", ref hasColor)) {
- if (hasColor) selected!.SetDocColor(color.ToHexString());
- else selected!.SetDocColor(null);
+ if (hasColor) selected?.SetDocColor(color.ToHexString());
+ else selected?.SetDocColor(null);
}
ImGui.SameLine();
if (!hasColor) ImGui.BeginDisabled();
ImGui.SetNextItemWidth(-float.Epsilon);
var colorVec = color.ToVector3();
if (ImGui.ColorEdit3("##Color", ref colorVec))
- selected!.SetDocColor(Color.FromRGB(colorVec).ToHexString());
+ selected?.SetDocColor(Color.FromRGB(colorVec).ToHexString());
if (!hasColor) ImGui.EndDisabled();
if (!hasSelected) ImGui.EndDisabled();
@@ -582,71 +596,71 @@ public partial class EntityInspector
// == Utility Functions ==
// =======================
- private EntityRef NewEntityInspectorWindow(World world)
+ private static Entity NewEntityInspectorWindow(World world)
=> world.New().Add().Set(new History())
.Build().SetDocName(DefaultWindowTitle);
- private void SetSelected(
- EntityRef window, // The InspectorWindow entity.
+ private static void SetSelected(
+ Entity window, // The InspectorWindow entity.
History? history, // InspectorWindow's History component, null if it shouldn't be changed.
- EntityRef? entity, // Entity to set as selected or null to unset.
+ Entity? entity, // Entity to set as selected or null to unset.
bool scrollTo = true) // Should entity be scrolled to in the explorer view?
{
- if (entity != null) window.Add(entity);
- else window.Remove();
+ if (entity is Entity e1) window.Add(e1);
+ else window.Remove();
- for (var parent = entity?.Parent; parent != null; parent = parent.Parent)
+ for (var p = entity?.Parent; p is Entity parent; p = parent.Parent)
window.Add(parent);
if ((entity != null) && scrollTo)
window.Add();
if (history != null) {
- if (entity != null) history.Current = new History.Entry(entity, history.Current, null);
+ if (entity is Entity e2) history.Current = new(e2, e2.Path, history.Current, null);
else if (history.Current is History.Entry entry) entry.Next = null;
}
}
- private void GoToPrevious(EntityRef window, History history, EntityRef? selected)
+ private static void GoToPrevious(Entity window, History history, Entity? selected)
{
if (selected != null) {
if (history.Current?.Prev == null) return;
history.Current = history.Current.Prev;
} else if (history.Current == null) return;
- var entity = EntityRef.CreateOrNull(window.World, history.Current.Entity);
+ var entity = Entity.GetOrNull(window.World, history.Current.Entity);
SetSelected(window, null, entity);
// TODO: Set path if entity could not be found.
}
- private void GoToNext(EntityRef window, History history)
+ private static void GoToNext(Entity window, History history)
{
if (history.Current?.Next == null) return;
history.Current = history.Current.Next;
- var entity = EntityRef.CreateOrNull(window.World, history.Current.Entity);
+ var entity = Entity.GetOrNull(window.World, history.Current.Entity);
SetSelected(window, null, entity);
// TODO: Set path if entity could not be found.
}
- private Rule? _findDisplayTypeRule;
- private (EntityRef? DisplayType, float Priority) FindDisplayType(EntityRef entity)
+ private static object? _findDisplayTypeRule;
+ private static (Entity? DisplayType, float Priority) FindDisplayType(Entity entity)
{
var world = entity.World;
- var component = world.LookupByTypeOrThrow();
+ var component = world.Entity();
- var rule = _findDisplayTypeRule ??= new Rule(world, new(
- $"$Type, gaemstone.Doc.DisplayType($Type)"));
+ var rule = (Rule)(_findDisplayTypeRule ??= new Rule(world, new(
+ $"$Type, gaemstone.Doc.DisplayType($Type)")));
var typeVar = rule.Variables["Type"]!;
- var curType = (EntityRef?)null;
+ var curType = (Entity?)null;
var curPriority = float.MaxValue;
- foreach (var iter in _findDisplayTypeRule.Iter().SetVar(rule.ThisVar!, entity))
+ foreach (var iter in rule.Iter().SetVar(rule.ThisVar!, entity))
for (var i = 0; i < iter.Count; i++) {
var type = iter.GetVar(typeVar);
- if ((type == component) && (entity.GetOrNull(component)?.Size == 0))
- type = world.LookupByTypeOrThrow();
- var priority = type.GetOrNull()?.Value ?? float.MaxValue;
+ if ((type == component) && (entity.GetOrNull(component)?.Size == 0))
+ type = world.Entity();
+ var priority = type?.GetOrNull()?.Value ?? float.MaxValue;
if (priority <= curPriority) { curType = type; curPriority = priority; }
}
@@ -658,24 +672,24 @@ public partial class EntityInspector
// == Utility ImGui Functions ==
// =============================
- private void RenderIdentifier(EntityRef window, History? history, IdRef id)
+ private static void RenderIdentifier(Entity window, History? history, Id id)
{
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(2, ImGui.GetStyle().ItemSpacing.Y));
- if (id.AsPair() is (EntityRef relation, EntityRef target)) {
+ if (id.AsPair() is (Entity relation, Entity target)) {
ImGui.TextUnformatted("("); ImGui.SameLine();
RenderEntity(window, history, relation);
ImGui.SameLine(); ImGui.TextUnformatted(","); ImGui.SameLine();
RenderEntity(window, history, target);
ImGui.SameLine(); ImGui.TextUnformatted(")");
- } else if (id.AsEntity() is EntityRef entity)
+ } else if (id.AsEntity() is Entity entity)
RenderEntity(window, history, entity);
else
ImGui.TextUnformatted(id.ToString());
ImGui.PopStyleVar();
}
- private void RenderEntity(
- EntityRef window, History? history, EntityRef entity,
+ private static void RenderEntity(
+ Entity window, History? history, Entity entity,
RenderEntityFlags flags = default)
{
var spanAvailWidth = (flags & RenderEntityFlags.SpanAvailWidth) != 0;
@@ -696,7 +710,7 @@ public partial class EntityInspector
var docName = entity.GetDocName(false);
var isDisabled = entity.IsDisabled;
- var displayName = (docName != null) ? $"\"{docName}\"" : entity.Name ?? entity.Id.ToString();
+ var displayName = (docName != null) ? $"\"{docName}\"" : entity.Name ?? entity.NumericId.ToString();
if (docIcon != null) displayName = $"{docIcon} {displayName}";
// Gotta push the font to calculate size properly.
@@ -715,10 +729,10 @@ public partial class EntityInspector
: Color.Transparent.RGBA);
ImGui.PushStyleColor(ImGuiCol.ButtonActive , ImGui.GetColorU32(ImGuiCol.HeaderActive));
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, ImGui.GetColorU32(ImGuiCol.HeaderHovered));
- ImGui.Button($"##{entity.Id}", size);
+ ImGui.Button($"##{entity.NumericId}", size);
ImGui.PopStyleColor(3);
ImGui.PopStyleVar();
- } else ImGui.InvisibleButton($"##{entity.Id}", size);
+ } else ImGui.InvisibleButton($"##{entity.NumericId}", size);
var shift = ImGui.IsKeyDown(ImGuiKey.ModShift);
var hovered = ImGui.IsItemHovered();
@@ -746,7 +760,7 @@ public partial class EntityInspector
if (hovered) {
ImGui.BeginTooltip();
ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[1]);
- ImGui.TextUnformatted(entity.GetFullPath().ToString());
+ ImGui.TextUnformatted(entity.Path.ToString());
ImGui.PopFont();
if (isDisabled) {
ImGui.SameLine();
diff --git a/src/gaemstone.Client/Systems/FreeCameraController.cs b/src/gaemstone.Client/Systems/FreeCameraController.cs
index 5b4fb7c..bf3c1f5 100644
--- a/src/gaemstone.Client/Systems/FreeCameraController.cs
+++ b/src/gaemstone.Client/Systems/FreeCameraController.cs
@@ -21,24 +21,25 @@ public partial class FreeCameraController
}
[System]
- public static void UpdateCamera(
- Universe universe, TimeSpan delta,
- in Camera camera, ref GlobalTransform transform, ref CameraController controller)
+ public static void UpdateCamera(
+ World world, TimeSpan delta,
+ in Camera camera, ref GlobalTransform transform, in CameraController controller)
{
- var input = universe.LookupByType ();
- var mouse = universe.LookupByType();
- var keyboard = universe.LookupByType();
- if ((input == null) || (mouse == null) || (keyboard == null)) return;
+ var input = world.Entity ();
+ var mouse = world.Entity();
+ var keyboard = world.Entity();
+ // FIXME: Is it okay if this crashes?
+ // if ((input == null) || (mouse == null) || (keyboard == null)) return;
- var module = universe.LookupByTypeOrThrow();
+ var module = world.Entity();
var capturedBy = input.GetTargets().FirstOrDefault();
var inputCapturedBy = input.GetTargets().FirstOrDefault();
- var isCaptured = (capturedBy != null);
+ var isCaptured = capturedBy.IsSome;
// If another system has the mouse captured, don't do anything here.
if (isCaptured && (capturedBy != module)) return;
- var isMouseDown = ((inputCapturedBy == null) || (inputCapturedBy == module))
- && mouse.LookupChild("Buttons/Right")?.Has() == true;
+ var isMouseDown = (inputCapturedBy.IsNone || (inputCapturedBy == module))
+ && mouse.LookupChildOrNull("Buttons/Right")?.Has() == true;
if (isMouseDown != isCaptured) {
if (isMouseDown)
input.Add(module);
@@ -51,18 +52,18 @@ public partial class FreeCameraController
var mouseMovement = Vector2.Zero;
if (isCaptured) {
- var raw = (Vector2?)mouse.LookupChild("Delta")?.GetOrThrow() ?? default;
+ var raw = (Vector2?)mouse.LookupChildOrNull("Delta")?.GetOrThrow() ?? default;
mouseMovement = raw * controller.MouseSensitivity * (float)delta.TotalSeconds;
}
if (camera.IsOrthographic) {
transform *= Matrix4x4.CreateTranslation(-mouseMovement.X, -mouseMovement.Y, 0);
} else {
- var shift = keyboard.LookupChild("ShiftLeft")?.Has() == true;
- var w = keyboard.LookupChild("W")?.Has() == true;
- var a = keyboard.LookupChild("A")?.Has() == true;
- var s = keyboard.LookupChild("S")?.Has() == true;
- var d = keyboard.LookupChild("D")?.Has() == true;
+ var shift = keyboard.LookupChildOrNull("ShiftLeft")?.Has() == true;
+ var w = keyboard.LookupChildOrNull("W")?.Has() == true;
+ var a = keyboard.LookupChildOrNull("A")?.Has() == true;
+ var s = keyboard.LookupChildOrNull("S")?.Has() == true;
+ var d = keyboard.LookupChildOrNull("D")?.Has() == true;
var speed = (shift ? 12 : 4) * (float)delta.TotalSeconds;
var forwardMovement = ((w ? -1 : 0) + (s ? 1 : 0)) * speed;
diff --git a/src/gaemstone.Client/Systems/ImGuiDemoWindow.cs b/src/gaemstone.Client/Systems/ImGuiDemoWindow.cs
index 0534b30..85ce160 100644
--- a/src/gaemstone.Client/Systems/ImGuiDemoWindow.cs
+++ b/src/gaemstone.Client/Systems/ImGuiDemoWindow.cs
@@ -9,10 +9,10 @@ namespace gaemstone.Client.Systems;
[DependsOn]
public partial class ImGuiDemoWindow
{
- private bool _isOpen = false;
+ private static bool _isOpen = false;
[System]
- public void Show(ImGuiData _)
+ public static void Show(ImGuiData _)
{
if (ImGuiUtility.UIButtonToggle(2, ForkAwesome.WindowMaximize, "ImGui Demo Window", ref _isOpen))
ImGui.ShowDemoWindow(ref _isOpen);
diff --git a/src/gaemstone.Client/Systems/ImGuiInputDebug.cs b/src/gaemstone.Client/Systems/ImGuiInputDebug.cs
index ee23dc7..36ce36c 100644
--- a/src/gaemstone.Client/Systems/ImGuiInputDebug.cs
+++ b/src/gaemstone.Client/Systems/ImGuiInputDebug.cs
@@ -17,13 +17,12 @@ namespace gaemstone.Client.Systems;
[DependsOn]
public partial class ImGuiInputDebug
{
- private bool _isOpen = false;
+ private static bool _isOpen = false;
[System]
- public void ShowInputDebugWindow(Universe universe, ImGuiData _)
+ public static void ShowInputDebugWindow(World world, ImGuiData _)
{
- var input = universe.LookupByType ();
- if (input == null) return;
+ var input = world.Entity ();
if (!ImGuiUtility.UIButtonToggle(1, ForkAwesome.Gamepad, "Input Information", ref _isOpen)) return;
@@ -34,19 +33,20 @@ public partial class ImGuiInputDebug
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize)) {
ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[0]);
- if (universe.LookupByType() is EntityRef keyboard)
- DrawKeyboard(keyboard);
+ var keyboard = world.Entity();
+ DrawKeyboard(keyboard);
- if (universe.LookupByType() is EntityRef mouse) {
+ var mouse = world.Entity();
+ {
ImGui.BeginChild("Mouse Info", new(160, 180), true);
- ImGui.Text("Position: " + (Vector2?)mouse.LookupChild("Position")?.GetOrNull());
- ImGui.Text("Delta: " + (Vector2?)mouse.LookupChild("Delta" )?.GetOrNull());
- ImGui.Text("Wheel: " + (float?) mouse.LookupChild("Wheel" )?.GetOrNull());
+ ImGui.Text("Position: " + (Vector2?)mouse.LookupChildOrNull("Position")?.GetOrNull());
+ ImGui.Text("Delta: " + (Vector2?)mouse.LookupChildOrNull("Delta" )?.GetOrNull());
+ ImGui.Text("Wheel: " + (float?) mouse.LookupChildOrNull("Wheel" )?.GetOrNull());
ImGui.Spacing();
- var buttons = mouse.LookupChild("Buttons")?.GetChildren().ToArray() ?? Array.Empty();
+ var buttons = mouse.LookupChildOrNull("Buttons")?.Children.ToArray() ?? Array.Empty>();
ImGui.Text("Buttons: " + string.Join(" ", buttons
.Where (button => button.Has())
.Select(button => $"{button.Name} ({button.GetOrThrow().Duration.TotalSeconds:f2}s)")));
@@ -60,11 +60,11 @@ public partial class ImGuiInputDebug
ImGui.EndChild();
}
- for (var index = 0; input.LookupChild("Gamepad" + index) is EntityRef gamepad; index++) {
+ for (var index = 0; input.LookupChildOrNull("Gamepad" + index) is Entity gamepad; index++) {
ImGui.SameLine();
ImGui.BeginChild($"{gamepad.Name} Info", new(160, 180), true);
- var buttons = gamepad.LookupChild("Buttons")?.GetChildren().ToArray() ?? Array.Empty();
+ var buttons = gamepad.LookupChildOrNull("Buttons")?.Children.ToArray() ?? Array.Empty>();
ImGui.Text("Buttons: " + string.Join(" ", buttons.Where(b => b.Has())
.Select(b => $"{b.Name} ({b.GetOrThrow().Duration.TotalSeconds:f2}s)")));
ImGui.Text(" Pressed: " + string.Join(" ", buttons.Where(b => b.Has()).Select(b => b.Name)));
@@ -73,7 +73,7 @@ public partial class ImGuiInputDebug
ImGui.Spacing();
ImGui.Text("Triggers:");
- for (var i = 0; gamepad.LookupChild("Trigger" + i) is EntityRef trigger; i++) {
+ for (var i = 0; gamepad.LookupChildOrNull("Trigger" + i) is Entity trigger; i++) {
var text = $" {i}: {(float?)trigger.GetOrNull() ?? default:f2}";
if (trigger.Has()) text += " pressed!";
else if (trigger.Has()) text += " released!";
@@ -83,7 +83,7 @@ public partial class ImGuiInputDebug
}
ImGui.Text("Thumbsticks:");
- for (var i = 0; gamepad.LookupChild("Thumbstick" + i) is EntityRef thumbstick; i++)
+ for (var i = 0; gamepad.LookupChildOrNull("Thumbstick" + i) is Entity thumbstick; i++)
ImGui.Text($" {i}: {(Vector2?)thumbstick.GetOrNull() ?? default:f2}");
ImGui.EndChild();
@@ -139,7 +139,7 @@ public partial class ImGuiInputDebug
[Key.NumLock] = "Num\nLck", [Key.KeypadEnter] = "=",
};
- public static void DrawKeyboard(EntityRef keyboard)
+ public static void DrawKeyboard(Entity keyboard)
{
const float UnitKeySize = 32.0f;
@@ -150,10 +150,10 @@ public partial class ImGuiInputDebug
var current = Vector2.Zero;
foreach (var (widths, keys) in KeyboardLayout.Zip(KeyboardKeys)) {
foreach (var (width, key) in widths.Zip(keys)) {
- var active = (key != null) && (keyboard.LookupChild(key.Value.ToString())?.Has() == true);
+ var active = (key != null) && (keyboard.LookupChildOrNull(key.Value.ToString())?.Has() == true);
var keySize = new Vector2(width, 1.0f);
- if (width == T) keySize = new Vector2((-keySize.X - 10), 2.0f);
+ if (width == ImGuiInputDebug.T) keySize = new Vector2((-keySize.X - 10), 2.0f);
else if (width < -10) keySize = new Vector2((-keySize.X - 10), 1.0f);
else if (width < 0) { current += new Vector2(-keySize.X * UnitKeySize, 0); continue; }
diff --git a/src/gaemstone.Client/Systems/ImGuiManager.cs b/src/gaemstone.Client/Systems/ImGuiManager.cs
index c9a4094..acd024d 100644
--- a/src/gaemstone.Client/Systems/ImGuiManager.cs
+++ b/src/gaemstone.Client/Systems/ImGuiManager.cs
@@ -4,8 +4,8 @@ using System.Linq;
using System.Text;
using gaemstone.Client.Utility;
using gaemstone.ECS;
+using gaemstone.ECS.Utility;
using gaemstone.Flecs;
-using gaemstone.Utility;
using ImGuiNET;
using Silk.NET.Input;
using Silk.NET.OpenGL.Extensions.ImGui;
@@ -22,14 +22,17 @@ namespace gaemstone.Client.Systems;
public partial class ImGuiManager
{
[Entity, Add]
- [DependsOn]
+ [DependsOn]
public struct ImGuiUpdatePhase { }
[Entity, Add]
- [DependsOn]
+ [DependsOn]
public struct ImGuiRenderPhase { }
- [Singleton(AutoAdd = false)]
+ // Start out disabled, because we first need to set it with a valid instance.
+ // TODO: Add a hint when a Singleton class is used without adding Disabled.
+ // TODO: Add a [Disabled] attribute as shortcut?
+ [Singleton, Add]
public class ImGuiData
{
public ImGuiController Controller { get; }
@@ -84,10 +87,11 @@ public partial class ImGuiManager
return io.Fonts.AddFontFromMemoryTTF((IntPtr)dataPtr, size, size, cfg);
}
- [System]
- public unsafe void Initialize(Universe universe, GameWindow window, Canvas canvas,
- [Source