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:
parent
bcba945557
commit
8aa50eb3ef
31
build.sh
31
build.sh
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
// =========================================================
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
Loading…
Reference in New Issue