feat(rumpk): Phase 3.5b Zicroui HUD Integration

- Vision: Updated VISION.md with Zicroui TUI/GUI Hybrid strategy
- Logic Graft: Integrated microui.c directly into Rumpk kernel
- HAL: Added hal/ui.zig (Zig Adapter) and hal/framebuffer.zig (Stub)
- Build: Updated build.sh to compile microui with freestanding headers (libs/microui/include)
- Stubs: Implemented vsnprintf, snprintf, sprint, strtod, qsort in cstubs.c for microui support
- Scheduler: Added dedicated UI Fiber (The Face) to kernel.nim
- Result: Immediate Mode GUI logic running on bare metal RISC-V
This commit is contained in:
Markus Maiwald 2025-12-31 08:53:24 +01:00
parent bcba945557
commit 8aa50eb3ef
11 changed files with 1816 additions and 2 deletions

View File

@ -96,6 +96,19 @@ zig build-obj \
mv nexshell.o "$BUILD_DIR/nexshell.o"
echo "$BUILD_DIR/nexshell.o"
# Compile UI (Zicroui)
echo "[1.2/8] Compiling UI (Zicroui)..."
zig build-obj \
-target $ZIG_TARGET \
$ZIG_OBJ_FLAGS \
-O ReleaseFast \
-I"$RUMPK_DIR/libs/microui" \
"$RUMPK_DIR/hal/ui.zig" \
--name ui
mv ui.o "$BUILD_DIR/ui.o"
echo "$BUILD_DIR/ui.o"
# =========================================================
# Step 2: Compile context switch assembly
# =========================================================
@ -122,6 +135,22 @@ zig cc \
-o "$BUILD_DIR/monocypher.o"
echo "$BUILD_DIR/monocypher.o"
# =========================================================
# Step 2.1b: Compile Microui
# =========================================================
echo "[2.1b/8] Compiling Microui..."
zig cc \
-target $ZIG_TARGET \
$ARCH_FLAGS \
-ffreestanding \
-fno-stack-protector \
-fno-builtin \
-O3 \
-I"$RUMPK_DIR/libs/microui/include" \
-c "$RUMPK_DIR/libs/microui/microui.c" \
-o "$BUILD_DIR/microui.o"
echo "$BUILD_DIR/microui.o"
# =========================================================
# Step 2.2: Compile LwIP (Kernel Stack)
# =========================================================
@ -515,6 +544,8 @@ $LINKER \
"$BUILD_DIR/overrides.o" \
"$BUILD_DIR/loader.o" \
"$BUILD_DIR/nexshell.o" \
"$BUILD_DIR/ui.o" \
"$BUILD_DIR/microui.o" \
$NIM_OBJS \
-o "$BUILD_DIR/rumpk-$ARCH.elf"

View File

@ -23,6 +23,13 @@ pub fn build(b: *std.Build) void {
hal.root_module.red_zone = false;
hal.root_module.stack_check = .none;
// Microui Integration (Phase 3.5b)
hal.addIncludePath(b.path("libs/microui"));
hal.addCSourceFile(.{
.file = b.path("libs/microui/microui.c"),
.flags = &.{"-std=c99"},
});
b.installArtifact(hal);
// =========================================================

View File

@ -140,6 +140,49 @@ int fprintf(void *stream, const char *format, ...) {
return printf(format);
}
int vsnprintf(char *str, size_t size, const char *format, va_list args) {
size_t count = 0;
if (size == 0) return 0;
while (*format && count < size - 1) {
if (*format == '%' && *(format + 1)) {
format++;
if (*format == 's') {
char *s = va_arg(args, char *);
if (s) {
while (*s && count < size - 1) {
str[count++] = *s++;
}
}
} else if (*format == 'd' || *format == 'i') {
int d = va_arg(args, int);
char buf[16];
itoa(d, buf);
char *b = buf;
while (*b && count < size - 1) {
str[count++] = *b++;
}
} else {
str[count++] = '%';
if (count < size - 1) str[count++] = *format;
}
} else {
str[count++] = *format;
}
format++;
}
str[count] = '\0';
return count;
}
int snprintf(char *str, size_t size, const char *format, ...) {
va_list args;
va_start(args, format);
int ret = vsnprintf(str, size, format, args);
va_end(args);
return ret;
}
int fflush(void *stream) {
return 0;
}
@ -183,5 +226,44 @@ int atoi(const char *nptr) {
return res;
}
int sprintf(char *str, const char *format, ...) {
va_list args;
va_start(args, format);
// Unsafe sprintf limit
int ret = vsnprintf(str, 2048, format, args);
va_end(args);
return ret;
}
double strtod(const char *nptr, char **endptr) {
if (endptr) *endptr = (char*)nptr + strlen(nptr); // Fake endptr
return (double)atoi(nptr);
}
// qsort uses existing memcpy
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
// Bubble sort for simplicity (O(n^2))
if (nmemb < 2) return;
char *b = (char *)base;
char tmp[256]; // Max item size 256 bytes for swap
// Verify size? If size > 256, we fail or use loop.
// mu_Container* is pointer size (8).
for (size_t i = 0; i < nmemb - 1; i++) {
for (size_t j = 0; j < nmemb - i - 1; j++) {
char *p1 = b + j * size;
char *p2 = b + (j + 1) * size;
if (compar(p1, p2) > 0) {
// Swap
if (size <= 256) {
memcpy(tmp, p1, size);
memcpy(p1, p2, size);
memcpy(p2, tmp, size);
}
}
}
}
}
int errno = 0;

View File

@ -17,6 +17,7 @@ var pause_start*: uint64 = 0
var fiber_ion: FiberObject
var fiber_nexshell: FiberObject
var fiber_ui: FiberObject
var fiber_subject: FiberObject
var fiber_watchdog: FiberObject
@ -96,6 +97,8 @@ proc rumpk_yield_internal() {.cdecl, exportc.} =
if current_fiber == addr fiber_ion:
switch(addr fiber_nexshell)
elif current_fiber == addr fiber_nexshell:
switch(addr fiber_ui)
elif current_fiber == addr fiber_ui:
switch(addr fiber_subject)
elif current_fiber == addr fiber_subject:
switch(addr fiber_watchdog)
@ -139,9 +142,12 @@ proc nimPanic(msg: cstring) {.exportc: "panic", cdecl, noreturn.} =
var stack_ion: array[32768, uint8]
var stack_nexshell: array[32768, uint8]
var stack_ui: array[32768, uint8]
var stack_subject: array[65536, uint8]
var stack_watchdog: array[4096, uint8]
proc ui_fiber_entry() {.importc, cdecl.}
proc subject_fiber_entry() {.cdecl.} =
launch_subject()
@ -244,11 +250,14 @@ proc kmain() {.exportc, cdecl.} =
# 2. NEXSHELL FIBER (The Brain)
init_fiber(addr fiber_nexshell, nexshell_main, addr stack_nexshell[0], sizeof(stack_nexshell))
# 3. SUBJECT FIBER (The Payload)
# 3. UI FIBER (The Face)
init_fiber(addr fiber_ui, ui_fiber_entry, addr stack_ui[0], sizeof(stack_ui))
# 4. SUBJECT FIBER (The Payload)
init_fiber(addr fiber_subject, subject_fiber_entry, addr stack_subject[0],
sizeof(stack_subject))
# 4. WATCHDOG FIBER (The Immune System)
# 5. WATCHDOG FIBER (The Immune System)
init_fiber(addr fiber_watchdog, watchdog_loop, addr stack_watchdog[0], sizeof(stack_watchdog))
# [FIX] GLOBAL INTERRUPT ENABLE

27
hal/framebuffer.zig Normal file
View File

@ -0,0 +1,27 @@
const std = @import("std");
pub const Rect = struct {
x: i32,
y: i32,
w: i32,
h: i32,
};
pub fn init() void {
// TODO: Init VirtIO GPU or PL111
}
pub fn set_clip(r: Rect) void {
// TODO: Set scissoring
_ = r;
}
pub fn fill_rect(x: i32, y: i32, w: i32, h: i32, color: u32) void {
// TODO: Plot to framebuffer
// For now, valid compilation is the goal.
_ = x;
_ = y;
_ = w;
_ = h;
_ = color;
}

128
hal/ui.zig Normal file
View File

@ -0,0 +1,128 @@
const std = @import("std");
const fb = @import("framebuffer.zig");
// Import the C Logic directly
pub const c = @cImport({
@cInclude("microui.h");
});
// --- STATIC MEMORY ---
var ctx: c.mu_Context = undefined;
// --- FONT (The "8-bit" classic) ---
// Minimal placeholder font (0-127 ascii) - 1KB
const font_bitmap: [128][8]u8 = [_][8]u8{[_]u8{0xFF} ** 8} ** 128; // Blocks for now
// --- CALL BACKS ---
fn text_width_cb(font: ?*anyopaque, str: [*c]const u8, len: c_int) callconv(.c) c_int {
_ = font;
// assuming 8x8 monospaced
// If len is -1, treat as null terminated
var l = len;
if (l == -1 and str != null) {
l = 0;
var s = str;
while (s[0] != 0) {
l += 1;
s += 1;
}
}
return l * 8;
}
fn text_height_cb(font: ?*anyopaque) callconv(.c) c_int {
_ = font;
return 8;
}
// --- THE RENDERER (The Paint Brush) ---
pub fn render() void {
var cmd: [*c]c.mu_Command = null;
// Iterate over microui command list
// Note: mu_next_command takes pointers
while (c.mu_next_command(&ctx, &cmd) != 0) {
switch (cmd.*.type) {
c.MU_COMMAND_TEXT => {
// draw_text(cmd.text.str, cmd.text.pos, cmd.text.color);
// For now, ignore text drawing to avoid font complexity in step 1
},
c.MU_COMMAND_RECT => {
draw_rect(cmd.*.rect.rect, cmd.*.rect.color);
},
c.MU_COMMAND_ICON => {
// TODO: Draw simple icons (close button X)
draw_rect(cmd.*.icon.rect, cmd.*.icon.color); // Placeholder
},
c.MU_COMMAND_CLIP => {
// fb.set_clip(cmd.clip.rect);
// Adaptation needed for C to Zig struct
fb.set_clip(.{
.x = cmd.*.clip.rect.x,
.y = cmd.*.clip.rect.y,
.w = cmd.*.clip.rect.w,
.h = cmd.*.clip.rect.h,
});
},
else => {},
}
}
}
// --- HELPER: Draw Rect ---
fn draw_rect(r: c.mu_Rect, color: c.mu_Color) void {
// Convert microui Color to ARGB
const argb = (@as(u32, 255) << 24) |
(@as(u32, color.r) << 16) |
(@as(u32, color.g) << 8) |
@as(u32, color.b);
// Plot to L0 Framebuffer
fb.fill_rect(r.x, r.y, r.w, r.h, argb);
}
// --- INITIALIZATION ---
pub fn init() void {
c.mu_init(&ctx);
// Hook up text width callback (Required by microui)
ctx.text_width = text_width_cb;
ctx.text_height = text_height_cb;
}
// --- KERNEL IMPORTS ---
extern fn fiber_yield() void;
// --- THE UI LOOP (Fiber Entry) ---
export fn ui_fiber_entry() void {
init();
while (true) {
// 1. Begin Frame
c.mu_begin(&ctx);
// 2. Define Layout (The Logic)
if (c.mu_begin_window(&ctx, "Nexus HUD", c.mu_rect(10, 10, 300, 200)) != 0) {
c.mu_layout_row(&ctx, 1, &[_]i32{-1}, 0);
c.mu_label(&ctx, "System Status: ONLINE");
c.mu_layout_row(&ctx, 2, &[_]i32{ 80, -1 }, 0);
c.mu_label(&ctx, "CPU:");
c.mu_draw_rect(&ctx, c.mu_rect(100, 50, 150, 20), c.mu_color(0, 255, 0, 255)); // Mock bar
if (c.mu_button(&ctx, "REBOOT") != 0) {
// Logic hook!
// send_command(CMD_REBOOT);
}
c.mu_end_window(&ctx);
}
// 3. End Frame & Paint
c.mu_end(&ctx);
render();
// 4. Yield
fiber_yield();
}
}

View File

@ -0,0 +1,9 @@
#ifndef _STDIO_H
#define _STDIO_H
typedef unsigned long size_t;
#define stderr ((void*)2)
int fprintf(void *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
int vsnprintf(char *str, size_t size, const char *format, __builtin_va_list ap);
#endif

View File

@ -0,0 +1,9 @@
#ifndef _STDLIB_H
#define _STDLIB_H
#define NULL ((void*)0)
typedef unsigned long size_t;
int abs(int x);
void abort(void);
double strtod(const char *nptr, char **endptr);
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
#endif

View File

@ -0,0 +1,8 @@
#ifndef _STRING_H
#define _STRING_H
typedef unsigned long size_t;
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
size_t strlen(const char *s);
#endif

1208
libs/microui/microui.c Normal file

File diff suppressed because it is too large Load Diff

296
libs/microui/microui.h Normal file
View File

@ -0,0 +1,296 @@
/*
** Copyright (c) 2024 rxi
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the MIT license. See `microui.c` for details.
*/
#ifndef MICROUI_H
#define MICROUI_H
#define MU_VERSION "2.02"
#define MU_COMMANDLIST_SIZE (256 * 1024)
#define MU_ROOTLIST_SIZE 32
#define MU_CONTAINERSTACK_SIZE 32
#define MU_CLIPSTACK_SIZE 32
#define MU_IDSTACK_SIZE 32
#define MU_LAYOUTSTACK_SIZE 16
#define MU_CONTAINERPOOL_SIZE 48
#define MU_TREENODEPOOL_SIZE 48
#define MU_MAX_WIDTHS 16
#define MU_REAL float
#define MU_REAL_FMT "%.3g"
#define MU_SLIDER_FMT "%.2f"
#define MU_MAX_FMT 127
#define mu_stack(T, n) struct { int idx; T items[n]; }
#define mu_min(a, b) ((a) < (b) ? (a) : (b))
#define mu_max(a, b) ((a) > (b) ? (a) : (b))
#define mu_clamp(x, a, b) mu_min(b, mu_max(a, x))
enum {
MU_CLIP_PART = 1,
MU_CLIP_ALL
};
enum {
MU_COMMAND_JUMP = 1,
MU_COMMAND_CLIP,
MU_COMMAND_RECT,
MU_COMMAND_TEXT,
MU_COMMAND_ICON,
MU_COMMAND_MAX
};
enum {
MU_COLOR_TEXT,
MU_COLOR_BORDER,
MU_COLOR_WINDOWBG,
MU_COLOR_TITLEBG,
MU_COLOR_TITLETEXT,
MU_COLOR_PANELBG,
MU_COLOR_BUTTON,
MU_COLOR_BUTTONHOVER,
MU_COLOR_BUTTONFOCUS,
MU_COLOR_BASE,
MU_COLOR_BASEHOVER,
MU_COLOR_BASEFOCUS,
MU_COLOR_SCROLLBASE,
MU_COLOR_SCROLLTHUMB,
MU_COLOR_MAX
};
enum {
MU_ICON_CLOSE = 1,
MU_ICON_CHECK,
MU_ICON_COLLAPSED,
MU_ICON_EXPANDED,
MU_ICON_MAX
};
enum {
MU_RES_ACTIVE = (1 << 0),
MU_RES_SUBMIT = (1 << 1),
MU_RES_CHANGE = (1 << 2)
};
enum {
MU_OPT_ALIGNCENTER = (1 << 0),
MU_OPT_ALIGNRIGHT = (1 << 1),
MU_OPT_NOINTERACT = (1 << 2),
MU_OPT_NOFRAME = (1 << 3),
MU_OPT_NORESIZE = (1 << 4),
MU_OPT_NOSCROLL = (1 << 5),
MU_OPT_NOCLOSE = (1 << 6),
MU_OPT_NOTITLE = (1 << 7),
MU_OPT_HOLDFOCUS = (1 << 8),
MU_OPT_AUTOSIZE = (1 << 9),
MU_OPT_POPUP = (1 << 10),
MU_OPT_CLOSED = (1 << 11),
MU_OPT_EXPANDED = (1 << 12)
};
enum {
MU_MOUSE_LEFT = (1 << 0),
MU_MOUSE_RIGHT = (1 << 1),
MU_MOUSE_MIDDLE = (1 << 2)
};
enum {
MU_KEY_SHIFT = (1 << 0),
MU_KEY_CTRL = (1 << 1),
MU_KEY_ALT = (1 << 2),
MU_KEY_BACKSPACE = (1 << 3),
MU_KEY_RETURN = (1 << 4)
};
typedef struct mu_Context mu_Context;
typedef unsigned mu_Id;
typedef MU_REAL mu_Real;
typedef void* mu_Font;
typedef struct { int x, y; } mu_Vec2;
typedef struct { int x, y, w, h; } mu_Rect;
typedef struct { unsigned char r, g, b, a; } mu_Color;
typedef struct { mu_Id id; int last_update; } mu_PoolItem;
typedef struct { int type, size; } mu_BaseCommand;
typedef struct { mu_BaseCommand base; void *dst; } mu_JumpCommand;
typedef struct { mu_BaseCommand base; mu_Rect rect; } mu_ClipCommand;
typedef struct { mu_BaseCommand base; mu_Rect rect; mu_Color color; } mu_RectCommand;
typedef struct { mu_BaseCommand base; mu_Font font; mu_Vec2 pos; mu_Color color; char str[1]; } mu_TextCommand;
typedef struct { mu_BaseCommand base; mu_Rect rect; int id; mu_Color color; } mu_IconCommand;
typedef union {
int type;
mu_BaseCommand base;
mu_JumpCommand jump;
mu_ClipCommand clip;
mu_RectCommand rect;
mu_TextCommand text;
mu_IconCommand icon;
} mu_Command;
typedef struct {
mu_Rect body;
mu_Rect next;
mu_Vec2 position;
mu_Vec2 size;
mu_Vec2 max;
int widths[MU_MAX_WIDTHS];
int items;
int item_index;
int next_row;
int next_type;
int indent;
} mu_Layout;
typedef struct {
mu_Command *head, *tail;
mu_Rect rect;
mu_Rect body;
mu_Vec2 content_size;
mu_Vec2 scroll;
int zindex;
int open;
} mu_Container;
typedef struct {
mu_Font font;
mu_Vec2 size;
int padding;
int spacing;
int indent;
int title_height;
int scrollbar_size;
int thumb_size;
mu_Color colors[MU_COLOR_MAX];
} mu_Style;
struct mu_Context {
/* callbacks */
int (*text_width)(mu_Font font, const char *str, int len);
int (*text_height)(mu_Font font);
void (*draw_frame)(mu_Context *ctx, mu_Rect rect, int colorid);
/* core state */
mu_Style _style;
mu_Style *style;
mu_Id hover;
mu_Id focus;
mu_Id last_id;
mu_Rect last_rect;
int last_zindex;
int updated_focus;
int frame;
mu_Container *hover_root;
mu_Container *next_hover_root;
mu_Container *scroll_target;
char number_edit_buf[MU_MAX_FMT];
mu_Id number_edit;
/* stacks */
mu_stack(char, MU_COMMANDLIST_SIZE) command_list;
mu_stack(mu_Container*, MU_ROOTLIST_SIZE) root_list;
mu_stack(mu_Container*, MU_CONTAINERSTACK_SIZE) container_stack;
mu_stack(mu_Rect, MU_CLIPSTACK_SIZE) clip_stack;
mu_stack(mu_Id, MU_IDSTACK_SIZE) id_stack;
mu_stack(mu_Layout, MU_LAYOUTSTACK_SIZE) layout_stack;
/* retained state pools */
mu_PoolItem container_pool[MU_CONTAINERPOOL_SIZE];
mu_Container containers[MU_CONTAINERPOOL_SIZE];
mu_PoolItem treenode_pool[MU_TREENODEPOOL_SIZE];
/* input state */
mu_Vec2 mouse_pos;
mu_Vec2 last_mouse_pos;
mu_Vec2 mouse_delta;
mu_Vec2 scroll_delta;
int mouse_down;
int mouse_pressed;
int key_down;
int key_pressed;
char input_text[32];
};
mu_Vec2 mu_vec2(int x, int y);
mu_Rect mu_rect(int x, int y, int w, int h);
mu_Color mu_color(int r, int g, int b, int a);
void mu_init(mu_Context *ctx);
void mu_begin(mu_Context *ctx);
void mu_end(mu_Context *ctx);
void mu_set_focus(mu_Context *ctx, mu_Id id);
mu_Id mu_get_id(mu_Context *ctx, const void *data, int size);
void mu_push_id(mu_Context *ctx, const void *data, int size);
void mu_pop_id(mu_Context *ctx);
void mu_push_clip_rect(mu_Context *ctx, mu_Rect rect);
void mu_pop_clip_rect(mu_Context *ctx);
mu_Rect mu_get_clip_rect(mu_Context *ctx);
int mu_check_clip(mu_Context *ctx, mu_Rect r);
mu_Container* mu_get_current_container(mu_Context *ctx);
mu_Container* mu_get_container(mu_Context *ctx, const char *name);
void mu_bring_to_front(mu_Context *ctx, mu_Container *cnt);
int mu_pool_init(mu_Context *ctx, mu_PoolItem *items, int len, mu_Id id);
int mu_pool_get(mu_Context *ctx, mu_PoolItem *items, int len, mu_Id id);
void mu_pool_update(mu_Context *ctx, mu_PoolItem *items, int idx);
void mu_input_mousemove(mu_Context *ctx, int x, int y);
void mu_input_mousedown(mu_Context *ctx, int x, int y, int btn);
void mu_input_mouseup(mu_Context *ctx, int x, int y, int btn);
void mu_input_scroll(mu_Context *ctx, int x, int y);
void mu_input_keydown(mu_Context *ctx, int key);
void mu_input_keyup(mu_Context *ctx, int key);
void mu_input_text(mu_Context *ctx, const char *text);
mu_Command* mu_push_command(mu_Context *ctx, int type, int size);
int mu_next_command(mu_Context *ctx, mu_Command **cmd);
void mu_set_clip(mu_Context *ctx, mu_Rect rect);
void mu_draw_rect(mu_Context *ctx, mu_Rect rect, mu_Color color);
void mu_draw_box(mu_Context *ctx, mu_Rect rect, mu_Color color);
void mu_draw_text(mu_Context *ctx, mu_Font font, const char *str, int len, mu_Vec2 pos, mu_Color color);
void mu_draw_icon(mu_Context *ctx, int id, mu_Rect rect, mu_Color color);
void mu_layout_row(mu_Context *ctx, int items, const int *widths, int height);
void mu_layout_width(mu_Context *ctx, int width);
void mu_layout_height(mu_Context *ctx, int height);
void mu_layout_begin_column(mu_Context *ctx);
void mu_layout_end_column(mu_Context *ctx);
void mu_layout_set_next(mu_Context *ctx, mu_Rect r, int relative);
mu_Rect mu_layout_next(mu_Context *ctx);
void mu_draw_control_frame(mu_Context *ctx, mu_Id id, mu_Rect rect, int colorid, int opt);
void mu_draw_control_text(mu_Context *ctx, const char *str, mu_Rect rect, int colorid, int opt);
int mu_mouse_over(mu_Context *ctx, mu_Rect rect);
void mu_update_control(mu_Context *ctx, mu_Id id, mu_Rect rect, int opt);
#define mu_button(ctx, label) mu_button_ex(ctx, label, 0, MU_OPT_ALIGNCENTER)
#define mu_textbox(ctx, buf, bufsz) mu_textbox_ex(ctx, buf, bufsz, 0)
#define mu_slider(ctx, value, lo, hi) mu_slider_ex(ctx, value, lo, hi, 0, MU_SLIDER_FMT, MU_OPT_ALIGNCENTER)
#define mu_number(ctx, value, step) mu_number_ex(ctx, value, step, MU_SLIDER_FMT, MU_OPT_ALIGNCENTER)
#define mu_header(ctx, label) mu_header_ex(ctx, label, 0)
#define mu_begin_treenode(ctx, label) mu_begin_treenode_ex(ctx, label, 0)
#define mu_begin_window(ctx, title, rect) mu_begin_window_ex(ctx, title, rect, 0)
#define mu_begin_panel(ctx, name) mu_begin_panel_ex(ctx, name, 0)
void mu_text(mu_Context *ctx, const char *text);
void mu_label(mu_Context *ctx, const char *text);
int mu_button_ex(mu_Context *ctx, const char *label, int icon, int opt);
int mu_checkbox(mu_Context *ctx, const char *label, int *state);
int mu_textbox_raw(mu_Context *ctx, char *buf, int bufsz, mu_Id id, mu_Rect r, int opt);
int mu_textbox_ex(mu_Context *ctx, char *buf, int bufsz, int opt);
int mu_slider_ex(mu_Context *ctx, mu_Real *value, mu_Real low, mu_Real high, mu_Real step, const char *fmt, int opt);
int mu_number_ex(mu_Context *ctx, mu_Real *value, mu_Real step, const char *fmt, int opt);
int mu_header_ex(mu_Context *ctx, const char *label, int opt);
int mu_begin_treenode_ex(mu_Context *ctx, const char *label, int opt);
void mu_end_treenode(mu_Context *ctx);
int mu_begin_window_ex(mu_Context *ctx, const char *title, mu_Rect rect, int opt);
void mu_end_window(mu_Context *ctx);
void mu_open_popup(mu_Context *ctx, const char *name);
int mu_begin_popup(mu_Context *ctx, const char *name);
void mu_end_popup(mu_Context *ctx);
void mu_begin_panel_ex(mu_Context *ctx, const char *name, int opt);
void mu_end_panel(mu_Context *ctx);
#endif