|
|
|
|
@@ -44,7 +44,7 @@ static CustomGradientData *alloc_gradient(Clay_Color top, Clay_Color bottom) {
|
|
|
|
|
// Per-frame shadow layer ID counter (each shadow uses N unique IDs)
|
|
|
|
|
static S32 g_shadow_id_counter = 0;
|
|
|
|
|
|
|
|
|
|
// Frame counter for double-click detection
|
|
|
|
|
// Frame counter for F64-click detection
|
|
|
|
|
static S32 g_frame_number = 0;
|
|
|
|
|
|
|
|
|
|
// Emit a smooth multi-layer drop shadow as floating rects.
|
|
|
|
|
@@ -59,16 +59,16 @@ static S32 g_frame_number = 0;
|
|
|
|
|
#define SHADOW_LAYERS 7
|
|
|
|
|
|
|
|
|
|
static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius,
|
|
|
|
|
float peak_alpha, int16_t z,
|
|
|
|
|
B32 attach_to_root, uint32_t parent_id,
|
|
|
|
|
F32 peak_alpha, S16 z,
|
|
|
|
|
B32 attach_to_root, U32 parent_id,
|
|
|
|
|
Clay_FloatingAttachPointType parent_attach) {
|
|
|
|
|
if (bb.width <= 0) return;
|
|
|
|
|
|
|
|
|
|
float per_layer = peak_alpha / (float)SHADOW_LAYERS;
|
|
|
|
|
F32 per_layer = peak_alpha / (F32)SHADOW_LAYERS;
|
|
|
|
|
|
|
|
|
|
// Draw outermost first (largest, lowest alpha contribution), innermost last
|
|
|
|
|
for (S32 i = SHADOW_LAYERS - 1; i >= 0; i--) {
|
|
|
|
|
float t = (float)(i + 1) / (float)SHADOW_LAYERS; // 1/N .. 1.0
|
|
|
|
|
F32 t = (F32)(i + 1) / (F32)SHADOW_LAYERS; // 1/N .. 1.0
|
|
|
|
|
F32 expand = radius * t;
|
|
|
|
|
|
|
|
|
|
S32 sid = g_shadow_id_counter++;
|
|
|
|
|
@@ -268,8 +268,8 @@ B32 ui_button(const char *id, const char *text) {
|
|
|
|
|
B32 hovered = Clay_PointerOver(eid);
|
|
|
|
|
|
|
|
|
|
Clay_Color base = hovered ? g_theme.accent_hover : g_theme.accent;
|
|
|
|
|
Clay_Color top = {(float)Min((int)base.r+12,255), (float)Min((int)base.g+12,255), (float)Min((int)base.b+12,255), base.a};
|
|
|
|
|
Clay_Color bot = {(float)Max((int)base.r-15,0), (float)Max((int)base.g-15,0), (float)Max((int)base.b-15,0), base.a};
|
|
|
|
|
Clay_Color top = {(F32)Min((S32)base.r+12,255), (F32)Min((S32)base.g+12,255), (F32)Min((S32)base.b+12,255), base.a};
|
|
|
|
|
Clay_Color bot = {(F32)Max((S32)base.r-15,0), (F32)Max((S32)base.g-15,0), (F32)Max((S32)base.b-15,0), base.a};
|
|
|
|
|
CustomGradientData *grad = alloc_gradient(top, bot);
|
|
|
|
|
|
|
|
|
|
CLAY(eid,
|
|
|
|
|
@@ -526,7 +526,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
|
|
|
|
|
|
|
|
|
|
// Key events
|
|
|
|
|
for (S32 k = 0; k < g_wstate.input.key_count; k++) {
|
|
|
|
|
uint8_t key = g_wstate.input.keys[k];
|
|
|
|
|
U8 key = g_wstate.input.keys[k];
|
|
|
|
|
|
|
|
|
|
// Skip Tab — handled via tab cycling
|
|
|
|
|
if (key == PKEY_TAB) continue;
|
|
|
|
|
@@ -656,7 +656,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
|
|
|
|
|
// Character input (printable only, skip control chars)
|
|
|
|
|
if (is_focused) {
|
|
|
|
|
for (S32 c = 0; c < g_wstate.input.char_count; c++) {
|
|
|
|
|
uint16_t ch = g_wstate.input.chars[c];
|
|
|
|
|
U16 ch = g_wstate.input.chars[c];
|
|
|
|
|
if (ch >= 32 && ch < 127) {
|
|
|
|
|
// Delete selection first if any
|
|
|
|
|
if (text_input_has_sel()) {
|
|
|
|
|
@@ -726,8 +726,8 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
|
|
|
|
|
Clay_Color border_color = is_focused ? g_theme.accent : g_theme.border;
|
|
|
|
|
|
|
|
|
|
// Inset effect: darker top, lighter bottom (recessed look)
|
|
|
|
|
Clay_Color inset_top = {(float)Max((int)bg.r-8,0), (float)Max((int)bg.g-8,0), (float)Max((int)bg.b-8,0), bg.a};
|
|
|
|
|
Clay_Color inset_bot = {(float)Min((int)bg.r+3,255), (float)Min((int)bg.g+3,255), (float)Min((int)bg.b+3,255), bg.a};
|
|
|
|
|
Clay_Color inset_top = {(F32)Max((S32)bg.r-8,0), (F32)Max((S32)bg.g-8,0), (F32)Max((S32)bg.b-8,0), bg.a};
|
|
|
|
|
Clay_Color inset_bot = {(F32)Min((S32)bg.r+3,255), (F32)Min((S32)bg.g+3,255), (F32)Min((S32)bg.b+3,255), bg.a};
|
|
|
|
|
CustomGradientData *inset_grad = alloc_gradient(inset_top, inset_bot);
|
|
|
|
|
|
|
|
|
|
CLAY(eid,
|
|
|
|
|
@@ -820,13 +820,13 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
|
|
|
|
|
static char dd_trunc_buf[256];
|
|
|
|
|
const char *display_label = current_label;
|
|
|
|
|
Clay_ElementId text_eid = WIDI(id, 500);
|
|
|
|
|
float avail_w = Clay_GetElementData(text_eid).boundingBox.width;
|
|
|
|
|
F32 avail_w = Clay_GetElementData(text_eid).boundingBox.width;
|
|
|
|
|
if (avail_w > 0) {
|
|
|
|
|
S32 label_len = (S32)strlen(current_label);
|
|
|
|
|
Vec2F32 text_size = ui_measure_text(current_label, label_len, FONT_SIZE_NORMAL);
|
|
|
|
|
if (text_size.x > avail_w) {
|
|
|
|
|
Vec2F32 dots = ui_measure_text("...", 3, FONT_SIZE_NORMAL);
|
|
|
|
|
float target_w = avail_w - dots.x;
|
|
|
|
|
F32 target_w = avail_w - dots.x;
|
|
|
|
|
S32 lo = 0, hi = label_len;
|
|
|
|
|
while (lo < hi) {
|
|
|
|
|
S32 mid = (lo + hi + 1) / 2;
|
|
|
|
|
@@ -845,7 +845,7 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
|
|
|
|
|
Clay_Color bg = is_open ? g_theme.bg_dark : g_theme.bg_medium;
|
|
|
|
|
if (header_hovered && !is_open) bg = g_theme.bg_lighter;
|
|
|
|
|
|
|
|
|
|
Clay_Color dd_top = {(float)Min((int)bg.r+6,255), (float)Min((int)bg.g+6,255), (float)Min((int)bg.b+6,255), bg.a};
|
|
|
|
|
Clay_Color dd_top = {(F32)Min((S32)bg.r+6,255), (F32)Min((S32)bg.g+6,255), (F32)Min((S32)bg.b+6,255), bg.a};
|
|
|
|
|
CustomGradientData *dd_grad = alloc_gradient(dd_top, bg);
|
|
|
|
|
|
|
|
|
|
CLAY(eid,
|
|
|
|
|
@@ -892,7 +892,7 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
|
|
|
|
|
// Draw dropdown list if open (floating so it escapes modal/container clipping)
|
|
|
|
|
if (is_open) {
|
|
|
|
|
Clay_ElementId list_id = WIDI(id, 502);
|
|
|
|
|
float header_width = Clay_GetElementData(eid).boundingBox.width;
|
|
|
|
|
F32 header_width = Clay_GetElementData(eid).boundingBox.width;
|
|
|
|
|
|
|
|
|
|
// Dropdown list shadow
|
|
|
|
|
{
|
|
|
|
|
@@ -1052,7 +1052,7 @@ S32 ui_modal(const char *id, const char *title, const char *message,
|
|
|
|
|
// Title bar (gradient: lighter top)
|
|
|
|
|
{
|
|
|
|
|
Clay_Color mtb = g_theme.title_bar;
|
|
|
|
|
Clay_Color mtb_top = {(float)Min((int)mtb.r+12,255), (float)Min((int)mtb.g+12,255), (float)Min((int)mtb.b+12,255), mtb.a};
|
|
|
|
|
Clay_Color mtb_top = {(F32)Min((S32)mtb.r+12,255), (F32)Min((S32)mtb.g+12,255), (F32)Min((S32)mtb.b+12,255), mtb.a};
|
|
|
|
|
CustomGradientData *mtb_grad = alloc_gradient(mtb_top, mtb);
|
|
|
|
|
|
|
|
|
|
CLAY(WIDI(id, 2002),
|
|
|
|
|
@@ -1099,8 +1099,8 @@ S32 ui_modal(const char *id, const char *title, const char *message,
|
|
|
|
|
B32 btn_hovered = Clay_PointerOver(btn_id);
|
|
|
|
|
|
|
|
|
|
Clay_Color mbtn_base = btn_hovered ? g_theme.accent_hover : g_theme.accent;
|
|
|
|
|
Clay_Color mbtn_top = {(float)Min((int)mbtn_base.r+12,255), (float)Min((int)mbtn_base.g+12,255), (float)Min((int)mbtn_base.b+12,255), mbtn_base.a};
|
|
|
|
|
Clay_Color mbtn_bot = {(float)Max((int)mbtn_base.r-15,0), (float)Max((int)mbtn_base.g-15,0), (float)Max((int)mbtn_base.b-15,0), mbtn_base.a};
|
|
|
|
|
Clay_Color mbtn_top = {(F32)Min((S32)mbtn_base.r+12,255), (F32)Min((S32)mbtn_base.g+12,255), (F32)Min((S32)mbtn_base.b+12,255), mbtn_base.a};
|
|
|
|
|
Clay_Color mbtn_bot = {(F32)Max((S32)mbtn_base.r-15,0), (F32)Max((S32)mbtn_base.g-15,0), (F32)Max((S32)mbtn_base.b-15,0), mbtn_base.a};
|
|
|
|
|
CustomGradientData *mbtn_grad = alloc_gradient(mbtn_top, mbtn_bot);
|
|
|
|
|
|
|
|
|
|
CLAY(btn_id,
|
|
|
|
|
@@ -1136,7 +1136,7 @@ S32 ui_modal(const char *id, const char *title, const char *message,
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
// Draggable window
|
|
|
|
|
|
|
|
|
|
static UI_WindowSlot *find_or_create_window_slot(uint32_t id, Vec2F32 initial_pos, Vec2F32 initial_size) {
|
|
|
|
|
static UI_WindowSlot *find_or_create_window_slot(U32 id, Vec2F32 initial_pos, Vec2F32 initial_size) {
|
|
|
|
|
// Look for existing slot
|
|
|
|
|
for (S32 i = 0; i < g_wstate.window_count; i++) {
|
|
|
|
|
if (g_wstate.windows[i].id == id) {
|
|
|
|
|
@@ -1157,25 +1157,25 @@ static UI_WindowSlot *find_or_create_window_slot(uint32_t id, Vec2F32 initial_po
|
|
|
|
|
static void bring_window_to_front(UI_WindowSlot *slot) {
|
|
|
|
|
// Renormalize if approaching modal z-range
|
|
|
|
|
if (g_wstate.next_z > 800) {
|
|
|
|
|
int16_t sorted[UI_WIDGET_MAX_WINDOWS];
|
|
|
|
|
S16 sorted[UI_WIDGET_MAX_WINDOWS];
|
|
|
|
|
S32 count = g_wstate.window_count;
|
|
|
|
|
for (S32 i = 0; i < count; i++) sorted[i] = g_wstate.windows[i].z_order;
|
|
|
|
|
// Bubble sort (tiny array)
|
|
|
|
|
for (S32 i = 0; i < count - 1; i++) {
|
|
|
|
|
for (S32 j = i + 1; j < count; j++) {
|
|
|
|
|
if (sorted[j] < sorted[i]) {
|
|
|
|
|
int16_t tmp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = tmp;
|
|
|
|
|
S16 tmp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = tmp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (S32 i = 0; i < count; i++) {
|
|
|
|
|
for (S32 j = 0; j < count; j++) {
|
|
|
|
|
if (g_wstate.windows[j].z_order == sorted[i]) {
|
|
|
|
|
g_wstate.windows[j].z_order = (int16_t)i;
|
|
|
|
|
g_wstate.windows[j].z_order = (S16)i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g_wstate.next_z = (int16_t)count;
|
|
|
|
|
g_wstate.next_z = (S16)count;
|
|
|
|
|
}
|
|
|
|
|
slot->z_order = g_wstate.next_z++;
|
|
|
|
|
}
|
|
|
|
|
@@ -1233,7 +1233,7 @@ B32 ui_window(const char *id, const char *title, B32 *open,
|
|
|
|
|
// Use absolute position since window uses offset-based floating
|
|
|
|
|
Clay_BoundingBox shadow_bb = { slot->position.x, slot->position.y, win_bb.width, win_bb.height };
|
|
|
|
|
emit_shadow(shadow_bb, uis(3), uis(3), uis(8),
|
|
|
|
|
g_theme.shadow.a, (int16_t)(100 + slot->z_order - 1),
|
|
|
|
|
g_theme.shadow.a, (S16)(100 + slot->z_order - 1),
|
|
|
|
|
1, 0, CLAY_ATTACH_POINT_LEFT_TOP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1247,7 +1247,7 @@ B32 ui_window(const char *id, const char *title, B32 *open,
|
|
|
|
|
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS),
|
|
|
|
|
.floating = {
|
|
|
|
|
.offset = { slot->position.x, slot->position.y },
|
|
|
|
|
.zIndex = (int16_t)(100 + slot->z_order),
|
|
|
|
|
.zIndex = (S16)(100 + slot->z_order),
|
|
|
|
|
.attachPoints = {
|
|
|
|
|
.element = CLAY_ATTACH_POINT_LEFT_TOP,
|
|
|
|
|
.parent = CLAY_ATTACH_POINT_LEFT_TOP,
|
|
|
|
|
@@ -1259,7 +1259,7 @@ B32 ui_window(const char *id, const char *title, B32 *open,
|
|
|
|
|
) {
|
|
|
|
|
// Title bar (gradient: lighter top)
|
|
|
|
|
Clay_Color tb = g_theme.title_bar;
|
|
|
|
|
Clay_Color tb_top = {(float)Min((int)tb.r+12,255), (float)Min((int)tb.g+12,255), (float)Min((int)tb.b+12,255), tb.a};
|
|
|
|
|
Clay_Color tb_top = {(F32)Min((S32)tb.r+12,255), (F32)Min((S32)tb.g+12,255), (F32)Min((S32)tb.b+12,255), tb.a};
|
|
|
|
|
CustomGradientData *tb_grad = alloc_gradient(tb_top, tb);
|
|
|
|
|
|
|
|
|
|
CLAY(title_bar_id,
|
|
|
|
|
@@ -1346,7 +1346,7 @@ S32 ui_tab_bar(const char *id, const char **labels, S32 count, S32 *selected) {
|
|
|
|
|
.border = { .color = g_theme.border, .width = { .bottom = 1 } },
|
|
|
|
|
) {
|
|
|
|
|
for (S32 i = 0; i < count; i++) {
|
|
|
|
|
Clay_ElementId tab_eid = Clay__HashStringWithOffset(id_str, (uint32_t)i, 0);
|
|
|
|
|
Clay_ElementId tab_eid = Clay__HashStringWithOffset(id_str, (U32)i, 0);
|
|
|
|
|
B32 is_active = (i == *selected);
|
|
|
|
|
B32 hovered = Clay_PointerOver(tab_eid);
|
|
|
|
|
|
|
|
|
|
@@ -1421,7 +1421,7 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (S32 k = 0; k < g_wstate.input.key_count; k++) {
|
|
|
|
|
uint8_t key = g_wstate.input.keys[k];
|
|
|
|
|
U8 key = g_wstate.input.keys[k];
|
|
|
|
|
|
|
|
|
|
if (ctrl) {
|
|
|
|
|
if (key == PKEY_A) {
|
|
|
|
|
@@ -1500,7 +1500,7 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
|
|
|
|
|
|
|
|
|
|
if (!commit && !cancel) {
|
|
|
|
|
for (S32 c = 0; c < g_wstate.input.char_count; c++) {
|
|
|
|
|
uint16_t ch = g_wstate.input.chars[c];
|
|
|
|
|
U16 ch = g_wstate.input.chars[c];
|
|
|
|
|
B32 valid = (ch >= '0' && ch <= '9') || ch == '.' || ch == '-';
|
|
|
|
|
if (valid) {
|
|
|
|
|
if (KE_HAS_SEL()) elen = ke_delete_sel();
|
|
|
|
|
@@ -1537,8 +1537,8 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Render the text edit box with selection/cursor display.
|
|
|
|
|
static void value_edit_render(uint32_t hash, F32 width) {
|
|
|
|
|
Clay_ElementId edit_eid = CLAY_IDI("ValEdit", (int)hash);
|
|
|
|
|
static void value_edit_render(U32 hash, F32 width) {
|
|
|
|
|
Clay_ElementId edit_eid = CLAY_IDI("ValEdit", (S32)hash);
|
|
|
|
|
|
|
|
|
|
char *ebuf = g_wstate.knob_edit_buf;
|
|
|
|
|
S32 elen = (S32)strlen(ebuf);
|
|
|
|
|
@@ -1588,7 +1588,7 @@ static void value_edit_render(uint32_t hash, F32 width) {
|
|
|
|
|
S32 n = sel_hi - sel_lo;
|
|
|
|
|
memcpy(ke_dbuf_sel, &ebuf[sel_lo], n); ke_dbuf_sel[n] = '\0';
|
|
|
|
|
Clay_String s_sel = { .length = n, .chars = ke_dbuf_sel };
|
|
|
|
|
CLAY(CLAY_IDI("ValEditSel", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("ValEditSel", (S32)hash),
|
|
|
|
|
.layout = { .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() } },
|
|
|
|
|
.backgroundColor = g_theme.accent
|
|
|
|
|
) {
|
|
|
|
|
@@ -1616,8 +1616,8 @@ static void value_edit_render(uint32_t hash, F32 width) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the Clay element ID of the current edit box (for click-away detection).
|
|
|
|
|
static Clay_ElementId value_edit_eid(uint32_t hash) {
|
|
|
|
|
return CLAY_IDI("ValEdit", (int)hash);
|
|
|
|
|
static Clay_ElementId value_edit_eid(U32 hash) {
|
|
|
|
|
return CLAY_IDI("ValEdit", (S32)hash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle click-outside to commit the edit.
|
|
|
|
|
@@ -1636,7 +1636,7 @@ static void value_edit_click_away(Clay_ElementId eid, F32 *value, F32 max_val, B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Enter text edit mode for a widget.
|
|
|
|
|
static void value_edit_enter(uint32_t hash, F32 value, B32 is_signed) {
|
|
|
|
|
static void value_edit_enter(U32 hash, F32 value, B32 is_signed) {
|
|
|
|
|
g_wstate.knob_edit_id = hash;
|
|
|
|
|
g_wstate.focused_id = 0;
|
|
|
|
|
if (is_signed) {
|
|
|
|
|
@@ -1684,7 +1684,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
|
|
|
|
|
F32 deg_to_rad = 3.14159265f / 180.0f;
|
|
|
|
|
F32 angle_rad = (-135.0f + normalized * 270.0f) * deg_to_rad;
|
|
|
|
|
|
|
|
|
|
uint32_t knob_hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
U32 knob_hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
B32 is_editing = (editable && g_wstate.knob_edit_id == knob_hash);
|
|
|
|
|
UI_KnobDragState *kd = &g_wstate.knob_drag;
|
|
|
|
|
|
|
|
|
|
@@ -1732,7 +1732,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
|
|
|
|
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
Clay_ElementId knob_eid = CLAY_IDI("KnobBg", (int)knob_hash);
|
|
|
|
|
Clay_ElementId knob_eid = CLAY_IDI("KnobBg", (S32)knob_hash);
|
|
|
|
|
B32 hovered = Clay_PointerOver(knob_eid);
|
|
|
|
|
|
|
|
|
|
CLAY(knob_eid,
|
|
|
|
|
@@ -1761,7 +1761,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Click: double-click resets, single click starts drag
|
|
|
|
|
// Click: F64-click resets, single click starts drag
|
|
|
|
|
if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) {
|
|
|
|
|
B32 is_double_click = (kd->last_click_id == knob_hash &&
|
|
|
|
|
(g_frame_number - kd->last_click_frame) < 20);
|
|
|
|
|
@@ -1785,7 +1785,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
|
|
|
|
|
value_edit_render(knob_hash, knob_size);
|
|
|
|
|
value_edit_click_away(value_edit_eid(knob_hash), value, max_val, is_signed, &changed);
|
|
|
|
|
} else if (val_text && val_len > 0) {
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("KnobVal", (int)knob_hash);
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("KnobVal", (S32)knob_hash);
|
|
|
|
|
B32 val_hovered = Clay_PointerOver(val_eid);
|
|
|
|
|
|
|
|
|
|
Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text };
|
|
|
|
|
@@ -1824,7 +1824,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
|
|
|
|
|
B32 changed = 0;
|
|
|
|
|
F32 normalized = value_normalize(*value, max_val, is_signed);
|
|
|
|
|
uint32_t hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
U32 hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
B32 is_editing = (editable && g_wstate.knob_edit_id == hash);
|
|
|
|
|
UI_KnobDragState *kd = &g_wstate.knob_drag;
|
|
|
|
|
|
|
|
|
|
@@ -1883,7 +1883,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
|
|
|
|
|
|
|
|
|
|
// Hit area (transparent, sized to encompass thumb travel)
|
|
|
|
|
Clay_ElementId hit_eid = CLAY_IDI("SlHHit", (int)hash);
|
|
|
|
|
Clay_ElementId hit_eid = CLAY_IDI("SlHHit", (S32)hash);
|
|
|
|
|
B32 hovered = Clay_PointerOver(hit_eid);
|
|
|
|
|
|
|
|
|
|
CLAY(hit_eid,
|
|
|
|
|
@@ -1893,7 +1893,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
// Visible track (centered inside hit area)
|
|
|
|
|
CLAY(CLAY_IDI("SlHTrack", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("SlHTrack", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -1903,7 +1903,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
// Fill bar
|
|
|
|
|
F32 fill_w = normalized * track_w;
|
|
|
|
|
if (fill_w < 1.0f) fill_w = 1.0f;
|
|
|
|
|
CLAY(CLAY_IDI("SlHFill", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("SlHFill", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(fill_w), .height = CLAY_SIZING_GROW() },
|
|
|
|
|
},
|
|
|
|
|
@@ -1919,7 +1919,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
idata->icon_id = (S32)UI_ICON_SLIDER_THUMB;
|
|
|
|
|
idata->color = g_theme.accent;
|
|
|
|
|
|
|
|
|
|
CLAY(CLAY_IDI("SlHThumb", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("SlHThumb", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(thumb_w), .height = CLAY_SIZING_FIXED(thumb_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -1941,7 +1941,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Click: double-click resets, single click starts drag
|
|
|
|
|
// Click: F64-click resets, single click starts drag
|
|
|
|
|
if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) {
|
|
|
|
|
B32 is_double_click = (kd->last_click_id == hash &&
|
|
|
|
|
(g_frame_number - kd->last_click_frame) < 20);
|
|
|
|
|
@@ -1964,7 +1964,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
value_edit_render(hash, track_w);
|
|
|
|
|
value_edit_click_away(value_edit_eid(hash), value, max_val, is_signed, &changed);
|
|
|
|
|
} else if (val_text && val_len > 0) {
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("SlHVal", (int)hash);
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("SlHVal", (S32)hash);
|
|
|
|
|
B32 val_hovered = Clay_PointerOver(val_eid);
|
|
|
|
|
|
|
|
|
|
Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text };
|
|
|
|
|
@@ -2000,7 +2000,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
|
|
|
|
|
B32 changed = 0;
|
|
|
|
|
F32 normalized = value_normalize(*value, max_val, is_signed);
|
|
|
|
|
uint32_t hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
U32 hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
B32 is_editing = (editable && g_wstate.knob_edit_id == hash);
|
|
|
|
|
UI_KnobDragState *kd = &g_wstate.knob_drag;
|
|
|
|
|
|
|
|
|
|
@@ -2059,7 +2059,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
|
|
|
|
|
|
|
|
|
|
// Hit area (transparent, sized to encompass thumb travel)
|
|
|
|
|
Clay_ElementId hit_eid = CLAY_IDI("SlVHit", (int)hash);
|
|
|
|
|
Clay_ElementId hit_eid = CLAY_IDI("SlVHit", (S32)hash);
|
|
|
|
|
B32 hovered = Clay_PointerOver(hit_eid);
|
|
|
|
|
|
|
|
|
|
CLAY(hit_eid,
|
|
|
|
|
@@ -2069,7 +2069,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
// Visible track (centered inside hit area)
|
|
|
|
|
CLAY(CLAY_IDI("SlVTrack", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("SlVTrack", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
|
|
|
|
|
.childAlignment = { .y = CLAY_ALIGN_Y_BOTTOM },
|
|
|
|
|
@@ -2080,7 +2080,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
// Fill bar (from bottom)
|
|
|
|
|
F32 fill_h = normalized * track_h;
|
|
|
|
|
if (fill_h < 1.0f) fill_h = 1.0f;
|
|
|
|
|
CLAY(CLAY_IDI("SlVFill", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("SlVFill", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(fill_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -2096,7 +2096,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
idata->icon_id = (S32)UI_ICON_SLIDER_THUMB;
|
|
|
|
|
idata->color = g_theme.accent;
|
|
|
|
|
|
|
|
|
|
CLAY(CLAY_IDI("SlVThumb", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("SlVThumb", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(thumb_w), .height = CLAY_SIZING_FIXED(thumb_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -2118,7 +2118,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Click: double-click resets, single click starts drag
|
|
|
|
|
// Click: F64-click resets, single click starts drag
|
|
|
|
|
if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) {
|
|
|
|
|
B32 is_double_click = (kd->last_click_id == hash &&
|
|
|
|
|
(g_frame_number - kd->last_click_frame) < 20);
|
|
|
|
|
@@ -2141,7 +2141,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
|
|
|
|
|
value_edit_render(hash, thumb_w * 2.0f);
|
|
|
|
|
value_edit_click_away(value_edit_eid(hash), value, max_val, is_signed, &changed);
|
|
|
|
|
} else if (val_text && val_len > 0) {
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("SlVVal", (int)hash);
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("SlVVal", (S32)hash);
|
|
|
|
|
B32 val_hovered = Clay_PointerOver(val_eid);
|
|
|
|
|
|
|
|
|
|
Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text };
|
|
|
|
|
@@ -2177,7 +2177,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
|
|
|
|
|
B32 changed = 0;
|
|
|
|
|
F32 normalized = value_normalize(*value, max_val, is_signed);
|
|
|
|
|
uint32_t hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
U32 hash = Clay__HashString(clay_str(id), 0).id;
|
|
|
|
|
B32 is_editing = (editable && g_wstate.knob_edit_id == hash);
|
|
|
|
|
UI_KnobDragState *kd = &g_wstate.knob_drag;
|
|
|
|
|
|
|
|
|
|
@@ -2239,7 +2239,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
|
|
|
|
|
|
|
|
|
|
// Hit area (transparent, sized to encompass fader cap travel)
|
|
|
|
|
Clay_ElementId hit_eid = CLAY_IDI("FdrHit", (int)hash);
|
|
|
|
|
Clay_ElementId hit_eid = CLAY_IDI("FdrHit", (S32)hash);
|
|
|
|
|
B32 hovered = Clay_PointerOver(hit_eid);
|
|
|
|
|
|
|
|
|
|
CLAY(hit_eid,
|
|
|
|
|
@@ -2249,7 +2249,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
// Visible track (centered inside hit area, empty)
|
|
|
|
|
CLAY(CLAY_IDI("FdrTrack", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("FdrTrack", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -2264,7 +2264,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
F32 tw = (i % 5 == 0) ? tick_major_w : tick_minor_w;
|
|
|
|
|
|
|
|
|
|
// Left tick
|
|
|
|
|
CLAY(CLAY_IDI("FdrTkL", (int)(hash * 100 + i)),
|
|
|
|
|
CLAY(CLAY_IDI("FdrTkL", (S32)(hash * 100 + i)),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -2285,7 +2285,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
) {}
|
|
|
|
|
|
|
|
|
|
// Right tick
|
|
|
|
|
CLAY(CLAY_IDI("FdrTkR", (int)(hash * 100 + i)),
|
|
|
|
|
CLAY(CLAY_IDI("FdrTkR", (S32)(hash * 100 + i)),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -2315,7 +2315,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
|
|
|
|
|
F32 cap_y = (1.0f - normalized) * (track_h - cap_h);
|
|
|
|
|
|
|
|
|
|
CLAY(CLAY_IDI("FdrCap", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("FdrCap", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(cap_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -2336,7 +2336,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
Clay_Color tint = g_theme.accent;
|
|
|
|
|
tint.a = 80;
|
|
|
|
|
F32 cap_corner = cap_w * (3.0f / 62.2f);
|
|
|
|
|
CLAY(CLAY_IDI("FdrTint", (int)hash),
|
|
|
|
|
CLAY(CLAY_IDI("FdrTint", (S32)hash),
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(cap_h) },
|
|
|
|
|
},
|
|
|
|
|
@@ -2356,7 +2356,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Click: double-click resets, single click starts drag
|
|
|
|
|
// Click: F64-click resets, single click starts drag
|
|
|
|
|
if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) {
|
|
|
|
|
B32 is_double_click = (kd->last_click_id == hash &&
|
|
|
|
|
(g_frame_number - kd->last_click_frame) < 20);
|
|
|
|
|
@@ -2379,7 +2379,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
|
|
|
|
|
value_edit_render(hash, cap_w * 2.0f);
|
|
|
|
|
value_edit_click_away(value_edit_eid(hash), value, max_val, is_signed, &changed);
|
|
|
|
|
} else if (val_text && val_len > 0) {
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("FdrVal", (int)hash);
|
|
|
|
|
Clay_ElementId val_eid = CLAY_IDI("FdrVal", (S32)hash);
|
|
|
|
|
B32 val_hovered = Clay_PointerOver(val_eid);
|
|
|
|
|
|
|
|
|
|
Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text };
|
|
|
|
|
|