From a569454df5a5e0594bccda1a29178d6758e08936 Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Wed, 8 Mar 2023 19:53:28 +0100 Subject: [PATCH] [ui, wip] scrolling / scrolling panels --- examples/ui_style_test/main.c | 362 ++++++++++++++++++++++++++++++++-- src/ui.c | 255 +++++++----------------- src/ui.h | 19 +- 3 files changed, 437 insertions(+), 199 deletions(-) diff --git a/examples/ui_style_test/main.c b/examples/ui_style_test/main.c index 6281b59..4175373 100644 --- a/examples/ui_style_test/main.c +++ b/examples/ui_style_test/main.c @@ -78,7 +78,7 @@ void debug_print_size(ui_box* box, ui_axis axis, int indent) { debug_print_indent(indent); printf("size %s: ", axis == UI_AXIS_X ? "x" : "y"); - switch(box->targetStyle->size.s[axis].kind) + switch(box->targetStyle->size.c[axis].kind) { case UI_SIZE_TEXT: printf("text\n"); @@ -177,6 +177,127 @@ mg_font create_font() return(font); } +void widget_begin_view(char* str) +{ + ui_style_next(&(ui_style){.layout.axis = UI_AXIS_Y, + .layout.spacing = 10, + .layout.margin.x = 10, + .layout.margin.y = 10, + .layout.align.x = UI_ALIGN_CENTER, + .layout.align.y = UI_ALIGN_START}, + UI_STYLE_LAYOUT); + + ui_box_begin(str, UI_FLAG_DRAW_BORDER); + ui_label(str); + +} + +void widget_end_view(void) +{ + ui_box_end(); +} + +#define widget_view(s) defer_loop(widget_begin_view(s), widget_end_view()) + + +void panel_begin(char* str, ui_flags flags) +{ + ui_box* box = ui_box_begin(str, flags | UI_FLAG_CLIP | UI_FLAG_BLOCK_MOUSE); + + ui_style contentsStyle = { + .size.width = {UI_SIZE_CHILDREN}, + .size.height = {UI_SIZE_CHILDREN}, + .floating.x = true, + .floating.y = true, + .floatTarget = {-box->scroll.x, -box->scroll.y}}; + + ui_style_next(&contentsStyle, UI_STYLE_FLOAT); + ui_box_begin("contents", 0); + +} + +void panel_end(void) +{ + ui_box* contents = ui_box_top(); + ui_box_end(); + + ui_box* panel = ui_box_top(); + ui_sig sig = ui_box_sig(panel); + + f32 contentsW = ClampLowBound(contents->rect.w, panel->rect.w); + f32 contentsH = ClampLowBound(contents->rect.h, panel->rect.h); + + contentsW = ClampLowBound(contentsW, 1); + contentsH = ClampLowBound(contentsH, 1); + + ui_box* scrollBarX = 0; + ui_box* scrollBarY = 0; + + if(contentsW > panel->rect.w) + { + f32 thumbRatioX = panel->rect.w / contentsW; + f32 sliderX = panel->scroll.x /(contentsW - panel->rect.w); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1., 0}, + .size.height = {UI_SIZE_PIXELS, 10, 0}, + .floating.x = true, + .floating.y = true, + .floatTarget = {0, panel->rect.h - 12}}, + UI_STYLE_SIZE); + + scrollBarX = ui_slider("scrollerX", thumbRatioX, &sliderX); + + panel->scroll.x = sliderX * (contentsW - panel->rect.w); + if(sig.hovering) + { + panel->scroll.x += sig.wheel.x; + ui_box_activate(scrollBarX); + } + } + + if(contentsH > panel->rect.h) + { + f32 thumbRatioY = panel->rect.h / contentsH; + f32 sliderY = panel->scroll.y /(contentsH - panel->rect.h); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 10, 0}, + .size.height = {UI_SIZE_PARENT, 1., 0}, + .floating.x = true, + .floating.y = true, + .floatTarget = {panel->rect.w - 12, 0}}, + UI_STYLE_SIZE + |UI_STYLE_FLOAT); + + scrollBarY = ui_slider("scrollerY", thumbRatioY, &sliderY); + + panel->scroll.y = sliderY * (contentsH - panel->rect.h); + if(sig.hovering) + { + panel->scroll.y += sig.wheel.y; + ui_box_activate(scrollBarY); + } + } + + panel->scroll.x = Clamp(panel->scroll.x, 0, contentsW - panel->rect.w); + panel->scroll.y = Clamp(panel->scroll.y, 0, contentsH - panel->rect.h); + + if(scrollBarX) + { +// ui_box_set_floating(scrollBarX, UI_AXIS_X, panel->scroll.x); +// ui_box_set_floating(scrollBarX, UI_AXIS_Y, panel->scroll.y + panel->rect.h - 12); + } + + if(scrollBarY) + { +// ui_box_set_floating(scrollBarY, UI_AXIS_X, panel->scroll.x + panel->rect.w - 12); +// ui_box_set_floating(scrollBarY, UI_AXIS_Y, panel->scroll.y); + } + + ui_box_end(); +} + +#define panel(s, f) defer_loop(panel_begin(s, f), panel_end()) + int main() { LogLevel(LOG_LEVEL_WARNING); @@ -206,6 +327,9 @@ int main() mg_font font = create_font(); + mem_arena textArena = {0}; + mem_arena_init(&textArena); + // start app mp_window_bring_to_front(window); mp_window_focus(window); @@ -242,26 +366,218 @@ int main() } //TEST UI - ui_style defaultStyle = {.size.width = {UI_SIZE_CHILDREN}, - .size.height = {UI_SIZE_CHILDREN}, - .layout.axis = UI_AXIS_Y, - .layout.spacing = 10, - .layout.margin.x = 10, - .layout.margin.y = 10, - .bgColor = {0.9, 0.9, 0.9, 1}, - .color = {0, 0, 0, 1}, - .borderSize = 2, - .borderColor = {0, 0, 1, 1}, + ui_style defaultStyle = {.bgColor = {0}, + .color = {1, 1, 1, 1}, .font = font, - .fontSize = 32}; + .fontSize = 16, + .borderColor = {1, 0, 0, 1}, + .borderSize = 2}; - ui_flags defaultFlags = UI_FLAG_DRAW_BORDER | UI_FLAG_DRAW_BACKGROUND; + ui_style_mask defaultMask = UI_STYLE_BG_COLOR + | UI_STYLE_COLOR + | UI_STYLE_BORDER_COLOR + | UI_STYLE_BORDER_SIZE + | UI_STYLE_FONT + | UI_STYLE_FONT_SIZE; + + ui_flags debugFlags = UI_FLAG_DRAW_BORDER; ui_box* root = 0; ui_frame() { root = ui_box_top(); + ui_style_match_before(ui_pattern_all(), &defaultStyle, defaultMask); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 1}, + .layout.axis = UI_AXIS_Y, + .layout.align.x = UI_ALIGN_CENTER, + .layout.align.y = UI_ALIGN_START, + .layout.spacing = 10, + .layout.margin.x = 10, + .layout.margin.y = 10, + .bgColor = {0.11, 0.11, 0.11, 1}}, + UI_STYLE_SIZE + | UI_STYLE_LAYOUT + | UI_STYLE_BG_COLOR); + + ui_container("background", UI_FLAG_DRAW_BACKGROUND) + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_CHILDREN}, + .layout.align.x = UI_ALIGN_CENTER}, + UI_STYLE_SIZE + |UI_STYLE_LAYOUT_ALIGN_X); + ui_container("title", debugFlags) + { + ui_style_next(&(ui_style){.fontSize = 26}, UI_STYLE_FONT_SIZE); + ui_label("Milepost UI Demo"); + } + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PIXELS, 500}}, + UI_STYLE_SIZE); + + ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X}, UI_STYLE_LAYOUT_AXIS); + ui_container("contents", debugFlags) + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5}, + .size.height = {UI_SIZE_PARENT, 1}}, + UI_STYLE_SIZE); + + ui_container("left", debugFlags) + { + ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X, + .layout.spacing = 10, + .layout.margin.x = 10, + .layout.margin.y = 10, + .size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 0.5}}, + UI_STYLE_LAYOUT_AXIS + |UI_STYLE_LAYOUT_SPACING + |UI_STYLE_LAYOUT_MARGIN_X + |UI_STYLE_LAYOUT_MARGIN_Y + |UI_STYLE_SIZE); + + ui_container("up", debugFlags) + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5}, + .size.height = {UI_SIZE_PARENT, 1}}, + UI_STYLE_SIZE); + widget_view("Buttons") + { + ui_button("Button 1"); + ui_button("Button 2"); + ui_button("Button 3"); + } + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5}, + .size.height = {UI_SIZE_PARENT, 1}}, + UI_STYLE_SIZE); + widget_view("checkboxes") + { + + } + } + + ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X, + .size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 0.5}}, + UI_STYLE_LAYOUT_AXIS + |UI_STYLE_SIZE); + + ui_container("down", debugFlags) + { + widget_view("Vertical Sliders") + { + ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X, + .layout.spacing = 10}, + UI_STYLE_LAYOUT_AXIS + |UI_STYLE_LAYOUT_SPACING); + ui_container("contents", 0) + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20}, + .size.height = {UI_SIZE_PIXELS, 200}}, + UI_STYLE_SIZE); + static f32 slider1 = 0; + ui_slider("slider1", 0.2, &slider1); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20}, + .size.height = {UI_SIZE_PIXELS, 200}}, + UI_STYLE_SIZE); + static f32 slider2 = 0; + ui_slider("slider2", 0.2, &slider2); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20}, + .size.height = {UI_SIZE_PIXELS, 200}}, + UI_STYLE_SIZE); + static f32 slider3 = 0; + ui_slider("slider3", 0.2, &slider3); + } + } + + widget_view("Horizontal Sliders") + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 200}, + .size.height = {UI_SIZE_PIXELS, 20}}, + UI_STYLE_SIZE); + static f32 slider1 = 0; + ui_slider("slider1", 0.2, &slider1); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 200}, + .size.height = {UI_SIZE_PIXELS, 20}}, + UI_STYLE_SIZE); + static f32 slider2 = 0; + ui_slider("slider2", 0.2, &slider2); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 200}, + .size.height = {UI_SIZE_PIXELS, 20}}, + UI_STYLE_SIZE); + static f32 slider3 = 0; + ui_slider("slider3", 0.2, &slider3); + } + } + } + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5}, + .size.height = {UI_SIZE_PARENT, 1}}, + UI_STYLE_SIZE); + + ui_container("right", debugFlags) + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 0.33}}, + UI_STYLE_SIZE); + widget_view("Text box") + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 300}, + .size.height = {UI_SIZE_TEXT}}, + UI_STYLE_SIZE); + static str8 text = {}; + ui_text_box_result res = ui_text_box("textbox", mem_scratch(), text); + if(res.changed) + { + mem_arena_clear(&textArena); + text = str8_push_copy(&textArena, res.text); + } + } + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 0.33}}, + UI_STYLE_SIZE); + widget_view("Menus") + {} + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 0.33}}, + UI_STYLE_SIZE); + widget_view("Color") + { + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 0.7}}, + UI_STYLE_SIZE); + + panel("Panel", UI_FLAG_DRAW_BORDER) + { + + ui_style_next(&(ui_style){.layout.spacing = 20}, + UI_STYLE_LAYOUT_SPACING); + ui_container("buttons", 0) + { + ui_button("Button A"); + ui_button("Button B"); + ui_button("Button C"); + ui_button("Button D"); + } + } + } + } + } + + } + + /* ui_pattern pattern = {0}; ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("b")}); ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("foo")}); @@ -350,9 +666,25 @@ int main() } } - ui_tag_next("foo"); - ui_label("label d"); + ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X}, UI_STYLE_LAYOUT_AXIS); + ui_container("f", defaultFlags) + { + ui_tag_next("foo"); + ui_label("label d"); + + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 300}, + .size.height = {UI_SIZE_TEXT}}, + UI_STYLE_SIZE); + static str8 text = {}; + ui_text_box_result res = ui_text_box("textbox", mem_scratch(), text); + if(res.changed) + { + mem_arena_clear(&textArena); + text = str8_push_copy(&textArena, res.text); + } + } } + */ } if(printDebugStyle) { diff --git a/src/ui.c b/src/ui.c index 9b5f2ad..979024e 100644 --- a/src/ui.c +++ b/src/ui.c @@ -643,20 +643,20 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box) { if(flags & UI_STYLE_ANIMATE_SIZE_WIDTH) { - ui_animate_ui_size(ui, &box->style.size.s[UI_AXIS_X], targetStyle->size.s[UI_AXIS_X], animationTime); + ui_animate_ui_size(ui, &box->style.size.c[UI_AXIS_X], targetStyle->size.c[UI_AXIS_X], animationTime); } else { - box->style.size.s[UI_AXIS_X] = targetStyle->size.s[UI_AXIS_X]; + box->style.size.c[UI_AXIS_X] = targetStyle->size.c[UI_AXIS_X]; } if(flags & UI_STYLE_ANIMATE_SIZE_HEIGHT) { - ui_animate_ui_size(ui, &box->style.size.s[UI_AXIS_Y], targetStyle->size.s[UI_AXIS_Y], animationTime); + ui_animate_ui_size(ui, &box->style.size.c[UI_AXIS_Y], targetStyle->size.c[UI_AXIS_Y], animationTime); } else { - box->style.size.s[UI_AXIS_Y] = targetStyle->size.s[UI_AXIS_Y]; + box->style.size.c[UI_AXIS_Y] = targetStyle->size.c[UI_AXIS_Y]; } if(flags & UI_STYLE_ANIMATE_COLOR) @@ -714,7 +714,10 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box) box->style.roundness = targetStyle->roundness; } - //TODO: non animatable attributes use mask + //NOTE: float target is animated in compute rect + box->style.floatTarget = targetStyle->floatTarget; + + //TODO: non animatable attributes. use mask box->style.layout = targetStyle->layout; box->style.font = targetStyle->font; } @@ -724,11 +727,11 @@ void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask) { if(mask & UI_STYLE_SIZE_WIDTH) { - dst->size.s[UI_AXIS_X] = src->size.s[UI_AXIS_X]; + dst->size.c[UI_AXIS_X] = src->size.c[UI_AXIS_X]; } if(mask & UI_STYLE_SIZE_HEIGHT) { - dst->size.s[UI_AXIS_Y] = src->size.s[UI_AXIS_Y]; + dst->size.c[UI_AXIS_Y] = src->size.c[UI_AXIS_Y]; } if(mask & UI_STYLE_LAYOUT_AXIS) { @@ -756,12 +759,12 @@ void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask) } if(mask & UI_STYLE_FLOAT_X) { - dst->floating[UI_AXIS_X] = src->floating[UI_AXIS_X]; + dst->floating.c[UI_AXIS_X] = src->floating.c[UI_AXIS_X]; dst->floatTarget.x = src->floatTarget.x; } if(mask & UI_STYLE_FLOAT_Y) { - dst->floating[UI_AXIS_Y] = src->floating[UI_AXIS_Y]; + dst->floating.c[UI_AXIS_Y] = src->floating.c[UI_AXIS_Y]; dst->floatTarget.y = src->floatTarget.y; } if(mask & UI_STYLE_COLOR) @@ -935,8 +938,8 @@ void ui_styling_prepass(ui_context* ui, ui_box* box, list_info* before, list_inf ui_style* style = &box->style; mp_rect textBox = {}; - ui_size desiredSize[2] = {box->style.size.s[UI_AXIS_X], - box->style.size.s[UI_AXIS_Y]}; + ui_size desiredSize[2] = {box->style.size.c[UI_AXIS_X], + box->style.size.c[UI_AXIS_Y]}; if( desiredSize[UI_AXIS_X].kind == UI_SIZE_TEXT ||desiredSize[UI_AXIS_Y].kind == UI_SIZE_TEXT) @@ -950,7 +953,7 @@ void ui_styling_prepass(ui_context* ui, ui_box* box, list_info* before, list_inf if(size.kind == UI_SIZE_TEXT) { - f32 margin = style->layout.margin.m[i]; + f32 margin = style->layout.margin.c[i]; box->rect.c[2+i] = textBox.c[2+i] + margin*2; } else if(size.kind == UI_SIZE_PIXELS) @@ -976,35 +979,10 @@ void ui_styling_prepass(ui_context* ui, ui_box* box, list_info* before, list_inf } } -void ui_layout_upward_dependent_size(ui_context* ui, ui_box* box, int axis) -{ - if(ui_box_hidden(box)) - { - return; - } - - ui_size* size = &box->style.size.s[axis]; - - if(size->kind == UI_SIZE_PARENT) - { - ui_box* parent = box->parent; - if(parent) - { - f32 margin = parent->style.layout.margin.m[axis]; - box->rect.c[2+axis] = maximum(0, parent->rect.c[2+axis] - 2*margin) * size->value; - } - //TODO else? - } - - for_list(&box->children, child, ui_box, listElt) - { - ui_layout_upward_dependent_size(ui, child, axis); - } -} - void ui_layout_downward_dependent_size(ui_context* ui, ui_box* box, int axis) { f32 sum = 0; + f32 count = 0; if(box->style.layout.axis == axis) { @@ -1014,7 +992,7 @@ void ui_layout_downward_dependent_size(ui_context* ui, ui_box* box, int axis) if(!ui_box_hidden(child)) { ui_layout_downward_dependent_size(ui, child, axis); - if(!child->style.floating[axis] && child->style.size.s[axis].kind != UI_SIZE_PARENT) + if(!child->style.floating.c[axis]) { //TODO: maybe log an error if child is dependant on parent sum += child->rect.c[2+axis]; @@ -1022,7 +1000,7 @@ void ui_layout_downward_dependent_size(ui_context* ui, ui_box* box, int axis) } } } - sum += maximum(0, count-1)*box->style.layout.spacing; + box->spacing[axis] = maximum(0, count-1)*box->style.layout.spacing; } else { @@ -1031,21 +1009,48 @@ void ui_layout_downward_dependent_size(ui_context* ui, ui_box* box, int axis) if(!ui_box_hidden(child)) { ui_layout_downward_dependent_size(ui, child, axis); - if(!child->style.floating[axis]) + if(!child->style.floating.c[axis]) { sum = maximum(sum, child->rect.c[2+axis]); } } } + box->spacing[axis] = 0; } box->childrenSum[axis] = sum; - ui_size* size = &box->style.size.s[axis]; + ui_size* size = &box->style.size.c[axis]; if(size->kind == UI_SIZE_CHILDREN) { - f32 margin = box->style.layout.margin.m[axis]; - box->rect.c[2+axis] = sum + margin*2; + f32 margin = box->style.layout.margin.c[axis]; + box->rect.c[2+axis] = sum + box->spacing[axis] + 2*margin; + } +} + +void ui_layout_upward_dependent_size(ui_context* ui, ui_box* box, int axis) +{ + if(ui_box_hidden(box)) + { + return; + } + + ui_size* size = &box->style.size.c[axis]; + + if(size->kind == UI_SIZE_PARENT) + { + ui_box* parent = box->parent; + if(parent) + { + f32 margin = parent->style.layout.margin.c[axis]; + box->rect.c[2+axis] = maximum(0, parent->rect.c[2+axis] - parent->spacing[axis] - 2*margin) * size->value; + } + //TODO else? + } + + for_list(&box->children, child, ui_box, listElt) + { + ui_layout_upward_dependent_size(ui, child, axis); } } @@ -1070,10 +1075,10 @@ void ui_layout_compute_rect(ui_context* ui, ui_box* box, vec2 pos) ui_axis secondAxis = (layoutAxis == UI_AXIS_X) ? UI_AXIS_Y : UI_AXIS_X; f32 spacing = box->style.layout.spacing; - ui_align* align = box->style.layout.align.a; + ui_align* align = box->style.layout.align.c; - vec2 origin = {box->rect.x - box->scroll.x, - box->rect.y - box->scroll.y}; + vec2 origin = {box->rect.x, + box->rect.y}; vec2 currentPos = origin; vec2 margin = {box->style.layout.margin.x, @@ -1082,32 +1087,31 @@ void ui_layout_compute_rect(ui_context* ui, ui_box* box, vec2 pos) currentPos.x += margin.x; currentPos.y += margin.y; - vec2 contentsSize = {maximum(box->rect.w, box->childrenSum[UI_AXIS_X]), - maximum(box->rect.h, box->childrenSum[UI_AXIS_Y])}; - for(int i=0; ichildrenSum[i] - margin.c[i]; + currentPos.c[i] = origin.c[i] + box->rect.c[2+i] - (box->childrenSum[i] + box->spacing[i] + margin.c[i]); } } if(align[layoutAxis] == UI_ALIGN_CENTER) { - currentPos.c[layoutAxis] += 0.5*(contentsSize.c[layoutAxis] - box->childrenSum[layoutAxis]); + currentPos.c[layoutAxis] = origin.c[layoutAxis] + + 0.5*(box->rect.c[2+layoutAxis] + - (box->childrenSum[layoutAxis] + box->spacing[layoutAxis])); } for_list(&box->children, child, ui_box, listElt) { if(align[secondAxis] == UI_ALIGN_CENTER) { - currentPos.c[secondAxis] = origin.c[secondAxis] + 0.5*(contentsSize.c[secondAxis] - child->rect.c[2+secondAxis]); + currentPos.c[secondAxis] = origin.c[secondAxis] + 0.5*(box->rect.c[2+secondAxis] - child->rect.c[2+secondAxis]); } vec2 childPos = currentPos; for(int i=0; istyle.floating[i]) + if(child->style.floating.c[i]) { ui_style* style = child->targetStyle; if((child->targetStyle->animationFlags & UI_STYLE_ANIMATE_POS) @@ -1125,7 +1129,7 @@ void ui_layout_compute_rect(ui_context* ui, ui_box* box, vec2 pos) ui_layout_compute_rect(ui, child, childPos); - if(!child->style.floating[layoutAxis]) + if(!child->style.floating.c[layoutAxis]) { currentPos.c[layoutAxis] += child->rect.c[2+layoutAxis] + spacing; } @@ -1217,7 +1221,7 @@ void ui_draw_box(ui_box* box) if(box->flags & UI_FLAG_CLIP) { -// mg_clip_push(box->rect.x, box->rect.y, box->rect.w, box->rect.h); + mg_clip_push(box->rect.x, box->rect.y, box->rect.w, box->rect.h); } if(box->flags & UI_FLAG_DRAW_BACKGROUND) @@ -1254,7 +1258,7 @@ void ui_draw_box(ui_box* box) if(box->flags & UI_FLAG_CLIP) { -// mg_clip_pop(); + mg_clip_pop(); } if(box->flags & UI_FLAG_DRAW_BORDER) @@ -1299,8 +1303,8 @@ void ui_begin_frame() vec2 size = mg_canvas_size(); ui_style defaultStyle = {0}; - defaultStyle.size.s[UI_AXIS_X] = (ui_size){UI_SIZE_PIXELS, size.x}; - defaultStyle.size.s[UI_AXIS_Y] = (ui_size){UI_SIZE_PIXELS, size.y}; + defaultStyle.size.c[UI_AXIS_X] = (ui_size){UI_SIZE_PIXELS, size.x}; + defaultStyle.size.c[UI_AXIS_Y] = (ui_size){UI_SIZE_PIXELS, size.y}; ui->root = ui_box_begin("_root_", 0); *ui->root->targetStyle = defaultStyle; @@ -1412,15 +1416,19 @@ ui_sig ui_button_str8(str8 label) { ui_context* ui = ui_get_context(); - ui_style defaultStyle = {.size.width = {UI_SIZE_TEXT, 5, 0}, - .size.height = {UI_SIZE_TEXT, 5, 0}, + ui_style defaultStyle = {.size.width = {UI_SIZE_TEXT}, + .size.height = {UI_SIZE_TEXT}, + .layout.margin.x = 5, + .layout.margin.y = 5, .bgColor = {0.5, 0.5, 0.5, 1}, .borderColor = {0.2, 0.2, 0.2, 1}, - .borderSize = 2, + .borderSize = 1, .roundness = 10}; ui_style_mask defaultMask = UI_STYLE_SIZE_WIDTH | UI_STYLE_SIZE_HEIGHT + | UI_STYLE_LAYOUT_MARGIN_X + | UI_STYLE_LAYOUT_MARGIN_Y | UI_STYLE_BG_COLOR | UI_STYLE_BORDER_COLOR | UI_STYLE_BORDER_SIZE @@ -1430,7 +1438,7 @@ ui_sig ui_button_str8(str8 label) ui_style activeStyle = {.bgColor = {0.3, 0.3, 0.3, 1}, .borderColor = {0.2, 0.2, 0.2, 1}, - .borderSize = 4}; + .borderSize = 2}; ui_style_mask activeMask = UI_STYLE_BG_COLOR | UI_STYLE_BORDER_COLOR | UI_STYLE_BORDER_SIZE; @@ -1502,13 +1510,13 @@ ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue) .roundness = roundness}; ui_style beforeStyle = trackStyle; - beforeStyle.size.s[trackAxis] = (ui_size){UI_SIZE_PARENT, beforeRatio}; + beforeStyle.size.c[trackAxis] = (ui_size){UI_SIZE_PARENT, beforeRatio}; ui_style afterStyle = trackStyle; - afterStyle.size.s[trackAxis] = (ui_size){UI_SIZE_PARENT, afterRatio}; + afterStyle.size.c[trackAxis] = (ui_size){UI_SIZE_PARENT, afterRatio}; ui_style thumbStyle = trackStyle; - thumbStyle.size.s[trackAxis] = (ui_size){UI_SIZE_PARENT, thumbRatio}; + thumbStyle.size.c[trackAxis] = (ui_size){UI_SIZE_PARENT, thumbRatio}; thumbStyle.bgColor = (mg_color){0.3, 0.3, 0.3, 1}; ui_style_mask styleMask = UI_STYLE_SIZE_WIDTH @@ -1594,121 +1602,7 @@ ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue) return(frame); } - -ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue) -{ - ui_box* frame = ui_box_begin(label, 0); - { - ui_axis trackAxis = (frame->rect.w > frame->rect.h) ? UI_AXIS_X : UI_AXIS_Y; - ui_axis secondAxis = (trackAxis == UI_AXIS_Y) ? UI_AXIS_X : UI_AXIS_Y; - - f32 roundness = 0.5*frame->rect.c[2+secondAxis]; - f32 animationTime = 0.5; - - -/* ui_push_bg_color((mg_color){0, 0, 0, 0}); - ui_push_fg_color((mg_color){0, 0, 0, 0}); - ui_push_roundness(roundness); - - ui_push_bg_color_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE, (mg_color){0, 0, 0, 0.5}); - ui_push_fg_color_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE, (mg_color){0, 0, 0, 0.7}); - ui_push_roundness_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE, roundness); - ui_push_animation_time_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, 1.); - ui_push_animation_flags_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, UI_STYLE_ANIMATE_BG_COLOR|UI_STYLE_ANIMATE_FG_COLOR); -*/ - ui_flags trackFlags = UI_FLAG_CLIP - | UI_FLAG_DRAW_BACKGROUND - | UI_FLAG_HOT_ANIMATION - | UI_FLAG_ACTIVE_ANIMATION; - - ui_box* track = ui_box_begin("track", trackFlags); - -// ui_box_set_size(track, trackAxis, UI_SIZE_PARENT, 1., 0); -// ui_box_set_size(track, secondAxis, UI_SIZE_PARENT, 1., 0); - //ui_box_set_layout(track, trackAxis, UI_ALIGN_START, UI_ALIGN_START); - - f32 beforeRatio = (*scrollValue) * (1. - thumbRatio); - f32 afterRatio = (1. - *scrollValue) * (1. - thumbRatio); - - ui_box* beforeSpacer = ui_box_make("before", 0); -// ui_box_set_size(beforeSpacer, trackAxis, UI_SIZE_PARENT, beforeRatio, 0); -// ui_box_set_size(beforeSpacer, secondAxis, UI_SIZE_PARENT, 1., 0); - - ui_flags thumbFlags = UI_FLAG_CLICKABLE - | UI_FLAG_DRAW_FOREGROUND - | UI_FLAG_HOT_ANIMATION - | UI_FLAG_ACTIVE_ANIMATION; - - ui_box* thumb = ui_box_make("thumb", thumbFlags); -// ui_box_set_size(thumb, trackAxis, UI_SIZE_PARENT, thumbRatio, 0); -// ui_box_set_size(thumb, secondAxis, UI_SIZE_PARENT, 1., 0); - - ui_box* afterSpacer = ui_box_make("after", 0); -// ui_box_set_size(afterSpacer, trackAxis, UI_SIZE_PARENT, afterRatio, 0); -// ui_box_set_size(afterSpacer, secondAxis, UI_SIZE_PARENT, 1., 0); - - ui_box_end(); /* - ui_pop_bg_color(); - ui_pop_fg_color(); - ui_pop_roundness(); - ui_pop_bg_color(); - ui_pop_fg_color(); - ui_pop_roundness(); - ui_pop_animation_time(); - ui_pop_animation_flags(); -*/ - //NOTE: interaction - ui_sig thumbSig = ui_box_sig(thumb); - if(thumbSig.dragging) - { - f32 trackExtents = track->rect.c[2+trackAxis] - thumb->rect.c[2+trackAxis]; - f32 delta = thumbSig.delta.c[trackAxis]/trackExtents; - f32 oldValue = *scrollValue; - - *scrollValue += delta; - *scrollValue = Clamp(*scrollValue, 0, 1); - } - - ui_sig trackSig = ui_box_sig(track); - - if(ui_box_active(frame)) - { - //NOTE: activated from outside - ui_box_set_hot(track, true); - ui_box_set_hot(thumb, true); - ui_box_activate(track); - ui_box_activate(thumb); - } - - if(trackSig.hovering) - { - ui_box_set_hot(track, true); - ui_box_set_hot(thumb, true); - } - else if(thumbSig.wheel.c[trackAxis] == 0) - { - ui_box_set_hot(track, false); - ui_box_set_hot(thumb, false); - } - - if(thumbSig.dragging) - { - ui_box_activate(track); - ui_box_activate(thumb); - } - else if(thumbSig.wheel.c[trackAxis] == 0) - { - ui_box_deactivate(track); - ui_box_deactivate(thumb); - ui_box_deactivate(frame); - } - - } ui_box_end(); - - return(frame); -} - ui_box* ui_panel_begin(const char* name) { ui_flags panelFlags = UI_FLAG_DRAW_BACKGROUND @@ -1785,6 +1679,7 @@ void ui_panel_end() ui_box_end(); } +*/ ui_sig ui_tooltip_begin(const char* name) { diff --git a/src/ui.h b/src/ui.h index 74398ec..5a33543 100644 --- a/src/ui.h +++ b/src/ui.h @@ -59,7 +59,7 @@ typedef union ui_layout_align ui_align x; ui_align y; }; - ui_align a[UI_AXIS_COUNT]; + ui_align c[UI_AXIS_COUNT]; } ui_layout_align; typedef struct ui_layout @@ -73,7 +73,7 @@ typedef struct ui_layout f32 x; f32 y; }; - f32 m[UI_AXIS_COUNT]; + f32 c[UI_AXIS_COUNT]; } margin; ui_layout_align align; @@ -102,9 +102,19 @@ typedef union ui_box_size ui_size width; ui_size height; }; - ui_size s[UI_AXIS_COUNT]; + ui_size c[UI_AXIS_COUNT]; } ui_box_size; +typedef union ui_box_floating +{ + struct + { + bool x; + bool y; + }; + bool c[UI_AXIS_COUNT]; +} ui_box_floating; + typedef enum { UI_STYLE_ANIMATE_SIZE_WIDTH = 1<<1, UI_STYLE_ANIMATE_SIZE_HEIGHT = 1<<2, UI_STYLE_ANIMATE_COLOR = 1<<3, @@ -120,7 +130,7 @@ typedef struct ui_style { ui_box_size size; ui_layout layout; - bool floating[UI_AXIS_COUNT]; + ui_box_floating floating; vec2 floatTarget; mg_color color; mg_color bgColor; @@ -291,6 +301,7 @@ struct ui_box vec2 floatPos; f32 childrenSum[2]; + f32 spacing[2]; mp_rect rect; // signals