From 3875e6ab5744f881cc920cd4affc3a57135f10b5 Mon Sep 17 00:00:00 2001 From: Emil Kosz Date: Sun, 15 Jun 2025 21:41:52 +0200 Subject: [PATCH] Progress bar widget --- game/res/shaders/uiwidget.frag | 42 ++++++++++++++++++++++++---------- game/src/ui/uiman.c | 20 ++-------------- game/src/ui/widget_core.c | 13 +++++++++++ game/src/ui/widget_core.h | 11 ++++++++- game/src/ui/widget_render.c | 20 ++++++++++++++++ game/src/ui/widget_render.h | 1 + game/src/ui/widget_style.h | 1 + 7 files changed, 77 insertions(+), 31 deletions(-) diff --git a/game/res/shaders/uiwidget.frag b/game/res/shaders/uiwidget.frag index 5a8fa75..21be93b 100644 --- a/game/res/shaders/uiwidget.frag +++ b/game/res/shaders/uiwidget.frag @@ -5,18 +5,20 @@ precision mediump float; uniform bool has_background_image; uniform bool has_icon; uniform bool has_scrollbar; +uniform bool has_progress; uniform vec2 widget_size; uniform float border_width; + uniform vec4 border_color; - uniform vec4 background_color; - uniform vec4 icon_color; +uniform vec4 progress_color; uniform vec2 scrollbar_position; uniform vec2 scrollbar_size; +uniform vec2 progress_size; uniform sampler2D background_image; uniform sampler2D icons; @@ -41,18 +43,34 @@ void main () return; } - if (has_scrollbar) { - bool in_scrollbar = - f_uv.x >= scrollbar_position.x && - f_uv.x <= (scrollbar_position.x + scrollbar_size.x) && - f_uv.y >= scrollbar_position.y && - f_uv.y <= (scrollbar_position.y + scrollbar_size.y); + if (has_scrollbar) + { + bool in_scrollbar = + f_uv.x >= scrollbar_position.x && + f_uv.x <= (scrollbar_position.x + scrollbar_size.x) && + f_uv.y >= scrollbar_position.y && + f_uv.y <= (scrollbar_position.y + scrollbar_size.y); - if (in_scrollbar) { - gl_FragColor = vec4 (1, 1, 1, 1); - return; + if (in_scrollbar) + { + gl_FragColor = vec4 (1, 1, 1, 1); + return; + } } - } + + if (has_progress) + { + bool in_progress = + f_uv.x <= progress_size.x && + f_uv.y >= (1.0 - progress_size.y); + + if (in_progress) + { + gl_FragColor = vec4 (1.0, 1.0, 1.0, 1.0); + return; + } + } + if (has_icon) { diff --git a/game/src/ui/uiman.c b/game/src/ui/uiman.c index 295635f..894f01f 100644 --- a/game/src/ui/uiman.c +++ b/game/src/ui/uiman.c @@ -28,7 +28,7 @@ uiman_init () debug_menu->style->layout_padding = 8; debug_menu->style->background_image = RESTEX ("terrain4"); VEC2_SETI (debug_menu->position, 32, 32); - VEC2_SETI (debug_menu->size, 350, 170); + VEC2_SETI (debug_menu->size, 350, 200); Widget_add_child (ui_root, debug_menu); Widget_add_child_weighed (debug_menu, Widget_label_make_float ("Frame time: %.3f", &delta_time, TEXT_ALIGN_LEFT), 1); @@ -48,23 +48,7 @@ uiman_init () Widget_add_child_weighed (chkboxes, Widget_composite_checkbox_make ("Flight", "flight_enabled"), 1); Widget_add_child_weighed (debug_menu, chkboxes, 1); - Widget *window2 = Widget_container_new (TRUE); - window2->style->layout_padding = 8; - window2->style->background_image = RESTEX ("terrain3"); - VEC2_SETI (window2->position, 400, 32); - VEC2_SETI (window2->size, 350, 170); - - Widget *scrollable = Widget_scrollable_new (); - - Widget *image = Widget_plain_new (); - image->style->background_image = RESTEX ("terrain2"); - VEC2_SETI (image->size, 400, 400); - Widget_add_child (scrollable, image); - - Widget_add_child_weighed (window2, scrollable, 0.95); - Widget_add_child_weighed (window2, Widget_scrollbar_new (scrollable, FALSE), 0.05); - - Widget_add_child (ui_root, window2); + Widget_add_child_weighed (debug_menu, Widget_progress_new (TRUE, 0.0, 0.1, &delta_time), 1); } void diff --git a/game/src/ui/widget_core.c b/game/src/ui/widget_core.c index f628454..f62d427 100644 --- a/game/src/ui/widget_core.c +++ b/game/src/ui/widget_core.c @@ -17,6 +17,7 @@ WidgetStyle DEFAULT_STYLE = .text_color = { 1.0, 1.0, 1.0, 1.0 }, .icon_color = { 1.0, 1.0, 1.0, 1.0 }, .border_color = { 1.0, 1.0, 1.0, 1.0 }, + .progress_color = { 1.0, 1.0, 1.0, 1.0 }, .border_width = 0, .layout_padding = 0, @@ -90,6 +91,18 @@ Widget_scrollbar_new (Widget *target, gboolean horizontal) return e; } +Widget * +Widget_progress_new (gboolean horizontal, float min, float max, float *ptr) +{ + Widget *e = ui_el_new_internal (WIDGET_SCROLLBAR); + e->do_render = Widget_render_progress; + e->progress.horizontal = horizontal; + e->progress.min = min; + e->progress.max = max; + e->progress.ptr = ptr; + return e; +} + void Widget_add_child (Widget *parent, Widget *child) { diff --git a/game/src/ui/widget_core.h b/game/src/ui/widget_core.h index 96cd1e4..79be4b0 100644 --- a/game/src/ui/widget_core.h +++ b/game/src/ui/widget_core.h @@ -24,7 +24,8 @@ typedef enum WidgetKind WIDGET_CONTAINER, WIDGET_LABEL, WIDGET_SCROLLABLE, - WIDGET_SCROLLBAR + WIDGET_SCROLLBAR, + WIDGET_PROGRESS, } WidgetKind; typedef enum WidgetIcon @@ -90,6 +91,12 @@ typedef struct ScrollbarWidget float drag_offset; } ScrollbarWidget; +typedef struct ProgressWidget +{ + gboolean horizontal; + float min, max, *ptr; +} ProgressWidget; + typedef struct Widget { struct Widget *parent; @@ -101,6 +108,7 @@ typedef struct Widget LabelWidget label; ScrollableWidget scrollable; ScrollbarWidget scrollbar; + ProgressWidget progress; }; gboolean visible; @@ -130,6 +138,7 @@ Widget *Widget_container_new (gboolean horizontal); Widget *Widget_label_new (const char *text, TextAlignment alignment); Widget *Widget_scrollable_new (); Widget *Widget_scrollbar_new (Widget *target, gboolean horizontal); +Widget *Widget_progress_new (gboolean horizontal, float min, float max, float *ptr); void Widget_add_child (Widget *parent, Widget *child); void Widget_add_child_weighed (Widget *parent, Widget *child, diff --git a/game/src/ui/widget_render.c b/game/src/ui/widget_render.c index d61069f..23b287e 100644 --- a/game/src/ui/widget_render.c +++ b/game/src/ui/widget_render.c @@ -129,6 +129,7 @@ Widget_render_label (Widget *self, mat4 projection, int window_height) void Widget_render_scrollbar (Widget *self, mat4 projection, int window_height) { + program_use (RESPRG ("uiwidget")); program_set_int (RESPRG ("uiwidget"), "has_scrollbar", TRUE); /* Calculate the scrollbar size. */ unsigned int idx = self->scrollbar.horizontal ? 0 : 1; @@ -152,3 +153,22 @@ Widget_render_scrollbar (Widget *self, mat4 projection, int window_height) Widget_render_base (self, projection, window_height); program_set_int (RESPRG ("uiwidget"), "has_scrollbar", FALSE); } + +void +Widget_render_progress (Widget *self, mat4 projection, int window_height) +{ + program_use (RESPRG ("uiwidget")); + program_set_int (RESPRG ("uiwidget"), "has_progress", TRUE); + + float bar_size = (*self->progress.ptr - self->progress.min) / (self->progress.max - self->progress.min); + bar_size = glm_clamp (bar_size, 0.0, 1.0); + + program_set_vec4 (RESPRG ("uiwidget"), "progress_color", self->style->progress_color); + + program_set_vec2 (RESPRG ("uiwidget"), "progress_size", self->progress.horizontal + ? (vec2) { bar_size, 1.0f } + : (vec2) { 1.0f, bar_size }); + + Widget_render_base (self, projection, window_height); + program_set_int (RESPRG ("uiwidget"), "has_progress", FALSE); +} diff --git a/game/src/ui/widget_render.h b/game/src/ui/widget_render.h index 8348bf7..3a44dad 100644 --- a/game/src/ui/widget_render.h +++ b/game/src/ui/widget_render.h @@ -10,3 +10,4 @@ void ui_widget_mesh_init (); void Widget_render_base (Widget *self, mat4 projection, int window_height); void Widget_render_label (Widget *self, mat4 projection, int window_height); void Widget_render_scrollbar (Widget *self, mat4 projection, int window_height); +void Widget_render_progress (Widget *self, mat4 projection, int window_height); diff --git a/game/src/ui/widget_style.h b/game/src/ui/widget_style.h index 84ac3de..9022f53 100644 --- a/game/src/ui/widget_style.h +++ b/game/src/ui/widget_style.h @@ -9,6 +9,7 @@ typedef struct WidgetStyle vec4 text_color; vec4 icon_color; vec4 border_color; + vec4 progress_color; float border_width; /* The two below apply only to container widgets. */