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"
|
mv nexshell.o "$BUILD_DIR/nexshell.o"
|
||||||
echo " → $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
|
# Step 2: Compile context switch assembly
|
||||||
# =========================================================
|
# =========================================================
|
||||||
|
|
@ -122,6 +135,22 @@ zig cc \
|
||||||
-o "$BUILD_DIR/monocypher.o"
|
-o "$BUILD_DIR/monocypher.o"
|
||||||
echo " → $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)
|
# Step 2.2: Compile LwIP (Kernel Stack)
|
||||||
# =========================================================
|
# =========================================================
|
||||||
|
|
@ -515,6 +544,8 @@ $LINKER \
|
||||||
"$BUILD_DIR/overrides.o" \
|
"$BUILD_DIR/overrides.o" \
|
||||||
"$BUILD_DIR/loader.o" \
|
"$BUILD_DIR/loader.o" \
|
||||||
"$BUILD_DIR/nexshell.o" \
|
"$BUILD_DIR/nexshell.o" \
|
||||||
|
"$BUILD_DIR/ui.o" \
|
||||||
|
"$BUILD_DIR/microui.o" \
|
||||||
$NIM_OBJS \
|
$NIM_OBJS \
|
||||||
-o "$BUILD_DIR/rumpk-$ARCH.elf"
|
-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.red_zone = false;
|
||||||
hal.root_module.stack_check = .none;
|
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);
|
b.installArtifact(hal);
|
||||||
|
|
||||||
// =========================================================
|
// =========================================================
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,49 @@ int fprintf(void *stream, const char *format, ...) {
|
||||||
return printf(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) {
|
int fflush(void *stream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -183,5 +226,44 @@ int atoi(const char *nptr) {
|
||||||
return res;
|
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;
|
int errno = 0;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ var pause_start*: uint64 = 0
|
||||||
|
|
||||||
var fiber_ion: FiberObject
|
var fiber_ion: FiberObject
|
||||||
var fiber_nexshell: FiberObject
|
var fiber_nexshell: FiberObject
|
||||||
|
var fiber_ui: FiberObject
|
||||||
var fiber_subject: FiberObject
|
var fiber_subject: FiberObject
|
||||||
var fiber_watchdog: FiberObject
|
var fiber_watchdog: FiberObject
|
||||||
|
|
||||||
|
|
@ -96,6 +97,8 @@ proc rumpk_yield_internal() {.cdecl, exportc.} =
|
||||||
if current_fiber == addr fiber_ion:
|
if current_fiber == addr fiber_ion:
|
||||||
switch(addr fiber_nexshell)
|
switch(addr fiber_nexshell)
|
||||||
elif current_fiber == addr fiber_nexshell:
|
elif current_fiber == addr fiber_nexshell:
|
||||||
|
switch(addr fiber_ui)
|
||||||
|
elif current_fiber == addr fiber_ui:
|
||||||
switch(addr fiber_subject)
|
switch(addr fiber_subject)
|
||||||
elif current_fiber == addr fiber_subject:
|
elif current_fiber == addr fiber_subject:
|
||||||
switch(addr fiber_watchdog)
|
switch(addr fiber_watchdog)
|
||||||
|
|
@ -139,9 +142,12 @@ proc nimPanic(msg: cstring) {.exportc: "panic", cdecl, noreturn.} =
|
||||||
|
|
||||||
var stack_ion: array[32768, uint8]
|
var stack_ion: array[32768, uint8]
|
||||||
var stack_nexshell: array[32768, uint8]
|
var stack_nexshell: array[32768, uint8]
|
||||||
|
var stack_ui: array[32768, uint8]
|
||||||
var stack_subject: array[65536, uint8]
|
var stack_subject: array[65536, uint8]
|
||||||
var stack_watchdog: array[4096, uint8]
|
var stack_watchdog: array[4096, uint8]
|
||||||
|
|
||||||
|
proc ui_fiber_entry() {.importc, cdecl.}
|
||||||
|
|
||||||
proc subject_fiber_entry() {.cdecl.} =
|
proc subject_fiber_entry() {.cdecl.} =
|
||||||
launch_subject()
|
launch_subject()
|
||||||
|
|
||||||
|
|
@ -244,11 +250,14 @@ proc kmain() {.exportc, cdecl.} =
|
||||||
# 2. NEXSHELL FIBER (The Brain)
|
# 2. NEXSHELL FIBER (The Brain)
|
||||||
init_fiber(addr fiber_nexshell, nexshell_main, addr stack_nexshell[0], sizeof(stack_nexshell))
|
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],
|
init_fiber(addr fiber_subject, subject_fiber_entry, addr stack_subject[0],
|
||||||
sizeof(stack_subject))
|
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))
|
init_fiber(addr fiber_watchdog, watchdog_loop, addr stack_watchdog[0], sizeof(stack_watchdog))
|
||||||
|
|
||||||
# [FIX] GLOBAL INTERRUPT ENABLE
|
# [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