Scrollbar improvements

This commit is contained in:
2025-06-15 08:50:09 +02:00
parent 3398eb1426
commit c276fa7bd5
8 changed files with 123 additions and 52 deletions
+22 -4
View File
@@ -11,6 +11,10 @@ uniform vec2 widget_size;
uniform bool has_icon;
uniform bool has_scrollbar;
uniform vec2 scrollbar_position;
uniform vec2 scrollbar_size;
uniform sampler2D background_image;
uniform sampler2D icons;
@@ -28,9 +32,23 @@ void main ()
vec4 bgc = has_background_image ? texture2D (background_image, f_uv) : background_color;
vec4 base_color = mix (bgc, border_color, is_border);
if (is_border > 0.5) {
gl_FragColor = base_color;
return;
if (is_border > 0.5)
{
gl_FragColor = base_color;
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 (in_scrollbar) {
gl_FragColor = vec4 (1, 1, 1, 1);
return;
}
}
if (has_icon)
@@ -39,6 +57,6 @@ void main ()
gl_FragColor = mix (base_color, fg, fg.a);
base_color = mix (base_color, fg, fg.a);
}
gl_FragColor = base_color;
}
+1 -1
View File
@@ -15,7 +15,7 @@ void
main ()
{
float tex_w = 40.0;
float tex_h = 40.0;
float tex_h = 80.0;
float icon_w = 20.0;
float icon_h = 20.0;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 B

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.
+16 -16
View File
@@ -146,23 +146,23 @@ resources_init ()
#define RAT resources_add_texture
#define RLT resources_load_texture
RAP ("default", RLP ("res/shaders/default.vert", "res/shaders/default.frag"));
RAP ("chunk", RLP ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
RAP ("clouds", RLP ("res/shaders/clouds.vert", "res/shaders/clouds.frag"));
RAP ("uiwidget", RLP ("res/shaders/uiwidget.vert", "res/shaders/uiwidget.frag"));
RAP ("uitext", RLP ("res/shaders/uitext.vert", "res/shaders/uitext.frag"));
RAP ("default", RLP ("res/shaders/default.vert", "res/shaders/default.frag"));
RAP ("chunk", RLP ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
RAP ("clouds", RLP ("res/shaders/clouds.vert", "res/shaders/clouds.frag"));
RAP ("uiwidget", RLP ("res/shaders/uiwidget.vert", "res/shaders/uiwidget.frag"));
RAP ("uitext", RLP ("res/shaders/uitext.vert", "res/shaders/uitext.frag"));
RAT ("terrain0", RLT ("res/textures/dirt.png"));
RAT ("terrain1", RLT ("res/textures/drygrass.png"));
RAT ("terrain2", RLT ("res/textures/grass.png"));
RAT ("terrain3", RLT ("res/textures/rock_cement.png"));
RAT ("terrain4", RLT ("res/textures/asphalt_gravel.png"));
RAT ("tree0", RLT ("res/textures/tree.png"));
RAT ("grass0", RLT ("res/textures/grass0.png"));
RAT ("clouds", RLT ("res/textures/clouds.png"));
RAT ("font0", RLT ("res/textures/font_9x20.png"));
RAT ("icons", RLT ("res/textures/icons.png"));
RAT ("terrain0", RLT ("res/textures/dirt.png"));
RAT ("terrain1", RLT ("res/textures/drygrass.png"));
RAT ("terrain2", RLT ("res/textures/grass.png"));
RAT ("terrain3", RLT ("res/textures/rock_cement.png"));
RAT ("terrain4", RLT ("res/textures/asphalt_gravel.png"));
RAT ("tree0", RLT ("res/textures/tree.png"));
RAT ("grass0", RLT ("res/textures/grass0.png"));
RAT ("clouds", RLT ("res/textures/clouds.png"));
RAT ("font0", RLT ("res/textures/font_9x20.png"));
RAT ("icons", RLT ("res/textures/icons.png"));
#undef RAP
#undef RLP
+3 -2
View File
@@ -49,8 +49,9 @@ uiman_init ()
Widget_add_child_weighed (chkboxes, Widget_composite_checkbox_make ("Flight", "flight_enabled"), 1);
Widget_add_child_weighed (debug_menu, chkboxes, 1);
Widget *content = Widget_label_new ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", TEXT_ALIGN_LEFT);
VEC2_SETI (content->size, 3000, 500);
Widget *content = Widget_plain_new ();
Widget_set_background_image (content, RESTEX ("terrain1"));
VEC2_SETI (content->size, 400, 600);
Widget *scrollable_window = Widget_composite_scrollable_make (content);
Widget_set_background_image (scrollable_window, RESTEX ("terrain4"));
+59 -19
View File
@@ -45,7 +45,16 @@ Widget *
Widget_scrollable_new ()
{
Widget *e = ui_el_new_internal (WIDGET_SCROLLABLE);
e->scrollable.scroll_amount = 5.0;
e->scrollable.scroll_amount = 10.0;
return e;
}
Widget *
Widget_scrollbar_new (Widget *scrollable, gboolean horizontal)
{
Widget *e = ui_el_new_internal (WIDGET_SCROLLBAR);
e->scrollbar.scrollable = scrollable;
e->scrollbar.horizontal = horizontal;
return e;
}
@@ -252,17 +261,20 @@ Widget_scrollable_layout (Widget *parent)
WIDGET_FOREACH_CHILD (parent, i, child)
{
child->position[0] = parent->position[0] - parent->scrollable.scroll_position[0];
child->position[1] = parent->position[1] - parent->scrollable.scroll_position[1];
float logical_x = 0.0f;
float logical_y = 0.0f;
child->position[0] = parent->position[0] + logical_x - parent->scrollable.scroll_position[0];
child->position[1] = parent->position[1] + logical_y - parent->scrollable.scroll_position[1];
if (child->layout_weight > 0.0)
{
child->size[0] = child->layout_weight * parent->size[0];
child->size[1] = child->layout_weight * parent->size[1];
}
float right = child->position[0] + child->size[0];
float bottom = child->position[1] + child->size[1];
float right = logical_x + child->size[0];
float bottom = logical_y + child->size[1];
if (right > content_size[0])
{
@@ -415,6 +427,33 @@ Widget_render (Widget *widget, mat4 projection, int window_height)
program_set_int (RESPRG ("uiwidget"), "has_icon", widget->has_icon);
program_set_float (RESPRG ("uiwidget"), "icon_index", widget->icon);
texture_use (RESTEX ("icons"), 1);
if (widget->kind == WIDGET_SCROLLBAR)
{
program_set_int (RESPRG ("uiwidget"), "has_scrollbar", TRUE);
/* Calculate the scrollbar size. */
unsigned int idx = widget->scrollbar.horizontal ? 0 : 1;
Widget *scr = widget->scrollbar.scrollable;
float content_size = scr->scrollable.content_size[idx];
float scroll_pos = scr->scrollable.scroll_position[idx];
float view_size = scr->size[idx];
float thumb_size_norm = view_size / content_size;
float thumb_pos_norm = scroll_pos / content_size;
program_set_vec2 (RESPRG ("uiwidget"), "scrollbar_position", widget->scrollbar.horizontal
? (vec2) { thumb_pos_norm, 0.0f }
: (vec2) { 0.0f, thumb_pos_norm });
program_set_vec2 (RESPRG ("uiwidget"), "scrollbar_size", widget->scrollbar.horizontal
? (vec2) { thumb_size_norm, 1.0f }
: (vec2) { 1.0f, thumb_size_norm });
}
else
{
program_set_int (RESPRG ("uiwidget"), "has_scrollbar", FALSE);
}
mat3 model;
glm_translate2d_make (model, widget->position);
@@ -445,10 +484,10 @@ Widget_render (Widget *widget, mat4 projection, int window_height)
vec2 clipped_aabb[2];
glm_aabb2d_crop (widget_aabb, parent_aabb, clipped_aabb);
int x = floor (clipped_aabb[0][0]);
int y = floor (window_height - clipped_aabb[1][1]);
int w = ceil (clipped_aabb[1][0] - clipped_aabb[0][0]);
int h = ceil (clipped_aabb[1][1] - clipped_aabb[0][1]);
int x = roundf (clipped_aabb[0][0]);
int y = roundf (window_height - clipped_aabb[1][1]);
int w = roundf (clipped_aabb[1][0] - clipped_aabb[0][0]);
int h = roundf (clipped_aabb[1][1] - clipped_aabb[0][1]);
/* X, Y is the lower left corner of the box. */
glScissor (x, y, w, h);
@@ -461,9 +500,10 @@ Widget_render (Widget *widget, mat4 projection, int window_height)
}
Widget *child;
WIDGET_FOREACH_CHILD (widget, i, child) {
Widget_render (child, projection, window_height);
}
WIDGET_FOREACH_CHILD (widget, i, child)
{
Widget_render (child, projection, window_height);
}
}
/* --------- */
@@ -630,11 +670,11 @@ Widget_composite_scrollable_make (Widget *content)
Widget *scroll_up = Widget_plain_new ();
Widget *scroll_down = Widget_plain_new ();
Widget_set_icon (scroll_up, ICON_SPINNER_LEFT);
Widget_set_icon (scroll_up, ICON_ARROW_UP);
Widget_set_on_left_click (scroll_up, uicb_scrollable_scroll_up, scrollable);
scroll_up->aspect_ratio = 1.0;
Widget_set_icon (scroll_down, ICON_SPINNER_RIGHT);
Widget_set_icon (scroll_down, ICON_ARROW_DOWN);
Widget_set_on_left_click (scroll_down, uicb_scrollable_scroll_down, scrollable);
scroll_down->aspect_ratio = 1.0;
@@ -642,7 +682,7 @@ Widget_composite_scrollable_make (Widget *content)
Widget *scrollbar_vertical = Widget_container_new (FALSE, 0, 0);
Widget_add_child_weighed (scrollbar_vertical, scroll_up, 1);
Widget_add_child_weighed (scrollbar_vertical, Widget_plain_new (), 1);
Widget_add_child_weighed (scrollbar_vertical, Widget_scrollbar_new (scrollable, FALSE), 1);
Widget_add_child_weighed (scrollbar_vertical, scroll_down, 1);
Widget_add_child_weighed (cont_horiz, scrollable, 0.93);
@@ -653,11 +693,11 @@ Widget_composite_scrollable_make (Widget *content)
Widget *scroll_left = Widget_plain_new ();
Widget *scroll_right = Widget_plain_new ();
Widget_set_icon (scroll_left, ICON_SPINNER_LEFT);
Widget_set_icon (scroll_left, ICON_ARROW_LEFT);
Widget_set_on_left_click (scroll_left, uicb_scrollable_scroll_left, scrollable);
scroll_left->aspect_ratio = 1.0;
Widget_set_icon (scroll_right, ICON_SPINNER_RIGHT);
Widget_set_icon (scroll_right, ICON_ARROW_RIGHT);
Widget_set_on_left_click (scroll_right, uicb_scrollable_scroll_right, scrollable);
scroll_right->aspect_ratio = 1.0;
@@ -667,7 +707,7 @@ Widget_composite_scrollable_make (Widget *content)
padding->aspect_ratio = 1.0;
Widget_add_child_weighed (scrollbar_horizontal, scroll_left, 1);
Widget_add_child_weighed (scrollbar_horizontal, Widget_plain_new (), 1);
Widget_add_child_weighed (scrollbar_horizontal, Widget_scrollbar_new (scrollable, TRUE), 1);
Widget_add_child_weighed (scrollbar_horizontal, scroll_right, 1);
Widget_add_child_weighed (scrollbar_horizontal, padding, 1);
+22 -10
View File
@@ -13,16 +13,27 @@
for (unsigned int i = 0; i < widget->children->len && \
((child = g_array_index(widget->children, Widget *, i)), 1); ++i)
typedef enum WidgetKind
{
WIDGET_PLAIN,
WIDGET_CONTAINER,
WIDGET_LABEL,
WIDGET_SCROLLABLE
WIDGET_SCROLLABLE,
WIDGET_SCROLLBAR
} WidgetKind;
typedef enum WidgetIcon
{
ICON_CHECKBOX_UNCHECKED = 0,
ICON_CHECKBOX_CHECKED,
ICON_SPINNER_LEFT,
ICON_SPINNER_RIGHT,
ICON_ARROW_LEFT,
ICON_ARROW_RIGHT,
ICON_ARROW_UP,
ICON_ARROW_DOWN
} WidgetIcon;
typedef struct ContainerWidget
{
gboolean horizontal;
@@ -51,13 +62,12 @@ typedef struct ScrollableWidget
vec2 content_size;
} ScrollableWidget;
typedef enum WidgetIcon
{
ICON_CHECKBOX_UNCHECKED = 0,
ICON_CHECKBOX_CHECKED,
ICON_SPINNER_LEFT,
ICON_SPINNER_RIGHT
} WidgetIcon;
typedef struct ScrollbarWidget
{
struct Widget *scrollable;
gboolean horizontal;
float bar_size;
} ScrollbarWidget;
typedef struct Widget
{
@@ -69,6 +79,7 @@ typedef struct Widget
ContainerWidget container;
LabelWidget label;
ScrollableWidget scrollable;
ScrollbarWidget scrollbar;
};
gboolean visible;
@@ -104,6 +115,7 @@ Widget *Widget_plain_new ();
Widget *Widget_container_new (gboolean horizontal, float padding, float child_spacing);
Widget *Widget_label_new (const char *text, TextAlignment alignment);
Widget *Widget_scrollable_new ();
Widget *Widget_scrollbar_new (Widget *scrollable, gboolean horizontal);
void Widget_add_child (Widget *parent, Widget *child);
void Widget_add_child_weighed (Widget *parent, Widget *child,