From b7e66977b178a8e3a6d1f788dd22b4c433ba9826 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Fri, 13 Jan 2023 14:53:19 +0100 Subject: [PATCH] correct clipping and culling of elements --- test/main.c | 16 +++++------- ugui.c | 75 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/test/main.c b/test/main.c index aef02cf..68e71b2 100644 --- a/test/main.c +++ b/test/main.c @@ -191,14 +191,14 @@ int main(void) // ug_container_remove(ctx, "Menu fichissimo"); //} - ug_container_floating(ctx, "stupid name", (ug_div_t){.x=SIZE_PX(0), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)}); + //ug_container_floating(ctx, "stupid name", (ug_div_t){.x=SIZE_PX(0), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)}); //ug_container_floating(ctx, "floating windoooooooow", (ug_div_t){.x=SIZE_PX(100), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)}); - ug_container_sidebar(ctx, "Right Sidebar", (ug_size_t)SIZE_PX(300), UG_SIDE_RIGHT); - ug_container_sidebar(ctx, "Left Sidebar", (ug_size_t)SIZE_PX(200), UG_SIDE_LEFT); + //ug_container_sidebar(ctx, "Right Sidebar", (ug_size_t)SIZE_PX(300), UG_SIDE_RIGHT); + //ug_container_sidebar(ctx, "Left Sidebar", (ug_size_t)SIZE_PX(200), UG_SIDE_LEFT); //ug_container_sidebar(ctx, "Bottom Sidebar", (ug_size_t)SIZE_MM(10), UG_SIDE_BOTTOM); - //ug_container_sidebar(ctx, "Top Sidebar", (ug_size_t)SIZE_MM(40), UG_SIDE_TOP); + ug_container_sidebar(ctx, "Top Sidebar", (ug_size_t)SIZE_MM(40), UG_SIDE_TOP); // ug_container_popup(ctx, "Annoying popup", (ug_div_t){.x=SIZE_MM(150), .y=SIZE_MM(150), .w=SIZE_PX(100), .h=SIZE_MM(75.0)}); @@ -207,16 +207,14 @@ int main(void) // printf("No space!\n"); ug_layout_row(ctx); - if (ug_element_button(ctx, "button", "btn", (ug_div_t){.w=SIZE_PX(20),.h=SIZE_PX(20)})) - printf("nope\n"); + ug_element_button(ctx, "button 1", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)}); ug_element_button(ctx, "button 2", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)}); - ug_element_button(ctx, "button 3", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)}); - + //ug_element_button(ctx, "button 3", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)}); ug_layout_column(ctx); ug_element_button(ctx, "button 4", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)}); ug_element_button(ctx, "button 5", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)}); - ug_element_button(ctx, "button 6", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10),.x=SIZE_PX(-10)}); + //ug_element_button(ctx, "button 6", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10),.x=SIZE_PX(-10)}); ug_frame_end(ctx); diff --git a/ugui.c b/ugui.c index eaaf7d8..f139229 100644 --- a/ugui.c +++ b/ugui.c @@ -593,8 +593,8 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy))) { cnt->flags |= CNT_STATE_RESIZE_B; - rect->h += ctx->mouse.delta.y; - rca->h += ctx->mouse.delta.y; + rect->h = MAX(10, rect->h + ctx->mouse.delta.y); + rca->h = MAX(10, rca->h + ctx->mouse.delta.y); } } @@ -1022,6 +1022,9 @@ int ug_frame_end(ug_ctx_t *ctx) ug_container_t *c = &ctx->cnt_stack.items[i]; // draw containers draw_container(ctx, c, c->name); + // TODO: add a debug flag + // debug draw space used by elements + push_rect_command(ctx, &c->space, (ug_color_t)RGBA_FORMAT(0x0000abf0)); // draw elements draw_elements(ctx, c); // reset the layout to row @@ -1183,10 +1186,30 @@ static ug_element_t *get_element(ug_container_t *cnt, ug_id_t id) } +// TODO: move these to the top and use theme everywhere needed // update the element's position in the container area +#define R_MARGIN(r, b) (r.x + r.w - b) +#define L_MARGIN(r, b) (r.x + b) +#define T_MARGIN(r, b) (r.y + b) +#define B_MARGIN(r, b) (r.y + r.h - b) +// check if ra is outside of rb +#define OUTSIDE(ra, ba, rb, bb) (L_MARGIN(ra, ba) > R_MARGIN(rb, bb) || \ + T_MARGIN(ra, ba) > B_MARGIN(rb, bb) || \ + R_MARGIN(ra, ba) < L_MARGIN(rb, bb) || \ + B_MARGIN(ra, ba) < T_MARGIN(rb, bb)) static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *elem) { + // if there is no space then return + if (TEST(cnt->flags, CNT_LAYOUT_COLUMN)) { + if (cnt->space.h >= cnt->rca.h) + return -1; + } else { + if (cnt->space.w >= cnt->rca.w) + return -1; + } + + ug_rect_t *rect, *rca; rect = &(elem->rect); rca = &(elem->rca); @@ -1200,8 +1223,10 @@ static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *el const ug_style_t *s = ctx->style_px; // FIXME: different border thickness - int b = SZ_INT(s->border.size); - int m = SZ_INT(s->margin); + int b = SZ_INT(s->border.size); + int m = SZ_INT(s->margin); + // TODO: element borders + int eb = 0; int cx, cy, cw, ch; // FIXME: this may not work @@ -1224,33 +1249,42 @@ static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *el rca->x = cx + rect->x; rca->y = cy + rect->y; - // if there is no space for the element - if (cnt->space.w + rca->w > cnt->rca.w || cnt->space.h + rca->h > cnt->rca.h) - return -1; - // or the element was put outside of the container - if (rca->x >= cnt->rca.x + cnt->rca.w || rca->y >= cnt->rca.y + cnt->rca.h) + // if the element was put outside of the container return, this can happen + // because of the element offset + // FIXME: can we do this check before? + if (OUTSIDE((*rca), eb, cnt->rca, b)) return -1; - // FIXME: crop element if it is partially outside, this shit introduces - // all sorts of resizing bugs - if (rca->x < cnt->rca.x + cnt->rca.w && rca->x + rca->w > cnt->rca.x + cnt->rca.w) - rca->w = rca->x + rca->w - (cnt->rca.x + cnt->rca.w); + if (R_MARGIN((*rca), eb) > R_MARGIN(cnt->rca, b)) + rca->w = R_MARGIN(cnt->rca, b) - L_MARGIN((*rca), eb); + if (L_MARGIN((*rca), eb) < L_MARGIN(cnt->rca, b)) { + rca->x = L_MARGIN(cnt->rca, b); + rca->w -= L_MARGIN(cnt->rca, b) - L_MARGIN((*rca), eb); + } + + if (T_MARGIN((*rca), eb) < T_MARGIN(cnt->rca, b)) { + rca->y = T_MARGIN(cnt->rca, b); + rca->h -= T_MARGIN(cnt->rca, b) - T_MARGIN((*rca), eb); + } + + if (B_MARGIN((*rca), eb) > B_MARGIN(cnt->rca, b)) + rca->h = B_MARGIN(cnt->rca, b) - T_MARGIN((*rca), eb); + if (TEST(cnt->flags, CNT_LAYOUT_COLUMN)) { cnt->c_orig.y += rca->h + m; cnt->r_orig.y += rca->h + m; - cnt->space.h += rca->h; - if ((cnt->space.x + cnt->space.w) < (rca->x + rca->w)) - cnt->space.w += cnt->space.x + cnt->space.w - rca->x - rca->w; + } else { cnt->r_orig.x += rca->w + m; cnt->c_orig.x += rca->w + m; - cnt->space.w += rca->w; - if ((cnt->space.y + cnt->space.h) < (rca->y + rca->h)) - cnt->space.h += cnt->space.y + cnt->space.h - rca->y - rca->h; } - + if (B_MARGIN(cnt->space, 0) < B_MARGIN((*rca), eb)) + cnt->space.h = B_MARGIN((*rca), eb) - T_MARGIN(cnt->space, 0); + if (R_MARGIN(cnt->space, 0) < R_MARGIN((*rca), eb)) + cnt->space.w = R_MARGIN((*rca), eb) - L_MARGIN(cnt->space, 0); + return 0; } @@ -1276,7 +1310,6 @@ int ug_element_button(ug_ctx_t *ctx, const char *name, const char *txt, ug_div_t ug_container_t *cp; GET_SELECTED_CONTAINER(ctx, cp); - printf("selected: %x\n", ctx->selected_cnt); ug_id_t id = hash(name, strlen(name)); ug_element_t *elem = get_element(cp, id);