First milestone: Getting windows drawing

Command list is working, windows draw in the correct order
This commit is contained in:
Bobby Lucero 2025-07-07 18:39:52 -04:00
parent d56f214a44
commit deda09a4a5
2 changed files with 526 additions and 41 deletions

View File

@ -1,4 +1,5 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Security.Cryptography;
namespace MicroUI namespace MicroUI
{ {
@ -37,7 +38,7 @@ namespace MicroUI
public static float Clamp(float x, float a, float b) => Min(b, Max(a, x)); public static float Clamp(float x, float a, float b) => Min(b, Max(a, x));
} }
public struct FixedStack<T> public class FixedStack<T>
{ {
public int Index; public int Index;
public T[] Items; public T[] Items;
@ -504,7 +505,7 @@ namespace MicroUI
public static void DrawFrame(MuContext ctx, MuRect rect, ColorType colorId) public static void DrawFrame(MuContext ctx, MuRect rect, ColorType colorId)
{ {
// Draw filled rectangle with given color // Draw filled rectangle with given color
//DrawRect(ctx, rect, ctx.Style.Colors[(int)colorId]); // TODO: Implement DrawRect MuCommandList.DrawRect(ctx, rect, ctx.Style.Colors[(int)colorId]);
// Early return for certain color IDs (skip border) // Early return for certain color IDs (skip border)
if (colorId == ColorType.ScrollBase || if (colorId == ColorType.ScrollBase ||
@ -517,7 +518,7 @@ namespace MicroUI
// Draw border if alpha > 0 // Draw border if alpha > 0
if (ctx.Style.Colors[(int)ColorType.Border].A > 0) if (ctx.Style.Colors[(int)ColorType.Border].A > 0)
{ {
//DrawBox(ctx, ExpandRect(rect, 1), ctx.Style.Colors[(int)ColorType.Border]); // TODO: Implement DrawBox MuCommandList.DrawBox(ctx, ExpandRect(rect, 1), ctx.Style.Colors[(int)ColorType.Border]); // TODO: Implement DrawBox
} }
} }
@ -530,6 +531,18 @@ namespace MicroUI
// Copy the default style (make sure it's cloned, not shared!) // Copy the default style (make sure it's cloned, not shared!)
ctx.Style = DefaultStyle; ctx.Style = DefaultStyle;
// Initialize containers array with actual MuContainer objects
for (int i = 0; i < ctx.Containers.Length; i++)
{
ctx.Containers[i] = new MuContainer();
}
// Initialize container pool items
for (int i = 0; i < ctx.ContainerPool.Length; i++)
{
ctx.ContainerPool[i] = new MuPoolItem(0, 0);
}
} }
public static void Begin(MuContext ctx) public static void Begin(MuContext ctx)
@ -579,7 +592,7 @@ namespace MicroUI
ctx.NextHoverRoot.ZIndex < ctx.LastZIndex && ctx.NextHoverRoot.ZIndex < ctx.LastZIndex &&
ctx.NextHoverRoot.ZIndex >= 0) ctx.NextHoverRoot.ZIndex >= 0)
{ {
//BringToFront(ctx.NextHoverRoot); // TODO: Implement BringToFront BringToFront(ctx, ctx.NextHoverRoot); // TODO: Implement BringToFront
} }
ctx.KeyPressed = 0; ctx.KeyPressed = 0;
@ -651,9 +664,13 @@ namespace MicroUI
} }
public static void PushClipRect(MuContext ctx, MuRect rect) { public static void PushClipRect(MuContext ctx, MuRect rect) {
if (ctx.ClipStack.Index == 0) {
ctx.ClipStack.Push(rect);
} else {
MuRect last = GetClipRect(ctx); MuRect last = GetClipRect(ctx);
ctx.ClipStack.Push(IntersectRects(rect, last)); ctx.ClipStack.Push(IntersectRects(rect, last));
} }
}
public static void PopClipRect(MuContext ctx) public static void PopClipRect(MuContext ctx)
{ {
@ -707,10 +724,10 @@ namespace MicroUI
// Call mu_layout_row with count=1, widths pointer to width var, height=0 // Call mu_layout_row with count=1, widths pointer to width var, height=0
int[] widths = { 0 }; int[] widths = { 0 };
LayoutRow(ctx, 1, widths, 0); MuLayoutUtil.LayoutRow(ctx, 1, widths, 0);
} }
static ref MuLayout GetLayout(MuContext ctx) public static ref MuLayout GetLayout(MuContext ctx)
{ {
if (ctx.LayoutStack.Index == 0) if (ctx.LayoutStack.Index == 0)
throw new InvalidOperationException("Layout stack is empty."); throw new InvalidOperationException("Layout stack is empty.");
@ -718,7 +735,7 @@ namespace MicroUI
return ref ctx.LayoutStack.Items[ctx.LayoutStack.Index - 1]; return ref ctx.LayoutStack.Items[ctx.LayoutStack.Index - 1];
} }
static void PopContainer(MuContext ctx) public static void PopContainer(MuContext ctx)
{ {
MuContainer cnt = GetCurrentContainer(ctx); MuContainer cnt = GetCurrentContainer(ctx);
MuLayout layout = GetLayout(ctx); MuLayout layout = GetLayout(ctx);
@ -734,7 +751,7 @@ namespace MicroUI
PopId(ctx); PopId(ctx);
} }
static MuContainer GetCurrentContainer(MuContext ctx) public static MuContainer GetCurrentContainer(MuContext ctx)
{ {
MuAssert.Expect(ctx.ContainerStack.Index > 0); MuAssert.Expect(ctx.ContainerStack.Index > 0);
return ctx.ContainerStack.Items[ctx.ContainerStack.Index - 1]; return ctx.ContainerStack.Items[ctx.ContainerStack.Index - 1];
@ -745,46 +762,49 @@ namespace MicroUI
**============================================================================*/ **============================================================================*/
public static void LayoutRow(MuContext ctx, int items, int[] widths, int height)
public static MuContainer? GetContainer(MuContext ctx, uint id, int opt)
{ {
var layout = GetLayout(ctx); // get current layout (implement accordingly) // Try to get existing container from pool
int idx = MuPool.Get(ctx, ctx.ContainerPool, id);
if (items > Constants.MaxWidths)
throw new ArgumentOutOfRangeException(nameof(items), $"Items cannot be more than {Constants.MaxWidths}.");
// Copy widths into layout.Widths
Array.Copy(widths, layout.Widths, items);
layout.Items = items;
layout.Position = new MuVec2(layout.Indent, layout.NextRow);
layout.Size = new MuVec2(layout.Size.X, height); // assuming Size is MuVec2, updating only Y component
layout.ItemIndex = 0;
}
static MuContainer? GetContainer(MuContext ctx, uint id, int opt)
{
//int idx = MuPool.Get(ctx, ctx.ContainerPool, ctx.Containers.Length, id); // TODO: Implement MuPool
int idx = MuPool.Get(ctx, ctx.ContainerPool, id); // TODO: Implement MuPool
if (idx >= 0) if (idx >= 0)
{ {
if (ctx.Containers[idx].Open || (opt & (int)Options.Closed) == 0) if (ctx.Containers[idx].Open || (opt & (int)Options.Closed) == 0)
{ {
//MuPool.Update(ctx, ctx.ContainerPool, idx); // TODO: Implement MuPool MuPool.Update(ctx, ctx.ContainerPool, idx);
MuPool.Update(ctx, ctx.ContainerPool, idx); // TODO: Implement MuPool
} }
return ctx.Containers[idx]; return ctx.Containers[idx];
} }
// Create a new container // If we're looking for a closed container and it doesn't exist, return null
//idx = MuPool.Init(ctx, ctx.ContainerPool, ctx.Containers.Length, id); // TODO: Implement MuPool if ((opt & (int)Options.Closed) != 0)
//ref MuContainer cnt = ref ctx.Containers[idx]; {
//cnt = new MuContainer(); // Reset all fields
//cnt.Open = true;
//BringToFront(ctx, ref cnt); // TODO: Implement BringToFront
return null; return null;
} }
// Container not found in pool: init new container
idx = MuPool.Init(ctx, ctx.ContainerPool, id);
var cnt = ctx.Containers[idx];
// Reset all fields (equivalent to memset(cnt, 0, sizeof(*cnt)))
cnt.HeadIndex = -1;
cnt.TailIndex = -1;
cnt.Rect = new MuRect(0, 0, 0, 0);
cnt.Body = new MuRect(0, 0, 0, 0);
cnt.ContentSize = new MuVec2(0, 0);
cnt.Scroll = new MuVec2(0, 0);
cnt.ZIndex = 0;
cnt.Open = true;
BringToFront(ctx, cnt);
return cnt;
}
public static void BringToFront(MuContext ctx, MuContainer cnt)
{
cnt.ZIndex = ++ctx.LastZIndex;
}
} }
public static class MuPool public static class MuPool
@ -875,4 +895,408 @@ namespace MicroUI
} }
} }
} }
public static class MuCommandList
{
public static void Push(MuContext ctx, MuCommand cmd)
{
ctx.CommandList.Push(cmd);
}
public static MuCommand? NextCommand(MuContext ctx, ref int index)
{
var commands = ctx.CommandList.Items;
int count = ctx.CommandList.Index;
while (index < count)
{
var cmd = commands[index];
if (cmd is MuJumpCommand jump)
{
// Jump to the destination index
if (jump.DestinationIndex < 0 || jump.DestinationIndex >= count)
return null; // Invalid jump, end iteration
index = jump.DestinationIndex;
continue;
}
// Return the current command and advance index
return commands[index++];
}
return null; // End of command list
}
public static MuJumpCommand PushJump(MuContext ctx, int destinationIndex = -1)
{
var jump = new MuJumpCommand { DestinationIndex = destinationIndex };
ctx.CommandList.Push(jump);
return jump;
}
public static void SetClip(MuContext ctx, MuRect rect)
{
MuCommandList.Push(ctx, new MuClipCommand(rect));
}
public static void DrawRect(MuContext ctx, MuRect rect, MuColor color)
{
// Intersect with current clip rect
rect = MicroUI.IntersectRects(rect, MicroUI.GetClipRect(ctx));
if (rect.W > 0 && rect.H > 0)
{
MuCommandList.Push(ctx, new MuRectCommand(rect, color));
}
}
public static void DrawBox(MuContext ctx, MuRect rect, MuColor color)
{
DrawRect(ctx, new MuRect(rect.X + 1, rect.Y, rect.W - 2, 1), color);
DrawRect(ctx, new MuRect(rect.X + 1, rect.Y + rect.H - 1, rect.W - 2, 1), color);
DrawRect(ctx, new MuRect(rect.X, rect.Y, 1, rect.H), color);
DrawRect(ctx, new MuRect(rect.X + rect.W - 1, rect.Y, 1, rect.H), color);
}
public static void DrawText(MuContext ctx, object? font, string str, MuVec2 pos, MuColor color)
{
int len = str.Length;
int w = ctx.TextWidth != null ? ctx.TextWidth(font, str, len) : 0;
int h = ctx.TextHeight != null ? ctx.TextHeight(font) : 0;
var rect = new MuRect(pos.X, pos.Y, w, h);
var clipped = MicroUI.CheckClip(ctx, rect);
if (clipped == ClipMode.All) return;
if (clipped == ClipMode.Part) SetClip(ctx, MicroUI.GetClipRect(ctx));
// Add command
MuCommandList.Push(ctx, new MuTextCommand(font, pos, color, str));
// Reset clipping if it was set
if (clipped != 0) SetClip(ctx, MicroUI.UnclippedRect);
}
public static void DrawIcon(MuContext ctx, int id, MuRect rect, MuColor color)
{
var clipped = MicroUI.CheckClip(ctx, rect);
if (clipped == ClipMode.All) return;
if (clipped == ClipMode.Part) SetClip(ctx, MicroUI.GetClipRect(ctx));
MuCommandList.Push(ctx, new MuIconCommand(rect, id, color));
if (clipped != 0) SetClip(ctx, MicroUI.UnclippedRect);
}
}
// Layout next type enum (matches C enum { RELATIVE = 1, ABSOLUTE = 2 })
enum LayoutNextType
{
Relative = 1,
Absolute = 2
}
public static class MuLayoutUtil
{
public static void LayoutBeginColumn(MuContext ctx)
{
var rect = LayoutNext(ctx);
MicroUI.PushLayout(ctx, rect, new MuVec2(0, 0));
}
public static void LayoutEndColumn(MuContext ctx)
{
// Get the child layout (top of stack)
ref var b = ref MicroUI.GetLayout(ctx);
ctx.LayoutStack.Pop();
// Get the parent layout (now top of stack)
ref var a = ref MicroUI.GetLayout(ctx);
a.Position = new MuVec2(
MathUtil.Max(a.Position.X, b.Position.X + b.Body.X - a.Body.X),
a.Position.Y
);
a.NextRow = MathUtil.Max(a.NextRow, b.NextRow + b.Body.Y - a.Body.Y);
a.Max = new MuVec2(
MathUtil.Max(a.Max.X, b.Max.X),
MathUtil.Max(a.Max.Y, b.Max.Y)
);
}
public static void LayoutRow(MuContext ctx, int items, int[]? widths, int height)
{
ref var layout = ref MicroUI.GetLayout(ctx);
if (widths != null)
{
MuAssert.Expect(items <= Constants.MaxWidths);
Array.Copy(widths, layout.Widths, items);
}
layout.Items = items;
layout.Position = new MuVec2(layout.Indent, layout.NextRow);
layout.Size = new MuVec2(layout.Size.X, height); // Only Y is updated
layout.ItemIndex = 0;
}
public static void LayoutWidth(MuContext ctx, int width)
{
ref var layout = ref MicroUI.GetLayout(ctx);
layout.Size = new MuVec2(width, layout.Size.Y);
}
public static void LayoutHeight(MuContext ctx, int height)
{
ref var layout = ref MicroUI.GetLayout(ctx);
layout.Size = new MuVec2(layout.Size.X, height);
}
public static void LayoutSetNext(MuContext ctx, MuRect r, bool relative)
{
ref var layout = ref MicroUI.GetLayout(ctx);
layout.Next = r;
layout.NextType = relative ? (int)LayoutNextType.Relative : (int)LayoutNextType.Absolute;
}
public static MuRect LayoutNext(MuContext ctx)
{
ref var layout = ref MicroUI.GetLayout(ctx);
var style = ctx.Style;
MuRect res;
if (layout.NextType != 0)
{
int type = layout.NextType;
layout.NextType = 0;
res = layout.Next;
if (type == (int)LayoutNextType.Absolute)
{
ctx.LastRect = res;
return res;
}
}
else
{
// handle next row
if (layout.ItemIndex == layout.Items)
{
LayoutRow(ctx, layout.Items, null, layout.Size.Y);
}
// position
res.X = layout.Position.X;
res.Y = layout.Position.Y;
// size
res.W = layout.Items > 0 ? layout.Widths[layout.ItemIndex] : layout.Size.X;
res.H = layout.Size.Y;
if (res.W == 0) res.W = style.Size.X + style.Padding * 2;
if (res.H == 0) res.H = style.Size.Y + style.Padding * 2;
if (res.W < 0) res.W += layout.Body.W - res.X + 1;
if (res.H < 0) res.H += layout.Body.H - res.Y + 1;
layout.ItemIndex++;
}
// update position
layout.Position = new MuVec2(
layout.Position.X + res.W + style.Spacing,
layout.Position.Y
);
layout.NextRow = MathUtil.Max(layout.NextRow, res.Y + res.H + style.Spacing);
// apply body offset
res.X += layout.Body.X;
res.Y += layout.Body.Y;
// update max position
layout.Max = new MuVec2(
MathUtil.Max(layout.Max.X, res.X + res.W),
MathUtil.Max(layout.Max.Y, res.Y + res.H)
);
ctx.LastRect = res;
return res;
}
}
public static class MuControl
{
public static void PushContainerBody(MuContext ctx, MuContainer cnt, MuRect body, int opt)
{
// If scrolling is enabled, handle scrollbars (stub for now)
if ((opt & (int)Options.NoScroll) == 0)
{
// TODO: Implement scrollbars(ctx, cnt, ref body);
}
// Push layout for the container body, with padding and scroll offset
MicroUI.PushLayout(ctx, MicroUI.ExpandRect(body, -ctx.Style.Padding), cnt.Scroll);
// Store the body rect in the container
cnt.Body = body;
}
public static void BeginRootContainer(MuContext ctx, MuContainer cnt)
{
// Push container onto container stack
ctx.ContainerStack.Push(cnt);
// Push container to roots list and push head command
ctx.RootList.Push(cnt);
cnt.HeadIndex = ctx.CommandList.Index; // Store the current command index as head
MuCommandList.PushJump(ctx); // Push a jump command (will be set up later)
// Set as hover root if the mouse is overlapping this container and it has a
// higher zindex than the current hover root
if (MicroUI.RectOverlapsVec2(cnt.Rect, ctx.MousePos) &&
(ctx.NextHoverRoot == null || cnt.ZIndex > ctx.NextHoverRoot.ZIndex))
{
ctx.NextHoverRoot = cnt;
}
// Clipping is reset here in case a root-container is made within
// another root-container's begin/end block; this prevents the inner
// root-container being clipped to the outer
MicroUI.PushClipRect(ctx, MicroUI.UnclippedRect);
}
public static void EndRootContainer(MuContext ctx)
{
// Push tail 'goto' jump command and set head 'skip' command. The final steps
// on setting up these are done in MicroUI.End()
MuContainer cnt = MicroUI.GetCurrentContainer(ctx);
cnt.TailIndex = ctx.CommandList.Index; // Store the current command index as tail
MuCommandList.PushJump(ctx); // Push a jump command (will be set up later)
// Set the head jump command to point to the current command index
// (This will be finalized in MicroUI.End())
if (cnt.HeadIndex >= 0 && cnt.HeadIndex < ctx.CommandList.Index)
{
var headJump = ctx.CommandList.Items[cnt.HeadIndex] as MuJumpCommand;
if (headJump != null)
{
headJump.DestinationIndex = ctx.CommandList.Index;
}
}
// Pop base clip rect and container
MicroUI.PopClipRect(ctx);
MicroUI.PopContainer(ctx);
}
public static bool BeginWindowEx(MuContext ctx, string title, MuRect rect, int opt)
{
// 1. Get/Init Container
uint id = MicroUI.GetId(ctx, System.Text.Encoding.UTF8.GetBytes(title));
MuContainer? cnt = MicroUI.GetContainer(ctx, id, opt);
if (cnt == null || !cnt.Open) return false;
// 2. Push ID
MicroUI.PushId(ctx, System.Text.Encoding.UTF8.GetBytes(title));
// 3. Set Initial Rect
if (cnt.Rect.W == 0) cnt.Rect = rect;
// 4. Begin Root Container
MuControl.BeginRootContainer(ctx, cnt);
rect = cnt.Rect;
var body = rect;
// 5. Draw Window Frame
if ((opt & (int)Options.NoFrame) == 0)
{
ctx.DrawFrame?.Invoke(ctx, rect, ColorType.WindowBg);
}
// 6. Draw Title Bar
if ((opt & (int)Options.NoTitle) == 0)
{
var tr = rect;
tr.H = ctx.Style.TitleHeight;
ctx.DrawFrame?.Invoke(ctx, tr, ColorType.TitleBg);
// Title text and drag
uint titleId = MicroUI.GetId(ctx, System.Text.Encoding.UTF8.GetBytes("!title"));
//MuControl.UpdateControl(ctx, titleId, tr, opt); // Implement or comment out
//MuControl.DrawControlText(ctx, title, tr, ColorType.TitleText, opt); // Implement or comment out
// Move window if dragging title bar
if (titleId == ctx.Focus && (ctx.MouseDown & (int)MouseButton.Left) != 0)
{
cnt.Rect = new MuRect(
cnt.Rect.X + ctx.MouseDelta.X,
cnt.Rect.Y + ctx.MouseDelta.Y,
cnt.Rect.W,
cnt.Rect.H
);
}
// Adjust body for title bar
body.Y += tr.H;
body.H -= tr.H;
// Close button
if ((opt & (int)Options.NoClose) == 0)
{
uint closeId = MicroUI.GetId(ctx, System.Text.Encoding.UTF8.GetBytes("!close"));
var r = new MuRect(tr.X + tr.W - tr.H, tr.Y, tr.H, tr.H);
tr.W -= r.W;
//MuControl.DrawIcon(ctx, (int)IconType.Close, r, ctx.Style.Colors[(int)ColorType.TitleText]); // Implement or comment out
//MuControl.UpdateControl(ctx, closeId, r, opt); // Implement or comment out
if ((ctx.MousePressed & (int)MouseButton.Left) != 0 && closeId == ctx.Focus)
{
cnt.Open = false;
}
}
}
// 7. Push Container Body Layout
MuControl.PushContainerBody(ctx, cnt, body, opt); // Implement or comment out
// 8. Resize handle
if ((opt & (int)Options.NoResize) == 0)
{
int sz = ctx.Style.TitleHeight;
uint resizeId = MicroUI.GetId(ctx, System.Text.Encoding.UTF8.GetBytes("!resize"));
var r = new MuRect(rect.X + rect.W - sz, rect.Y + rect.H - sz, sz, sz);
//MuControl.UpdateControl(ctx, resizeId, r, opt); // Implement or comment out
if (resizeId == ctx.Focus && (ctx.MouseDown & (int)MouseButton.Left) != 0)
{
cnt.Rect = new MuRect(
cnt.Rect.X,
cnt.Rect.Y,
MathUtil.Max(96, cnt.Rect.W + ctx.MouseDelta.X),
MathUtil.Max(64, cnt.Rect.H + ctx.MouseDelta.Y)
);
}
}
// 9. Auto-size
if ((opt & (int)Options.AutoSize) != 0)
{
var r = MicroUI.GetLayout(ctx).Body;
cnt.Rect = new MuRect(
cnt.Rect.X,
cnt.Rect.Y,
cnt.ContentSize.X + (cnt.Rect.W - r.W),
cnt.ContentSize.Y + (cnt.Rect.H - r.H)
);
}
// 10. Popup close
if ((opt & (int)Options.Popup) != 0 && ctx.MousePressed != 0 && ctx.HoverRoot != cnt)
{
cnt.Open = false;
}
// 11. Push Clip Rect
MicroUI.PushClipRect(ctx, cnt.Body);
// 12. Return Active
return true;
}
public static void EndWindow(MuContext ctx)
{
MicroUI.PopClipRect(ctx);
MuControl.EndRootContainer(ctx);
}
}
} }

View File

@ -1,6 +1,7 @@
using Raylib_cs; using Raylib_cs;
using MicroUI;
namespace HelloWorld; namespace MicroUI;
class Program class Program
{ {
@ -10,14 +11,74 @@ class Program
{ {
Raylib.InitWindow(800, 480, "Hello World"); Raylib.InitWindow(800, 480, "Hello World");
// Create microui context
var ctx = new MuContext();
// Set up required callbacks
ctx.TextWidth = (object font, string str, int len) =>
{
return str.Length * 8; // Simple approximation
};
ctx.TextHeight = (object font) =>
{
return 16; // Simple approximation
};
// Initialize microui
MicroUI.Init(ctx);
while (!Raylib.WindowShouldClose()) while (!Raylib.WindowShouldClose())
{ {
Raylib.BeginDrawing(); Raylib.BeginDrawing();
Raylib.ClearBackground(Color.White); Raylib.ClearBackground(Color.White);
Raylib.DrawText("Hello, world!", 12, 12, 20, Color.Black); // Begin frame
MicroUI.Begin(ctx);
if(MuControl.BeginWindowEx(ctx, "Test Window", new MuRect(100, 100, 100, 100), 0)){
MuControl.EndWindow(ctx);
}
if(MuControl.BeginWindowEx(ctx, "Test Window 2", new MuRect(120, 120, 300, 200), 0)){
MuControl.EndWindow(ctx);
}
// End frame
MicroUI.End(ctx);
// Print all commands in the command list
int cmdIndex = 0;
MuCommand? cmd = null;
while ((cmd = MuCommandList.NextCommand(ctx, ref cmdIndex)) != null)
{
Console.Write($"Command: {cmd.Type}");
switch (cmd)
{
case MuRectCommand rectCmd:
Console.Write($" | Rect: ({rectCmd.Rect.X},{rectCmd.Rect.Y},{rectCmd.Rect.W},{rectCmd.Rect.H}) Color: {rectCmd.Color.R},{rectCmd.Color.G},{rectCmd.Color.B},{rectCmd.Color.A}");
Raylib.DrawRectangle(rectCmd.Rect.X, rectCmd.Rect.Y, rectCmd.Rect.W, rectCmd.Rect.H, new Color(rectCmd.Color.R, rectCmd.Color.G, rectCmd.Color.B, rectCmd.Color.A));
break;
case MuClipCommand clipCmd:
Console.Write($" | Clip: ({clipCmd.Rect.X},{clipCmd.Rect.Y},{clipCmd.Rect.W},{clipCmd.Rect.H})");
break;
case MuJumpCommand jumpCmd:
Console.Write($" | Jump to: {jumpCmd.DestinationIndex}");
break;
case MuTextCommand textCmd:
Console.Write($" | Text: '{textCmd.Text}' at ({textCmd.Position.X},{textCmd.Position.Y}) Color: {textCmd.Color.R},{textCmd.Color.G},{textCmd.Color.B},{textCmd.Color.A}");
break;
case MuIconCommand iconCmd:
Console.Write($" | Icon: {iconCmd.IconId} Rect: ({iconCmd.Rect.X},{iconCmd.Rect.Y},{iconCmd.Rect.W},{iconCmd.Rect.H}) Color: {iconCmd.Color.R},{iconCmd.Color.G},{iconCmd.Color.B},{iconCmd.Color.A}");
break;
}
Console.WriteLine("");
}
Raylib.EndDrawing(); Raylib.EndDrawing();
//break;
} }
Raylib.CloseWindow(); Raylib.CloseWindow();