From c2861def8f13c647bdd5c970ef7568d15821e0e2 Mon Sep 17 00:00:00 2001 From: iamcheeseman Date: Thu, 21 May 2026 20:52:19 -0400 Subject: clip all ui elements --- teensy/teensy.h | 3 ++ teensy/teensy_math.c | 19 +++++++++++++ teensy/teensy_renderer.c | 4 +-- teensy/teensy_ui.c | 74 ++++++++++++++++++++---------------------------- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/teensy/teensy.h b/teensy/teensy.h index e5954fc..80f9a71 100644 --- a/teensy/teensy.h +++ b/teensy/teensy.h @@ -22,6 +22,7 @@ #define ty_max(a, b) ((a) > (b) ? (a) : (b)) #define ty_min(a, b) ((a) < (b) ? (a) : (b)) +#define ty_clamp(a, mi, ma) (ty_max(ty_min(a, ma), mi)) #define TY_CLIP_NONE (ty_recti(0, 0, -1, -1)) @@ -155,6 +156,8 @@ bool ty_point_in_rect(ty_Vec2 point, ty_Rect rect); ty_Recti ty_recti_shrink(ty_Recti rect, int p); // Grows a rect by `p`. ty_Recti ty_recti_grow(ty_Recti rect, int p); +// Clamps a rect's bounds to be entirely within another. +ty_Recti ty_recti_clamp(ty_Recti rect, ty_Recti minmax); // Creates an image using the relevant data (formatted in RGB8). You may free // the passed data after this call as it is copied. diff --git a/teensy/teensy_math.c b/teensy/teensy_math.c index 5da800c..9247bd0 100644 --- a/teensy/teensy_math.c +++ b/teensy/teensy_math.c @@ -36,3 +36,22 @@ ty_Recti ty_recti_grow(ty_Recti rect, int p) rect.h += p * 2; return rect; } + +ty_Recti ty_recti_clamp(ty_Recti rect, ty_Recti minmax) +{ + ty_Vec2i start = ty_recti_start(rect); + ty_Vec2i end = ty_recti_end(rect); + + ty_Vec2i min = ty_recti_start(minmax); + ty_Vec2i max = ty_recti_end(minmax); + + start.x = ty_clamp(start.x, min.x, max.x); + start.y = ty_clamp(start.y, min.y, max.y); + end.x = ty_clamp(end.x, min.x, max.x); + end.y = ty_clamp(end.y, min.y, max.y); + + return ty_recti( + start.x, start.y, + end.x - start.x, end.y - start.y + ); +} diff --git a/teensy/teensy_renderer.c b/teensy/teensy_renderer.c index 5f6fced..564718a 100644 --- a/teensy/teensy_renderer.c +++ b/teensy/teensy_renderer.c @@ -45,8 +45,8 @@ void image_bounds_check(ty_Image img, ty_Vec2i pos) static ty_Vec2i clamp_point(ty_Vec2i p, ty_Recti rect) { - p.x = fmin(fmax(p.x, rect.x), rect.x + rect.w); - p.y = fmin(fmax(p.y, rect.y), rect.y + rect.h); + p.x = ty_clamp(p.x, rect.x, rect.x + rect.w); + p.y = ty_clamp(p.y, rect.y, rect.y + rect.h); return p; } diff --git a/teensy/teensy_ui.c b/teensy/teensy_ui.c index 27af0cf..32e4ca5 100644 --- a/teensy/teensy_ui.c +++ b/teensy/teensy_ui.c @@ -21,7 +21,7 @@ enum { CMD_RECT, CMD_TEXT, - CMD_TARGET, + CMD_CLIP, CMD_IMAGE, }; typedef uint8_t Cmd_Kind; @@ -47,7 +47,6 @@ typedef struct { typedef struct { const char *title; ty_Recti rect; - ty_Image content; uint32_t flags; Layout layout_stack[MAX_LAYOUTS]; @@ -123,19 +122,25 @@ void image_cmd(ty_Image img, ty_Recti rect) } static -void target_cmd(ty_Image target) +void clip_cmd(ty_Recti rect) { Cmd cmd = {}; - cmd.kind = CMD_TARGET; - cmd.img = target; + cmd.kind = CMD_CLIP; + if (rect.w < 0 || rect.h < 0) + rect = window()->rect; // This is a full screen clip + + cmd.rect = ty_recti_clamp(rect, window()->rect); ty_list_append(uictx.cmds, cmd); } static void draw_frame(ty_Recti rect, ty_Color bg_col) { + clip_cmd(TY_CLIP_NONE); rect_cmd(rect, uictx.style.frame); - rect_cmd(ty_recti_shrink(rect, uictx.style.frame_size), bg_col); + ty_Recti content_rect = ty_recti_shrink(rect, uictx.style.frame_size); + rect_cmd(content_rect, bg_col); + clip_cmd(content_rect); } static @@ -186,6 +191,9 @@ ty_Recti next_rect(int height) y += outer->total_height; } + x += window()->rect.x; + y += window()->rect.y; + advance_layout(); return ty_recti(x, y, width, height); @@ -201,19 +209,10 @@ ty_Vec2i mouse_delta(void) ); } -static -ty_Vec2i mouse_pos(void) -{ - ty_Vec2i mouse_pos = ty_mouse_pos(); - mouse_pos.x -= window()->rect.x; - mouse_pos.y -= window()->rect.y; - return mouse_pos; -} - static bool is_hovered(ty_Recti rect) { - return ty_pointi_in_recti(mouse_pos(), rect); + return ty_pointi_in_recti(ty_mouse_pos(), rect); } static @@ -223,7 +222,6 @@ Window create_window(const char *title, ty_Recti rect, uint32_t flags) win.title = title; win.rect = rect; win.flags = flags; - win.content = ty_create_image(rect.w, rect.h, NULL); return win; } @@ -255,11 +253,6 @@ void tyui_init(const ty_Font *font) void tyui_deinit(void) { ty_list_free(uictx.cmds); - - ty_free_image(uictx.root.content); - for (int i = 0; i < uictx.window_count; i++) { - ty_free_image(uictx.windows[i].content); - } } void tyui_push_layout(const float *column_widths) @@ -327,12 +320,8 @@ void tyui_draw(void) case CMD_IMAGE: ty_draw_image(cmd.img, ty_recti_start(cmd.rect)); break; - case CMD_TARGET: - // Add a draw rect property to the renderer, which allows me to - // define a rect that anything drawn will be clipped by. - - ty_draw_set_target(cmd.img.data ? &cmd.img : NULL); - if (cmd.img.data != NULL) ty_draw_clear(TY_COLOR_MAGENTA); + case CMD_CLIP: + ty_draw_set_clip(cmd.rect); break; } } @@ -397,12 +386,6 @@ bool tyui_begin_window_ex( if (ty_button_down(TY_BTN_DB_LMB) && hovering_resizer) { win->rect.w += md.x; win->rect.h += md.y; - ty_free_image(win->content); - win->content = ty_create_image( - win->rect.w, - win->rect.h + title_rect.h, - NULL - ); } // Grabbing title bar? @@ -418,20 +401,26 @@ bool tyui_begin_window_ex( title_rect.h = title_bar_height(); } - target_cmd(win->content); + clip_cmd(TY_CLIP_NONE); - title_rect = ty_recti(0, 0, win->rect.w, title_bar_height()); rect_cmd(title_rect, uictx.style.win_title); text_cmd(win->title, title_rect, TYUI_ALIGN_LEFT); ty_Recti body_rect = win->rect; - body_rect.x = 0; - body_rect.y = title_bar_height(); + body_rect.y += title_bar_height(); rect_cmd(body_rect, uictx.style.win_bg); if (hovering_resizer) { - rect_cmd(ty_recti(win->rect.w-1, title_bar_height(), 1, win->rect.h), uictx.style.win_title); - rect_cmd(ty_recti(0, win->rect.h-1+title_bar_height(), win->rect.w, 1), uictx.style.win_title); + ty_Recti right_bar = ty_recti( + win->rect.x + win->rect.w - 1, 0, + 1, win->rect.y + win->rect.h + ); + rect_cmd(right_bar, uictx.style.win_title); + ty_Recti bot_bar = ty_recti( + 0, win->rect.y + win->rect.h - 1, + win->rect.x + win->rect.w, 1 + ); + rect_cmd(bot_bar, uictx.style.win_title); } tyui_push_layout((float[]){-1, 0}); @@ -448,9 +437,7 @@ void tyui_end_window(void) return; } - target_cmd((ty_Image){}); - - image_cmd(window()->content, window()->rect); + clip_cmd(TY_CLIP_NONE); uictx.active = &uictx.root; } @@ -464,6 +451,7 @@ void tyui_text_ex(tyui_Align align, const char *fmt, ...) ty_Recti rect = next_rect(TEXT_HEIGHT); + clip_cmd(rect); text_cmd(text, rect, align); } -- cgit v1.3-2-g0d8e