From 17a2bc32b88ee19494c5171b476d2b7610db2369 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Thu, 8 Dec 2022 01:02:44 +0100 Subject: [PATCH] working again --- ugui.c | 212 ++++++++++++++++++++++++++++----------------------------- ugui.h | 5 +- 2 files changed, 108 insertions(+), 109 deletions(-) diff --git a/ugui.c b/ugui.c index d35268e..dbf6a27 100644 --- a/ugui.c +++ b/ugui.c @@ -174,6 +174,10 @@ int ug_ctx_set_displayinfo(ug_ctx_t *ctx, float scale, float ppi) if (scale <= 0 || ppi < 20.0) return -1; + ctx->last_ppi = ctx->ppi; + ctx->last_ppm = ctx->ppd; + ctx->last_ppd = ctx->ppm; + ctx->ppm = PPI_PPM(scale, ppi); ctx->ppd = PPI_PPM(scale, ppi); ctx->ppi = ppi; @@ -253,27 +257,37 @@ static ug_container_t *get_container(ug_ctx_t *ctx, ug_id_t id) // also handle resizing, moving, ect. if allowed by the container static void update_container(ug_ctx_t *ctx, ug_container_t *cnt) { - // use millimeters as common screen-relative units - if (cnt->unit == UG_UNIT_PT) { - cnt->rect.fx *= ctx->ppd; - cnt->rect.fy *= ctx->ppd; - cnt->rect.fw *= ctx->ppd; - cnt->rect.fh *= ctx->ppd; - } - - // recalculate position + // if the container is new it has never been converted to pixels if (cnt->unit != UG_UNIT_PX) { - cnt->rect_abs.x = roundf(cnt->rect.fx * ctx->ppm); - cnt->rect_abs.y = roundf(cnt->rect.fy * ctx->ppm); - cnt->rect_abs.w = roundf(cnt->rect.fw * ctx->ppm); - cnt->rect_abs.h = roundf(cnt->rect.fh * ctx->ppm); + float scale = 1.0; + switch (ctx->unit) { + case UG_UNIT_MM: scale = ctx->ppm; break; + case UG_UNIT_PT: scale = ctx->ppd; break; + default: break; + } + cnt->rect.x = roundf(cnt->rect.fx * scale); + cnt->rect.y = roundf(cnt->rect.fy * scale); + cnt->rect.w = roundf(cnt->rect.fw * scale); + cnt->rect.h = roundf(cnt->rect.fh * scale); + + cnt->unit = UG_UNIT_PX; + } else if (ctx->ppi != ctx->last_ppi) { + // if the scale has been updated than we need to scale the container + // as well + float scale = ctx->ppi / ctx->last_ppi; + cnt->rect.x = roundf(cnt->rect.x * scale); + cnt->rect.y = roundf(cnt->rect.y * scale); + cnt->rect.w = roundf(cnt->rect.w * scale); + cnt->rect.h = roundf(cnt->rect.h * scale); } + cnt->rca = cnt->rect; + /* * Container style: * - * rect_abs(0,0) - * v + * rca + * v * +-----------------------------------------------+ * | Titlebar | * +-----------------------------------------------+ @@ -299,111 +313,83 @@ static void update_container(ug_ctx_t *ctx, ug_container_t *cnt) */ const ug_style_t *s = ctx->style_px; + int bl = s->cnt.border.l.size; + int br = s->cnt.border.r.size; + int bt = s->cnt.border.t.size; + int bb = s->cnt.border.b.size; + int hh = s->cnt.titlebar.height.size; + int cw = ctx->size.w; + int ch = ctx->size.h; + // 0 -> take all the space, <0 -> take absolute - if (cnt->rect_abs.w < 0) cnt->rect_abs.w = -cnt->rect_abs.w; - if (cnt->rect_abs.h < 0) cnt->rect_abs.h = -cnt->rect_abs.h; + if (cnt->rect.w < 0) cnt->rca.w = -cnt->rect.w; + if (cnt->rect.h < 0) cnt->rca.h = -cnt->rect.h; - if (cnt->rect_abs.w == 0) { - cnt->rect_abs.w = ctx->size.w - - s->cnt.border.l.size - - s->cnt.border.r.size ; - } else { - cnt->rect_abs.w += s->cnt.border.r.size + s->cnt.border.l.size; - } - if (cnt->rect_abs.h == 0) { - cnt->rect_abs.h = ctx->size.h - - s->cnt.border.t.size - - s->cnt.border.b.size ; - } else { - cnt->rect_abs.h += s->cnt.border.t.size + s->cnt.border.b.size; - } - if (cnt->flags & UG_CNT_MOVABLE) - cnt->rect_abs.h += s->cnt.titlebar.height.size; + // handle relative position + // and move to fit borders + if (cnt->rect.w == 0) cnt->rca.w = cw - br - bl; + else cnt->rca.w += bl + br; + if (cnt->rect.h == 0) cnt->rca.h = ch - bt - bb; + else if (cnt->flags & UG_CNT_MOVABLE) cnt->rca.h += hh + 2*bt + bb; + else cnt->rca.h += bt + bb; // the window may have been resized so cap the position to the window size - if (cnt->rect_abs.x > ctx->size.w) - cnt->rect_abs.x = ctx->size.x - cnt->rect_abs.w; - if (cnt->rect_abs.y > ctx->size.h) - cnt->rect_abs.y = ctx->size.y - cnt->rect_abs.h; + // FIXME: is MAX(cw - bl, 0) better? + if (cnt->rect.x > cw) cnt->rca.x = cw; + if (cnt->rect.y > ch) cnt->rca.y = ch; // <0 -> relative to the right margin - if (cnt->rect_abs.x < 0) - cnt->rect_abs.x = ctx->size.x - cnt->rect_abs.w + cnt->rect_abs.x; - if (cnt->rect_abs.y < 0) - cnt->rect_abs.y = ctx->size.y - cnt->rect_abs.h + cnt->rect_abs.y; + if (cnt->rect.x < 0) cnt->rca.x = cw - cnt->rca.w + cnt->rca.x; + if (cnt->rect.y < 0) cnt->rca.y = ch - cnt->rca.h + cnt->rca.y; // if we had focus the frame before, then do shit - // FIXME: if this is a brand new container then do we need to handle user - // inputs, since all inputs lag one frame, then it would make no sense if (ctx->hover.cnt_last != cnt->id) goto cnt_draw; // mouse pressed handle resize, for simplicity containers can only // be resized from the bottom and right border + // TODO: bring selected container to the top of the stack if (!(ctx->mouse.down_mask & UG_BTN_LEFT) || !(cnt->flags & (UG_CNT_RESIZABLE | UG_CNT_MOVABLE))) goto cnt_draw; ug_vec2_t mpos = ctx->mouse.pos; int minx, maxx, miny, maxy; - int delta_x = 0, delta_y = 0, delta_w = 0, delta_h = 0; // handle movable windows if (cnt->flags & UG_CNT_MOVABLE) { - minx = cnt->rect_abs.x; - maxx = cnt->rect_abs.x + cnt->rect_abs.w - s->cnt.border.l.size; - miny = cnt->rect_abs.y; - maxy = cnt->rect_abs.y + s->cnt.titlebar.height.size; - if (BETWEEN(mpos.x, minx, maxx) && - BETWEEN(mpos.y, miny, maxy)) { - cnt->rect_abs.x += ctx->mouse.delta.x; - cnt->rect_abs.y += ctx->mouse.delta.y; - - delta_x = ctx->mouse.delta.x; - delta_y = ctx->mouse.delta.y; + minx = cnt->rca.x; + maxx = cnt->rca.x + cnt->rca.w - br; + miny = cnt->rca.y; + maxy = cnt->rca.y + bt + hh; + if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) { + cnt->rect.x += ctx->mouse.delta.x; + cnt->rect.y += ctx->mouse.delta.y; + cnt->rca.x += ctx->mouse.delta.x; + cnt->rca.y += ctx->mouse.delta.y; } } - if (cnt->flags & UG_CNT_RESIZABLE) { // right border resize - minx = cnt->rect_abs.x + cnt->rect_abs.w - s->cnt.border.r.size; - maxx = cnt->rect_abs.x + cnt->rect_abs.w; - miny = cnt->rect_abs.y; - maxy = cnt->rect_abs.y + cnt->rect_abs.h; + minx = cnt->rca.x + cnt->rca.w - br; + maxx = cnt->rca.x + cnt->rca.w; + miny = cnt->rca.y; + maxy = cnt->rca.y + cnt->rca.h; if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) { - cnt->rect_abs.w += ctx->mouse.delta.x; - CAP(cnt->rect_abs.w, 0); - - delta_w = ctx->mouse.delta.x; - } + cnt->rect.w += ctx->mouse.delta.x; + cnt->rca.w += ctx->mouse.delta.x; + } // bottom border resize - minx = cnt->rect_abs.x; - maxx = cnt->rect_abs.x + cnt->rect_abs.w; - miny = cnt->rect_abs.y + cnt->rect_abs.h - s->cnt.border.b.size; - maxy = cnt->rect_abs.y + cnt->rect_abs.h; + minx = cnt->rca.x; + maxx = cnt->rca.x + cnt->rca.w; + miny = cnt->rca.y + cnt->rca.h - bb; + maxy = cnt->rca.y + cnt->rca.h; if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) { - cnt->rect_abs.h += ctx->mouse.delta.y; - CAP(cnt->rect_abs.h, s->text.size.size); - - delta_h = ctx->mouse.delta.y; - } - } - - if (delta_x || delta_y || delta_w || delta_h) { - if (cnt->unit == UG_UNIT_PX) { - cnt->rect = cnt->rect_abs; - } else { - if (cnt->rect.fx < 0) - cnt->rect.fx = cnt->rect_abs.x / ctx->ppm; - if (cnt->rect.fy < 0) - cnt->rect.fy = cnt->rect_abs.y / ctx->ppm; - cnt->rect.fx += delta_x / ctx->ppm; - cnt->rect.fy += delta_y / ctx->ppm; - cnt->rect.fw += delta_w / ctx->ppm; - cnt->rect.fh += delta_h / ctx->ppm; + cnt->rect.h += ctx->mouse.delta.y; + cnt->rca.h += ctx->mouse.delta.y; } } @@ -414,30 +400,34 @@ static void update_container(ug_ctx_t *ctx, ug_container_t *cnt) // a scroll bar? Maybe add that information inside the // container structure - cnt_draw: // push the appropriate rectangles to the drawing stack + ug_rect_t draw_rect; + cnt_draw: + // push outline - push_rect_command(ctx, &cnt->rect_abs, s->cnt.border.color); - // push titlebar - ug_rect_t titlebar = { - .x = (cnt->rect_abs.x + s->cnt.border.l.size), - .y = (cnt->rect_abs.y + s->cnt.border.t.size), - .w = (cnt->rect_abs.w - s->cnt.border.r.size - s->cnt.border.l.size), - .h = s->cnt.titlebar.height.size, - }; - push_rect_command(ctx, &titlebar, s->cnt.titlebar.bg_color); + draw_rect = cnt->rca; + push_rect_command(ctx, &draw_rect, s->cnt.border.color); + + // titlebar + if (cnt->flags & UG_CNT_MOVABLE) { + draw_rect.x += bl; + draw_rect.y += bt; + draw_rect.w -= bl + br; + draw_rect.h = hh; + push_rect_command(ctx, &draw_rect, s->cnt.titlebar.bg_color); + } + // push main body - ug_rect_t body = { - .x = (cnt->rect_abs.x + s->cnt.border.l.size), - .y = (cnt->rect_abs.y + s->cnt.border.t.size), - .w = (cnt->rect_abs.w - s->cnt.border.l.size - s->cnt.border.r.size), - .h = (cnt->rect_abs.h - s->cnt.border.t.size - s->cnt.border.b.size), - }; + draw_rect = cnt->rca; + draw_rect.x += bl; + draw_rect.y += bt; + draw_rect.w -= bl + br; + draw_rect.h -= bt + bb; if (cnt->flags & UG_CNT_MOVABLE) { - body.y += s->cnt.titlebar.height.size + s->cnt.border.t.size; - body.h -= s->cnt.titlebar.height.size + s->cnt.border.t.size; + draw_rect.y += bt + hh; + draw_rect.h -= bt + hh; } - push_rect_command(ctx, &body, s->cnt.bg_color); + push_rect_command(ctx, &draw_rect, s->cnt.bg_color); // TODO: push other rects } @@ -533,7 +523,7 @@ int ug_frame_begin(ug_ctx_t *ctx) ug_vec2_t v = ctx->mouse.pos; // printf("mouse: x=%d, y=%d\n", ctx->mouse.pos.x, ctx->mouse.pos.x); for (int i = 0; i < ctx->cnt_stack.idx; i++) { - ug_rect_t r = ctx->cnt_stack.items[i].rect_abs; + ug_rect_t r = ctx->cnt_stack.items[i].rca; if (INTERSECTS(v, r)) { ctx->hover.cnt = ctx->cnt_stack.items[i].id; // printf("intersects! %.8x\n", ctx->hover.cnt); @@ -561,6 +551,12 @@ int ug_frame_end(ug_ctx_t *ctx) ctx->hover.cnt = 0; ctx->hover.elem = 0; + ctx->last_ppi = ctx->ppi; + ctx->last_ppm = ctx->ppm; + ctx->last_ppd = ctx->ppd; + + ctx->frame++; + return 0; } diff --git a/ugui.h b/ugui.h index 1ba2eab..71c3381 100644 --- a/ugui.h +++ b/ugui.h @@ -35,7 +35,9 @@ typedef enum { typedef struct { ug_id_t id; ug_unit_t unit; - ug_rect_t rect, rect_abs; + ug_rect_t rect; + // absolute position rect + ug_rect_t rca; ug_vec2_t max_size; unsigned int flags; } ug_container_t; @@ -134,6 +136,7 @@ typedef struct { // ppm: pixels per millimeter // ppd: pixels per dot float ppi, ppm, ppd; + float last_ppi, last_ppm, last_ppd; // containers need to know how big the "main container" is so that all // the relative positioning work ug_vec2_t size;