Format all
This commit is contained in:
@@ -18,8 +18,8 @@ F32 g_ui_scale = 1.0f;
|
||||
////////////////////////////////
|
||||
// Theme global
|
||||
|
||||
UI_Theme g_theme = {};
|
||||
S32 g_theme_id = 0;
|
||||
UI_Theme g_theme = {};
|
||||
S32 g_theme_id = 0;
|
||||
|
||||
void ui_set_theme(S32 theme_id) {
|
||||
g_theme_id = theme_id;
|
||||
@@ -27,55 +27,55 @@ void ui_set_theme(S32 theme_id) {
|
||||
switch (theme_id) {
|
||||
default:
|
||||
case 0: // Dark
|
||||
g_theme.bg_dark = Clay_Color{ 26, 26, 26, 255};
|
||||
g_theme.bg_medium = Clay_Color{ 36, 36, 36, 255};
|
||||
g_theme.bg_light = Clay_Color{ 46, 46, 46, 255};
|
||||
g_theme.bg_lighter = Clay_Color{ 54, 54, 54, 255};
|
||||
g_theme.border = Clay_Color{ 52, 52, 52, 255};
|
||||
g_theme.text = Clay_Color{220, 220, 220, 255};
|
||||
g_theme.text_dim = Clay_Color{105, 105, 105, 255};
|
||||
g_theme.accent = Clay_Color{ 87, 138, 176, 255};
|
||||
g_theme.accent_hover = Clay_Color{102, 153, 191, 255};
|
||||
g_theme.button_text = Clay_Color{224, 224, 224, 255};
|
||||
g_theme.disabled_bg = Clay_Color{ 44, 44, 44, 255};
|
||||
g_theme.disabled_text = Clay_Color{ 90, 90, 90, 255};
|
||||
g_theme.header_bg = Clay_Color{ 46, 46, 46, 255};
|
||||
g_theme.title_bar = Clay_Color{ 22, 22, 22, 255};
|
||||
g_theme.scrollbar_bg = Clay_Color{ 22, 22, 22, 255};
|
||||
g_theme.scrollbar_grab = Clay_Color{ 58, 58, 58, 255};
|
||||
g_theme.shadow = Clay_Color{ 0, 0, 0, 30};
|
||||
g_theme.tab_active_top = Clay_Color{ 70, 120, 160, 255};
|
||||
g_theme.tab_active_bottom= Clay_Color{ 30, 55, 80, 255};
|
||||
g_theme.tab_inactive = Clay_Color{ 40, 40, 40, 255};
|
||||
g_theme.tab_inactive_hover= Clay_Color{ 50, 50, 50, 255};
|
||||
g_theme.tab_text = Clay_Color{240, 240, 240, 255};
|
||||
g_theme.corner_radius = 4.0f;
|
||||
g_theme.bg_dark = Clay_Color{ 26, 26, 26, 255 };
|
||||
g_theme.bg_medium = Clay_Color{ 36, 36, 36, 255 };
|
||||
g_theme.bg_light = Clay_Color{ 46, 46, 46, 255 };
|
||||
g_theme.bg_lighter = Clay_Color{ 54, 54, 54, 255 };
|
||||
g_theme.border = Clay_Color{ 52, 52, 52, 255 };
|
||||
g_theme.text = Clay_Color{ 220, 220, 220, 255 };
|
||||
g_theme.text_dim = Clay_Color{ 105, 105, 105, 255 };
|
||||
g_theme.accent = Clay_Color{ 87, 138, 176, 255 };
|
||||
g_theme.accent_hover = Clay_Color{ 102, 153, 191, 255 };
|
||||
g_theme.button_text = Clay_Color{ 224, 224, 224, 255 };
|
||||
g_theme.disabled_bg = Clay_Color{ 44, 44, 44, 255 };
|
||||
g_theme.disabled_text = Clay_Color{ 90, 90, 90, 255 };
|
||||
g_theme.header_bg = Clay_Color{ 46, 46, 46, 255 };
|
||||
g_theme.title_bar = Clay_Color{ 22, 22, 22, 255 };
|
||||
g_theme.scrollbar_bg = Clay_Color{ 22, 22, 22, 255 };
|
||||
g_theme.scrollbar_grab = Clay_Color{ 58, 58, 58, 255 };
|
||||
g_theme.shadow = Clay_Color{ 0, 0, 0, 30 };
|
||||
g_theme.tab_active_top = Clay_Color{ 70, 120, 160, 255 };
|
||||
g_theme.tab_active_bottom = Clay_Color{ 30, 55, 80, 255 };
|
||||
g_theme.tab_inactive = Clay_Color{ 40, 40, 40, 255 };
|
||||
g_theme.tab_inactive_hover = Clay_Color{ 50, 50, 50, 255 };
|
||||
g_theme.tab_text = Clay_Color{ 240, 240, 240, 255 };
|
||||
g_theme.corner_radius = 4.0f;
|
||||
break;
|
||||
|
||||
case 1: // Light
|
||||
g_theme.bg_dark = Clay_Color{195, 193, 190, 255};
|
||||
g_theme.bg_medium = Clay_Color{212, 210, 207, 255};
|
||||
g_theme.bg_light = Clay_Color{225, 223, 220, 255};
|
||||
g_theme.bg_lighter = Clay_Color{232, 230, 227, 255};
|
||||
g_theme.border = Clay_Color{178, 176, 173, 255};
|
||||
g_theme.text = Clay_Color{ 35, 33, 30, 255};
|
||||
g_theme.text_dim = Clay_Color{115, 113, 108, 255};
|
||||
g_theme.accent = Clay_Color{ 50, 110, 170, 255};
|
||||
g_theme.accent_hover = Clay_Color{ 65, 125, 185, 255};
|
||||
g_theme.button_text = Clay_Color{255, 255, 255, 255};
|
||||
g_theme.disabled_bg = Clay_Color{185, 183, 180, 255};
|
||||
g_theme.disabled_text = Clay_Color{145, 143, 140, 255};
|
||||
g_theme.header_bg = Clay_Color{202, 200, 197, 255};
|
||||
g_theme.title_bar = Clay_Color{202, 200, 197, 255};
|
||||
g_theme.scrollbar_bg = Clay_Color{202, 200, 197, 255};
|
||||
g_theme.scrollbar_grab = Clay_Color{168, 166, 163, 255};
|
||||
g_theme.shadow = Clay_Color{ 0, 0, 0, 18};
|
||||
g_theme.tab_active_top = Clay_Color{ 70, 130, 180, 255};
|
||||
g_theme.tab_active_bottom= Clay_Color{ 50, 100, 150, 255};
|
||||
g_theme.tab_inactive = Clay_Color{205, 203, 200, 255};
|
||||
g_theme.tab_inactive_hover= Clay_Color{195, 193, 190, 255};
|
||||
g_theme.tab_text = Clay_Color{255, 255, 255, 255};
|
||||
g_theme.corner_radius = 4.0f;
|
||||
g_theme.bg_dark = Clay_Color{ 195, 193, 190, 255 };
|
||||
g_theme.bg_medium = Clay_Color{ 212, 210, 207, 255 };
|
||||
g_theme.bg_light = Clay_Color{ 225, 223, 220, 255 };
|
||||
g_theme.bg_lighter = Clay_Color{ 232, 230, 227, 255 };
|
||||
g_theme.border = Clay_Color{ 178, 176, 173, 255 };
|
||||
g_theme.text = Clay_Color{ 35, 33, 30, 255 };
|
||||
g_theme.text_dim = Clay_Color{ 115, 113, 108, 255 };
|
||||
g_theme.accent = Clay_Color{ 50, 110, 170, 255 };
|
||||
g_theme.accent_hover = Clay_Color{ 65, 125, 185, 255 };
|
||||
g_theme.button_text = Clay_Color{ 255, 255, 255, 255 };
|
||||
g_theme.disabled_bg = Clay_Color{ 185, 183, 180, 255 };
|
||||
g_theme.disabled_text = Clay_Color{ 145, 143, 140, 255 };
|
||||
g_theme.header_bg = Clay_Color{ 202, 200, 197, 255 };
|
||||
g_theme.title_bar = Clay_Color{ 202, 200, 197, 255 };
|
||||
g_theme.scrollbar_bg = Clay_Color{ 202, 200, 197, 255 };
|
||||
g_theme.scrollbar_grab = Clay_Color{ 168, 166, 163, 255 };
|
||||
g_theme.shadow = Clay_Color{ 0, 0, 0, 18 };
|
||||
g_theme.tab_active_top = Clay_Color{ 70, 130, 180, 255 };
|
||||
g_theme.tab_active_bottom = Clay_Color{ 50, 100, 150, 255 };
|
||||
g_theme.tab_inactive = Clay_Color{ 205, 203, 200, 255 };
|
||||
g_theme.tab_inactive_hover = Clay_Color{ 195, 193, 190, 255 };
|
||||
g_theme.tab_text = Clay_Color{ 255, 255, 255, 255 };
|
||||
g_theme.corner_radius = 4.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ S32 g_accent_id = 0;
|
||||
|
||||
void ui_set_accent(S32 accent_id) {
|
||||
g_accent_id = accent_id;
|
||||
B32 dark = (g_theme_id == 0);
|
||||
B32 dark = (g_theme_id == 0);
|
||||
|
||||
// Each palette: accent, accent_hover, tab_top, tab_bottom, button_text, tab_text
|
||||
struct AccentColors {
|
||||
@@ -97,44 +97,44 @@ void ui_set_accent(S32 accent_id) {
|
||||
// Dark-mode palettes
|
||||
static const AccentColors dark_palettes[] = {
|
||||
// 0: Blue
|
||||
{ {87,138,176,255}, {102,153,191,255}, {70,120,160,255}, {30,55,80,255}, {224,224,224,255}, {240,240,240,255} },
|
||||
{ { 87, 138, 176, 255 }, { 102, 153, 191, 255 }, { 70, 120, 160, 255 }, { 30, 55, 80, 255 }, { 224, 224, 224, 255 }, { 240, 240, 240, 255 } },
|
||||
// 1: Turquoise
|
||||
{ {60,160,155,255}, {75,175,170,255}, {50,140,135,255}, {25,70,68,255}, {224,224,224,255}, {240,240,240,255} },
|
||||
{ { 60, 160, 155, 255 }, { 75, 175, 170, 255 }, { 50, 140, 135, 255 }, { 25, 70, 68, 255 }, { 224, 224, 224, 255 }, { 240, 240, 240, 255 } },
|
||||
// 2: Orange
|
||||
{ {200,130,50,255}, {215,145,65,255}, {190,120,40,255}, {100,60,20,255}, {240,240,240,255}, {240,240,240,255} },
|
||||
{ { 200, 130, 50, 255 }, { 215, 145, 65, 255 }, { 190, 120, 40, 255 }, { 100, 60, 20, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
|
||||
// 3: Purple
|
||||
{ {130,100,180,255}, {145,115,195,255}, {120,90,170,255}, {60,45,85,255}, {224,224,224,255}, {240,240,240,255} },
|
||||
{ { 130, 100, 180, 255 }, { 145, 115, 195, 255 }, { 120, 90, 170, 255 }, { 60, 45, 85, 255 }, { 224, 224, 224, 255 }, { 240, 240, 240, 255 } },
|
||||
// 4: Pink
|
||||
{ {185,95,140,255}, {200,110,155,255}, {175,85,130,255}, {88,42,65,255}, {240,240,240,255}, {240,240,240,255} },
|
||||
{ { 185, 95, 140, 255 }, { 200, 110, 155, 255 }, { 175, 85, 130, 255 }, { 88, 42, 65, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
|
||||
// 5: Red
|
||||
{ {190,75,75,255}, {205,90,90,255}, {180,65,65,255}, {90,32,32,255}, {240,240,240,255}, {240,240,240,255} },
|
||||
{ { 190, 75, 75, 255 }, { 205, 90, 90, 255 }, { 180, 65, 65, 255 }, { 90, 32, 32, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
|
||||
// 6: Green
|
||||
{ {80,155,80,255}, {95,170,95,255}, {70,140,70,255}, {35,70,35,255}, {240,240,240,255}, {240,240,240,255} },
|
||||
{ { 80, 155, 80, 255 }, { 95, 170, 95, 255 }, { 70, 140, 70, 255 }, { 35, 70, 35, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
|
||||
};
|
||||
|
||||
// Light-mode palettes (slightly more saturated for contrast on light bg)
|
||||
static const AccentColors light_palettes[] = {
|
||||
// 0: Blue
|
||||
{ {50,110,170,255}, {65,125,185,255}, {70,130,180,255}, {50,100,150,255}, {255,255,255,255}, {255,255,255,255} },
|
||||
{ { 50, 110, 170, 255 }, { 65, 125, 185, 255 }, { 70, 130, 180, 255 }, { 50, 100, 150, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
|
||||
// 1: Turquoise
|
||||
{ {30,140,135,255}, {45,155,150,255}, {40,150,145,255}, {25,115,110,255}, {255,255,255,255}, {255,255,255,255} },
|
||||
{ { 30, 140, 135, 255 }, { 45, 155, 150, 255 }, { 40, 150, 145, 255 }, { 25, 115, 110, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
|
||||
// 2: Orange
|
||||
{ {190,115,25,255}, {205,130,40,255}, {195,120,30,255}, {155,90,15,255}, {255,255,255,255}, {255,255,255,255} },
|
||||
{ { 190, 115, 25, 255 }, { 205, 130, 40, 255 }, { 195, 120, 30, 255 }, { 155, 90, 15, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
|
||||
// 3: Purple
|
||||
{ {110,75,170,255}, {125,90,185,255}, {115,80,175,255}, {85,55,140,255}, {255,255,255,255}, {255,255,255,255} },
|
||||
{ { 110, 75, 170, 255 }, { 125, 90, 185, 255 }, { 115, 80, 175, 255 }, { 85, 55, 140, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
|
||||
// 4: Pink
|
||||
{ {175,70,125,255}, {190,85,140,255}, {180,75,130,255}, {140,50,100,255}, {255,255,255,255}, {255,255,255,255} },
|
||||
{ { 175, 70, 125, 255 }, { 190, 85, 140, 255 }, { 180, 75, 130, 255 }, { 140, 50, 100, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
|
||||
// 5: Red
|
||||
{ {185,55,55,255}, {200,70,70,255}, {190,60,60,255}, {150,40,40,255}, {255,255,255,255}, {255,255,255,255} },
|
||||
{ { 185, 55, 55, 255 }, { 200, 70, 70, 255 }, { 190, 60, 60, 255 }, { 150, 40, 40, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
|
||||
// 6: Green
|
||||
{ {55,140,55,255}, {70,155,70,255}, {60,145,60,255}, {40,110,40,255}, {255,255,255,255}, {255,255,255,255} },
|
||||
{ { 55, 140, 55, 255 }, { 70, 155, 70, 255 }, { 60, 145, 60, 255 }, { 40, 110, 40, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
|
||||
};
|
||||
|
||||
S32 idx = accent_id;
|
||||
if (idx < 0) idx = 0;
|
||||
if (idx > 6) idx = 6;
|
||||
|
||||
const AccentColors &c = dark ? dark_palettes[idx] : light_palettes[idx];
|
||||
const AccentColors &c = dark ? dark_palettes[idx] : light_palettes[idx];
|
||||
g_theme.accent = c.accent;
|
||||
g_theme.accent_hover = c.accent_hover;
|
||||
g_theme.tab_active_top = c.tab_top;
|
||||
@@ -148,7 +148,7 @@ void ui_set_accent(S32 accent_id) {
|
||||
|
||||
static void clay_error_handler(Clay_ErrorData error) {
|
||||
char buf[512];
|
||||
S32 len = error.errorText.length < 511 ? error.errorText.length : 511;
|
||||
S32 len = error.errorText.length < 511 ? error.errorText.length : 511;
|
||||
memcpy(buf, error.errorText.chars, len);
|
||||
buf[len] = '\0';
|
||||
fprintf(stderr, "[Clay Error] %s\n", buf);
|
||||
@@ -163,10 +163,10 @@ static UI_Context *g_measure_ctx = nullptr;
|
||||
static Clay_Dimensions clay_measure_text(Clay_StringSlice text, Clay_TextElementConfig *config, void *user_data) {
|
||||
UI_Context *ctx = (UI_Context *)user_data;
|
||||
if (!ctx || !ctx->measure_text_fn || text.length == 0) {
|
||||
return Clay_Dimensions{0, (F32)config->fontSize};
|
||||
return Clay_Dimensions{ 0, (F32)config->fontSize };
|
||||
}
|
||||
Vec2F32 result = ctx->measure_text_fn(text.chars, text.length, (F32)config->fontSize, ctx->measure_text_user_data);
|
||||
return Clay_Dimensions{result.x, result.y};
|
||||
return Clay_Dimensions{ result.x, result.y };
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -175,17 +175,17 @@ static Clay_Dimensions clay_measure_text(Clay_StringSlice text, Clay_TextElement
|
||||
UI_Context *ui_create(F32 viewport_w, F32 viewport_h) {
|
||||
UI_Context *ctx = (UI_Context *)calloc(1, sizeof(UI_Context));
|
||||
|
||||
U32 min_memory = Clay_MinMemorySize();
|
||||
ctx->clay_memory = malloc(min_memory);
|
||||
U32 min_memory = Clay_MinMemorySize();
|
||||
ctx->clay_memory = malloc(min_memory);
|
||||
Clay_Arena clay_arena = Clay_CreateArenaWithCapacityAndMemory(min_memory, ctx->clay_memory);
|
||||
|
||||
Clay_ErrorHandler err_handler = {};
|
||||
Clay_ErrorHandler err_handler = {};
|
||||
err_handler.errorHandlerFunction = clay_error_handler;
|
||||
err_handler.userData = ctx;
|
||||
err_handler.userData = ctx;
|
||||
|
||||
ctx->clay_ctx = Clay_Initialize(clay_arena,
|
||||
Clay_Dimensions{viewport_w, viewport_h},
|
||||
err_handler);
|
||||
Clay_Dimensions{ viewport_w, viewport_h },
|
||||
err_handler);
|
||||
|
||||
Clay_SetMeasureTextFunction(clay_measure_text, ctx);
|
||||
|
||||
@@ -200,13 +200,12 @@ void ui_destroy(UI_Context *ctx) {
|
||||
|
||||
void ui_begin_frame(UI_Context *ctx, F32 viewport_w, F32 viewport_h,
|
||||
Vec2F32 mouse_pos, B32 mouse_down,
|
||||
Vec2F32 scroll_delta, F32 dt)
|
||||
{
|
||||
Vec2F32 scroll_delta, F32 dt) {
|
||||
g_measure_ctx = ctx;
|
||||
Clay_SetCurrentContext(ctx->clay_ctx);
|
||||
Clay_SetLayoutDimensions(Clay_Dimensions{viewport_w, viewport_h});
|
||||
Clay_SetPointerState(Clay_Vector2{mouse_pos.x, mouse_pos.y}, mouse_down != 0);
|
||||
Clay_UpdateScrollContainers(false, Clay_Vector2{scroll_delta.x, scroll_delta.y}, dt);
|
||||
Clay_SetLayoutDimensions(Clay_Dimensions{ viewport_w, viewport_h });
|
||||
Clay_SetPointerState(Clay_Vector2{ mouse_pos.x, mouse_pos.y }, mouse_down != 0);
|
||||
Clay_UpdateScrollContainers(false, Clay_Vector2{ scroll_delta.x, scroll_delta.y }, dt);
|
||||
Clay_BeginLayout();
|
||||
}
|
||||
|
||||
@@ -216,7 +215,7 @@ Clay_RenderCommandArray ui_end_frame(UI_Context *ctx) {
|
||||
}
|
||||
|
||||
void ui_set_measure_text_fn(UI_Context *ctx, UI_MeasureTextFn fn, void *user_data) {
|
||||
ctx->measure_text_fn = fn;
|
||||
ctx->measure_text_fn = fn;
|
||||
ctx->measure_text_user_data = user_data;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ typedef Vec2F32 (*UI_MeasureTextFn)(const char *text, S32 length, F32 font_size,
|
||||
// UI Context
|
||||
|
||||
struct UI_Context {
|
||||
Clay_Context *clay_ctx;
|
||||
void *clay_memory;
|
||||
Clay_Context *clay_ctx;
|
||||
void *clay_memory;
|
||||
|
||||
// Text measurement
|
||||
UI_MeasureTextFn measure_text_fn;
|
||||
@@ -65,28 +65,28 @@ struct UI_Theme {
|
||||
Clay_Color title_bar;
|
||||
Clay_Color scrollbar_bg;
|
||||
Clay_Color scrollbar_grab;
|
||||
Clay_Color shadow; // Semi-transparent black for drop shadows
|
||||
Clay_Color shadow; // Semi-transparent black for drop shadows
|
||||
|
||||
// Tab bar colors
|
||||
Clay_Color tab_active_top;
|
||||
Clay_Color tab_active_bottom;
|
||||
Clay_Color tab_inactive;
|
||||
Clay_Color tab_inactive_hover;
|
||||
Clay_Color tab_text; // Always light — readable on colored tab gradient
|
||||
Clay_Color tab_text; // Always light — readable on colored tab gradient
|
||||
|
||||
// Corner radius (unscaled pixels, applied via uis())
|
||||
F32 corner_radius;
|
||||
};
|
||||
|
||||
extern UI_Theme g_theme;
|
||||
extern S32 g_theme_id;
|
||||
extern S32 g_theme_id;
|
||||
|
||||
// Set theme by index: 0 = Dark, 1 = Light
|
||||
void ui_set_theme(S32 theme_id);
|
||||
|
||||
// Accent color palette: 0=Blue, 1=Turquoise, 2=Orange, 3=Purple, 4=Pink, 5=Red, 6=Green
|
||||
extern S32 g_accent_id;
|
||||
void ui_set_accent(S32 accent_id);
|
||||
void ui_set_accent(S32 accent_id);
|
||||
|
||||
////////////////////////////////
|
||||
// UI scale (Cmd+/Cmd- zoom)
|
||||
@@ -105,37 +105,37 @@ static inline U16 uifs(F32 x) { return (U16)(x * g_ui_scale + 0.5f); }
|
||||
////////////////////////////////
|
||||
// Tab styling
|
||||
|
||||
#define TAB_ACTIVE_TOP g_theme.tab_active_top
|
||||
#define TAB_ACTIVE_BOTTOM g_theme.tab_active_bottom
|
||||
#define TAB_INACTIVE_BG g_theme.tab_inactive
|
||||
#define TAB_INACTIVE_HOVER g_theme.tab_inactive_hover
|
||||
#define TAB_HEIGHT uis(26)
|
||||
#define TAB_CORNER_RADIUS CORNER_RADIUS
|
||||
#define TAB_PADDING_H uip(10)
|
||||
#define TAB_ACTIVE_TOP g_theme.tab_active_top
|
||||
#define TAB_ACTIVE_BOTTOM g_theme.tab_active_bottom
|
||||
#define TAB_INACTIVE_BG g_theme.tab_inactive
|
||||
#define TAB_INACTIVE_HOVER g_theme.tab_inactive_hover
|
||||
#define TAB_HEIGHT uis(26)
|
||||
#define TAB_CORNER_RADIUS CORNER_RADIUS
|
||||
#define TAB_PADDING_H uip(10)
|
||||
|
||||
////////////////////////////////
|
||||
// Custom render types (for gradient rects via CLAY_RENDER_COMMAND_TYPE_CUSTOM)
|
||||
|
||||
enum CustomRenderType {
|
||||
CUSTOM_RENDER_VGRADIENT = 1,
|
||||
CUSTOM_RENDER_ICON = 2,
|
||||
CUSTOM_RENDER_VGRADIENT = 1,
|
||||
CUSTOM_RENDER_ICON = 2,
|
||||
CUSTOM_RENDER_ROTATED_ICON = 3,
|
||||
};
|
||||
|
||||
struct CustomGradientData {
|
||||
CustomRenderType type;
|
||||
Clay_Color top_color;
|
||||
Clay_Color bottom_color;
|
||||
Clay_Color top_color;
|
||||
Clay_Color bottom_color;
|
||||
};
|
||||
|
||||
struct CustomIconData {
|
||||
CustomRenderType type; // CUSTOM_RENDER_ICON
|
||||
CustomRenderType type; // CUSTOM_RENDER_ICON
|
||||
S32 icon_id;
|
||||
Clay_Color color;
|
||||
};
|
||||
|
||||
struct CustomRotatedIconData {
|
||||
CustomRenderType type; // CUSTOM_RENDER_ROTATED_ICON
|
||||
CustomRenderType type; // CUSTOM_RENDER_ROTATED_ICON
|
||||
S32 icon_id;
|
||||
Clay_Color color;
|
||||
F32 angle_rad;
|
||||
@@ -144,23 +144,23 @@ struct CustomRotatedIconData {
|
||||
////////////////////////////////
|
||||
// Font sizes
|
||||
|
||||
#define FONT_SIZE_NORMAL uifs(15)
|
||||
#define FONT_SIZE_SMALL uifs(12)
|
||||
#define FONT_SIZE_TAB uifs(13)
|
||||
#define FONT_SIZE_NORMAL uifs(15)
|
||||
#define FONT_SIZE_SMALL uifs(12)
|
||||
#define FONT_SIZE_TAB uifs(13)
|
||||
|
||||
////////////////////////////////
|
||||
// Widget sizing
|
||||
|
||||
#define WIDGET_BUTTON_HEIGHT uis(30)
|
||||
#define WIDGET_CHECKBOX_HEIGHT uis(28)
|
||||
#define WIDGET_CHECKBOX_SIZE uis(18)
|
||||
#define WIDGET_RADIO_OUTER uis(16)
|
||||
#define WIDGET_RADIO_INNER uis(8)
|
||||
#define WIDGET_INPUT_HEIGHT uis(30)
|
||||
#define WIDGET_DROPDOWN_HEIGHT uis(30)
|
||||
#define WIDGET_DROPDOWN_ITEM_H uis(28)
|
||||
#define WIDGET_KNOB_SIZE uis(48)
|
||||
#define WIDGET_KNOB_LABEL_GAP uip(4)
|
||||
#define WIDGET_BUTTON_HEIGHT uis(30)
|
||||
#define WIDGET_CHECKBOX_HEIGHT uis(28)
|
||||
#define WIDGET_CHECKBOX_SIZE uis(18)
|
||||
#define WIDGET_RADIO_OUTER uis(16)
|
||||
#define WIDGET_RADIO_INNER uis(8)
|
||||
#define WIDGET_INPUT_HEIGHT uis(30)
|
||||
#define WIDGET_DROPDOWN_HEIGHT uis(30)
|
||||
#define WIDGET_DROPDOWN_ITEM_H uis(28)
|
||||
#define WIDGET_KNOB_SIZE uis(48)
|
||||
#define WIDGET_KNOB_LABEL_GAP uip(4)
|
||||
|
||||
#define WIDGET_SLIDER_H_WIDTH uis(160)
|
||||
#define WIDGET_SLIDER_H_TRACK_H uis(6)
|
||||
@@ -181,11 +181,11 @@ struct CustomRotatedIconData {
|
||||
////////////////////////////////
|
||||
// Corner radius (from theme)
|
||||
|
||||
#define CORNER_RADIUS uis(g_theme.corner_radius)
|
||||
#define CORNER_RADIUS uis(g_theme.corner_radius)
|
||||
|
||||
////////////////////////////////
|
||||
// Panel sizing
|
||||
|
||||
#define PANEL_BROWSER_WIDTH uis(200)
|
||||
#define PANEL_RIGHT_COL_WIDTH uis(250)
|
||||
#define PANEL_LOG_HEIGHT uis(180)
|
||||
#define PANEL_BROWSER_WIDTH uis(200)
|
||||
#define PANEL_RIGHT_COL_WIDTH uis(250)
|
||||
#define PANEL_LOG_HEIGHT uis(180)
|
||||
|
||||
@@ -163,16 +163,16 @@ U8 *ui_icons_rasterize_atlas(S32 *out_w, S32 *out_h, S32 icon_size) {
|
||||
if (bmp.isNull()) continue;
|
||||
|
||||
// Copy BGRA premultiplied → RGBA straight (un-premultiply)
|
||||
U8 *src = bmp.data();
|
||||
S32 bmp_w = bmp.width();
|
||||
S32 bmp_h = bmp.height();
|
||||
U8 *src = bmp.data();
|
||||
S32 bmp_w = bmp.width();
|
||||
S32 bmp_h = bmp.height();
|
||||
S32 stride = bmp.stride();
|
||||
|
||||
for (S32 y = 0; y < bmp_h && y < atlas_h; y++) {
|
||||
for (S32 x = 0; x < bmp_w && (pen_x + x) < atlas_w; x++) {
|
||||
U8 *s = &src[y * stride + x * 4];
|
||||
U8 *s = &src[y * stride + x * 4];
|
||||
S32 dst_idx = (y * atlas_w + pen_x + x) * 4;
|
||||
U8 b = s[0], g = s[1], r = s[2], a = s[3];
|
||||
U8 b = s[0], g = s[1], r = s[2], a = s[3];
|
||||
if (a > 0 && a < 255) {
|
||||
r = (U8)((r * 255) / a);
|
||||
g = (U8)((g * 255) / a);
|
||||
@@ -190,8 +190,8 @@ U8 *ui_icons_rasterize_atlas(S32 *out_w, S32 *out_h, S32 icon_size) {
|
||||
g_icons[i].v0 = 0.0f;
|
||||
g_icons[i].u1 = (F32)(pen_x + bmp_w) / (F32)atlas_w;
|
||||
g_icons[i].v1 = (F32)bmp_h / (F32)atlas_h;
|
||||
g_icons[i].w = (F32)bmp_w;
|
||||
g_icons[i].h = (F32)bmp_h;
|
||||
g_icons[i].w = (F32)bmp_w;
|
||||
g_icons[i].h = (F32)bmp_h;
|
||||
|
||||
pen_x += icon_size;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ enum UI_IconID {
|
||||
};
|
||||
|
||||
struct UI_IconInfo {
|
||||
F32 u0, v0, u1, v1; // UV coordinates in icon atlas
|
||||
F32 w, h; // pixel dimensions at rasterized size
|
||||
F32 u0, v0, u1, v1; // UV coordinates in icon atlas
|
||||
F32 w, h; // pixel dimensions at rasterized size
|
||||
};
|
||||
|
||||
extern UI_IconInfo g_icons[UI_ICON_COUNT];
|
||||
|
||||
@@ -14,26 +14,25 @@ Clay_Color piano_velocity_color(S32 velocity) {
|
||||
F32 r, g, b;
|
||||
if (t < 0.5f) {
|
||||
F32 s = t * 2.0f;
|
||||
r = 40.0f + s * (76.0f - 40.0f);
|
||||
g = 120.0f + s * (175.0f - 120.0f);
|
||||
b = 220.0f + s * (80.0f - 220.0f);
|
||||
r = 40.0f + s * (76.0f - 40.0f);
|
||||
g = 120.0f + s * (175.0f - 120.0f);
|
||||
b = 220.0f + s * (80.0f - 220.0f);
|
||||
} else {
|
||||
F32 s = (t - 0.5f) * 2.0f;
|
||||
r = 76.0f + s * (220.0f - 76.0f);
|
||||
g = 175.0f + s * (50.0f - 175.0f);
|
||||
b = 80.0f + s * (40.0f - 80.0f);
|
||||
r = 76.0f + s * (220.0f - 76.0f);
|
||||
g = 175.0f + s * (50.0f - 175.0f);
|
||||
b = 80.0f + s * (40.0f - 80.0f);
|
||||
}
|
||||
return Clay_Color{r, g, b, 255};
|
||||
return Clay_Color{ r, g, b, 255 };
|
||||
}
|
||||
|
||||
void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h) {
|
||||
Clay_ElementId piano_id = CLAY_ID("PianoContainer");
|
||||
CLAY(piano_id,
|
||||
.layout = {
|
||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
||||
}
|
||||
) {
|
||||
.layout = {
|
||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
||||
}) {
|
||||
// Compute black key size proportional to white keys
|
||||
F32 black_key_h = avail_h * PIANO_BLACK_H_PCT;
|
||||
if (black_key_h < uis(20)) black_key_h = uis(20);
|
||||
@@ -46,24 +45,22 @@ void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h)
|
||||
for (S32 note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) {
|
||||
if (piano_is_black_key(note)) continue;
|
||||
|
||||
B32 midi_held = midi_is_note_held(midi, note);
|
||||
B32 mouse_held = state->mouse_note == note;
|
||||
B32 midi_held = midi_is_note_held(midi, note);
|
||||
B32 mouse_held = state->mouse_note == note;
|
||||
Clay_Color bg;
|
||||
if (midi_held) {
|
||||
bg = piano_velocity_color(midi_get_note_velocity(midi, note));
|
||||
} else if (mouse_held) {
|
||||
bg = g_theme.accent;
|
||||
} else {
|
||||
bg = Clay_Color{240, 240, 240, 255};
|
||||
bg = Clay_Color{ 240, 240, 240, 255 };
|
||||
}
|
||||
|
||||
CLAY(CLAY_IDI("PKey", note),
|
||||
.layout = {
|
||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
||||
},
|
||||
.backgroundColor = bg,
|
||||
.border = { .color = {190, 190, 190, 255}, .width = { .right = 1 } },
|
||||
) {}
|
||||
.layout = {
|
||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
||||
},
|
||||
.backgroundColor = bg, .border = { .color = { 190, 190, 190, 255 }, .width = { .right = 1 } }, ) {}
|
||||
}
|
||||
|
||||
// Black keys (floating, attached to left white key)
|
||||
@@ -71,36 +68,33 @@ void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h)
|
||||
if (!piano_is_black_key(note)) continue;
|
||||
|
||||
Clay_ElementId parent_wkey = CLAY_IDI("PKey", note - 1);
|
||||
B32 midi_held = midi_is_note_held(midi, note);
|
||||
B32 mouse_held = state->mouse_note == note;
|
||||
Clay_Color bg;
|
||||
B32 midi_held = midi_is_note_held(midi, note);
|
||||
B32 mouse_held = state->mouse_note == note;
|
||||
Clay_Color bg;
|
||||
if (midi_held) {
|
||||
bg = piano_velocity_color(midi_get_note_velocity(midi, note));
|
||||
} else if (mouse_held) {
|
||||
bg = g_theme.accent;
|
||||
} else {
|
||||
bg = Clay_Color{25, 25, 30, 255};
|
||||
bg = Clay_Color{ 25, 25, 30, 255 };
|
||||
}
|
||||
|
||||
CLAY(CLAY_IDI("PKey", note),
|
||||
.layout = {
|
||||
.sizing = {
|
||||
.width = CLAY_SIZING_FIXED(black_key_w),
|
||||
.height = CLAY_SIZING_FIXED(black_key_h),
|
||||
},
|
||||
},
|
||||
.backgroundColor = bg,
|
||||
.cornerRadius = { .topLeft = 0, .topRight = 0, .bottomLeft = uis(2), .bottomRight = uis(2) },
|
||||
.floating = {
|
||||
.parentId = parent_wkey.id,
|
||||
.zIndex = 100,
|
||||
.attachPoints = {
|
||||
.element = CLAY_ATTACH_POINT_CENTER_TOP,
|
||||
.parent = CLAY_ATTACH_POINT_RIGHT_TOP,
|
||||
},
|
||||
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
|
||||
},
|
||||
) {}
|
||||
.layout = {
|
||||
.sizing = {
|
||||
.width = CLAY_SIZING_FIXED(black_key_w),
|
||||
.height = CLAY_SIZING_FIXED(black_key_h),
|
||||
},
|
||||
},
|
||||
.backgroundColor = bg, .cornerRadius = { .topLeft = 0, .topRight = 0, .bottomLeft = uis(2), .bottomRight = uis(2) }, .floating = {
|
||||
.parentId = parent_wkey.id,
|
||||
.zIndex = 100,
|
||||
.attachPoints = {
|
||||
.element = CLAY_ATTACH_POINT_CENTER_TOP,
|
||||
.parent = CLAY_ATTACH_POINT_RIGHT_TOP,
|
||||
},
|
||||
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
|
||||
}, ) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
#include "ui/ui_core.h"
|
||||
#include "midi/midi.h"
|
||||
#include "ui/ui_core.h"
|
||||
|
||||
#define PIANO_FIRST_NOTE 21 // A0
|
||||
#define PIANO_LAST_NOTE 108 // C8
|
||||
#define PIANO_FIRST_NOTE 21 // A0
|
||||
#define PIANO_LAST_NOTE 108 // C8
|
||||
|
||||
struct UI_PianoState {
|
||||
S32 mouse_note; // MIDI note held by mouse click (-1 = none)
|
||||
S32 mouse_note; // MIDI note held by mouse click (-1 = none)
|
||||
};
|
||||
|
||||
B32 piano_is_black_key(S32 note);
|
||||
|
||||
@@ -23,7 +23,10 @@ PopupWindow *popup_open(PlatformWindow *parent_window, Renderer *parent_renderer
|
||||
// Find free slot
|
||||
PopupWindow *popup = nullptr;
|
||||
for (S32 i = 0; i < MAX_POPUP_WINDOWS; i++) {
|
||||
if (!g_popups[i].alive) { popup = &g_popups[i]; break; }
|
||||
if (!g_popups[i].alive) {
|
||||
popup = &g_popups[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!popup) return nullptr;
|
||||
|
||||
@@ -31,24 +34,24 @@ PopupWindow *popup_open(PlatformWindow *parent_window, Renderer *parent_renderer
|
||||
|
||||
// Create native popup window
|
||||
PlatformWindowDesc desc = {};
|
||||
desc.title = title;
|
||||
desc.width = width;
|
||||
desc.height = height;
|
||||
desc.style = style;
|
||||
desc.parent = parent_window;
|
||||
desc.independent = independent;
|
||||
popup->platform_window = platform_create_window(&desc);
|
||||
desc.title = title;
|
||||
desc.width = width;
|
||||
desc.height = height;
|
||||
desc.style = style;
|
||||
desc.parent = parent_window;
|
||||
desc.independent = independent;
|
||||
popup->platform_window = platform_create_window(&desc);
|
||||
if (!popup->platform_window) return nullptr;
|
||||
|
||||
// Create shared renderer
|
||||
S32 pw, ph;
|
||||
platform_get_size(popup->platform_window, &pw, &ph);
|
||||
|
||||
RendererDesc rdesc = {};
|
||||
RendererDesc rdesc = {};
|
||||
rdesc.window_handle = platform_get_native_handle(popup->platform_window);
|
||||
rdesc.width = pw;
|
||||
rdesc.height = ph;
|
||||
popup->renderer = renderer_create_shared(parent_renderer, &rdesc);
|
||||
popup->renderer = renderer_create_shared(parent_renderer, &rdesc);
|
||||
if (!popup->renderer) {
|
||||
platform_destroy_window(popup->platform_window);
|
||||
return nullptr;
|
||||
@@ -58,16 +61,16 @@ PopupWindow *popup_open(PlatformWindow *parent_window, Renderer *parent_renderer
|
||||
popup->ui_ctx = ui_create((F32)pw, (F32)ph);
|
||||
ui_set_measure_text_fn(popup->ui_ctx, renderer_measure_text, popup->renderer);
|
||||
|
||||
popup->alive = 1;
|
||||
popup->open_flag = open_flag;
|
||||
popup->content_fn = content_fn;
|
||||
popup->alive = 1;
|
||||
popup->open_flag = open_flag;
|
||||
popup->content_fn = content_fn;
|
||||
popup->content_user_data = user_data;
|
||||
popup->width = width;
|
||||
popup->height = height;
|
||||
popup->last_w = pw;
|
||||
popup->last_h = ph;
|
||||
popup->title = title;
|
||||
popup->wstate = {};
|
||||
popup->width = width;
|
||||
popup->height = height;
|
||||
popup->last_w = pw;
|
||||
popup->last_h = ph;
|
||||
popup->title = title;
|
||||
popup->wstate = {};
|
||||
|
||||
platform_set_frame_callback(popup->platform_window, popup_frame_callback, popup);
|
||||
|
||||
@@ -111,7 +114,7 @@ void popup_do_frame(PopupWindow *popup, F32 dt) {
|
||||
if (input.ctrl_held) {
|
||||
if (input.keys[k] == PKEY_EQUAL) g_ui_scale *= 1.1f;
|
||||
if (input.keys[k] == PKEY_MINUS) g_ui_scale /= 1.1f;
|
||||
if (input.keys[k] == PKEY_0) g_ui_scale = 1.0f;
|
||||
if (input.keys[k] == PKEY_0) g_ui_scale = 1.0f;
|
||||
}
|
||||
}
|
||||
g_ui_scale = Clamp(0.5f, g_ui_scale, 3.0f);
|
||||
@@ -121,7 +124,7 @@ void popup_do_frame(PopupWindow *popup, F32 dt) {
|
||||
|
||||
// Swap widget state
|
||||
UI_WidgetState saved_wstate = g_wstate;
|
||||
g_wstate = popup->wstate;
|
||||
g_wstate = popup->wstate;
|
||||
|
||||
ui_widgets_begin_frame(input);
|
||||
|
||||
@@ -131,14 +134,13 @@ void popup_do_frame(PopupWindow *popup, F32 dt) {
|
||||
|
||||
// Background fill
|
||||
CLAY(CLAY_ID("PopupBg"),
|
||||
.layout = {
|
||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
||||
.padding = { uip(12), uip(12), uip(10), uip(10) },
|
||||
.childGap = uip(8),
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||
},
|
||||
.backgroundColor = g_theme.bg_medium,
|
||||
) {
|
||||
.layout = {
|
||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
||||
.padding = { uip(12), uip(12), uip(10), uip(10) },
|
||||
.childGap = uip(8),
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||
},
|
||||
.backgroundColor = g_theme.bg_medium, ) {
|
||||
if (popup->content_fn) {
|
||||
popup->content_fn(popup->content_user_data);
|
||||
}
|
||||
@@ -148,7 +150,7 @@ void popup_do_frame(PopupWindow *popup, F32 dt) {
|
||||
|
||||
// Save widget state back
|
||||
popup->wstate = g_wstate;
|
||||
g_wstate = saved_wstate;
|
||||
g_wstate = saved_wstate;
|
||||
|
||||
// Render
|
||||
renderer_end_frame(popup->renderer, render_commands);
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
#pragma once
|
||||
#include "ui/ui_core.h"
|
||||
#include "ui/ui_widgets.h"
|
||||
#include "platform/platform.h"
|
||||
#include "renderer/renderer.h"
|
||||
#include "ui/ui_core.h"
|
||||
#include "ui/ui_widgets.h"
|
||||
|
||||
#define MAX_POPUP_WINDOWS 4
|
||||
|
||||
struct PopupWindow {
|
||||
B32 alive;
|
||||
B32 *open_flag; // e.g. &app->show_settings_window
|
||||
PlatformWindow *platform_window;
|
||||
Renderer *renderer;
|
||||
UI_Context *ui_ctx;
|
||||
UI_WidgetState wstate;
|
||||
B32 alive;
|
||||
B32 *open_flag; // e.g. &app->show_settings_window
|
||||
PlatformWindow *platform_window;
|
||||
Renderer *renderer;
|
||||
UI_Context *ui_ctx;
|
||||
UI_WidgetState wstate;
|
||||
UI_WindowContentFn content_fn;
|
||||
void *content_user_data;
|
||||
S32 width, height;
|
||||
S32 last_w, last_h;
|
||||
const char *title;
|
||||
void *content_user_data;
|
||||
S32 width, height;
|
||||
S32 last_w, last_h;
|
||||
const char *title;
|
||||
};
|
||||
|
||||
PopupWindow *popup_open(PlatformWindow *parent_window, Renderer *parent_renderer,
|
||||
const char *title, B32 *open_flag,
|
||||
S32 width, S32 height,
|
||||
UI_WindowContentFn content_fn, void *user_data,
|
||||
PlatformWindowStyle style = PLATFORM_WINDOW_STYLE_POPUP,
|
||||
B32 independent = 0);
|
||||
PlatformWindowStyle style = PLATFORM_WINDOW_STYLE_POPUP,
|
||||
B32 independent = 0);
|
||||
void popup_close(PopupWindow *popup);
|
||||
PopupWindow *popup_find_by_flag(B32 *flag);
|
||||
void popup_do_frame(PopupWindow *popup, F32 dt);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,9 +6,9 @@
|
||||
// The caller owns all data — the widget layer only stores transient UI state
|
||||
// like which text field is focused or which dropdown is open.
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "ui/ui_core.h"
|
||||
#include "ui/ui_icons.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
////////////////////////////////
|
||||
// Widget state (global, managed by widget layer)
|
||||
@@ -17,29 +17,29 @@
|
||||
#define UI_WIDGET_MAX_TEXT_INPUTS 16
|
||||
|
||||
struct UI_KnobDragState {
|
||||
U32 dragging_id; // Hash of the knob being dragged (0 = none)
|
||||
F32 drag_start_y; // Mouse Y when drag started
|
||||
F32 drag_start_x; // Mouse X when drag started (for h-slider)
|
||||
F32 value_at_start; // Value when drag started
|
||||
B32 was_shift; // Shift state last frame (to re-anchor on change)
|
||||
U32 last_click_id; // Knob hash of last click (for F64-click detection)
|
||||
S32 last_click_frame; // Frame number of last click
|
||||
U32 dragging_id; // Hash of the knob being dragged (0 = none)
|
||||
F32 drag_start_y; // Mouse Y when drag started
|
||||
F32 drag_start_x; // Mouse X when drag started (for h-slider)
|
||||
F32 value_at_start; // Value when drag started
|
||||
B32 was_shift; // Shift state last frame (to re-anchor on change)
|
||||
U32 last_click_id; // Knob hash of last click (for F64-click detection)
|
||||
S32 last_click_frame; // Frame number of last click
|
||||
};
|
||||
|
||||
struct UI_WidgetState {
|
||||
// Text input focus
|
||||
U32 focused_id; // Clay element ID hash of the focused text input (0 = none)
|
||||
S32 cursor_pos; // Cursor position in focused text input
|
||||
F32 cursor_blink; // Blink timer (seconds)
|
||||
U32 focused_id; // Clay element ID hash of the focused text input (0 = none)
|
||||
S32 cursor_pos; // Cursor position in focused text input
|
||||
F32 cursor_blink; // Blink timer (seconds)
|
||||
|
||||
// Text selection (sel_start == sel_end means no selection)
|
||||
S32 sel_start; // Selection anchor (where selection began)
|
||||
S32 sel_end; // Selection extent (moves with cursor)
|
||||
S32 sel_start; // Selection anchor (where selection began)
|
||||
S32 sel_end; // Selection extent (moves with cursor)
|
||||
|
||||
// Tab cycling: registered text input IDs in order of declaration
|
||||
U32 text_input_ids[UI_WIDGET_MAX_TEXT_INPUTS];
|
||||
S32 text_input_count;
|
||||
B32 tab_pressed; // True on the frame Tab was pressed
|
||||
U32 text_input_ids[UI_WIDGET_MAX_TEXT_INPUTS];
|
||||
S32 text_input_count;
|
||||
B32 tab_pressed; // True on the frame Tab was pressed
|
||||
|
||||
// Dropdown
|
||||
U32 open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none)
|
||||
@@ -54,11 +54,11 @@ struct UI_WidgetState {
|
||||
UI_KnobDragState knob_drag;
|
||||
|
||||
// Knob text edit state
|
||||
U32 knob_edit_id; // Hash of knob in text edit mode (0 = none)
|
||||
char knob_edit_buf[32]; // Text buffer for numeric entry
|
||||
S32 knob_edit_cursor; // Cursor position in edit buffer
|
||||
S32 knob_edit_sel_start; // Selection anchor
|
||||
S32 knob_edit_sel_end; // Selection extent
|
||||
U32 knob_edit_id; // Hash of knob in text edit mode (0 = none)
|
||||
char knob_edit_buf[32]; // Text buffer for numeric entry
|
||||
S32 knob_edit_cursor; // Cursor position in edit buffer
|
||||
S32 knob_edit_sel_start; // Selection anchor
|
||||
S32 knob_edit_sel_end; // Selection extent
|
||||
};
|
||||
|
||||
extern UI_WidgetState g_wstate;
|
||||
|
||||
Reference in New Issue
Block a user