Some UI stuff

This commit is contained in:
2025-06-12 20:46:46 +02:00
parent 438083503d
commit f0394fbb8d
15 changed files with 195 additions and 86 deletions
+2 -2
View File
@@ -2,7 +2,7 @@
precision mediump float;
uniform vec4 text_color;
uniform vec4 color;
uniform sampler2D texture;
varying vec2 f_uv;
@@ -10,5 +10,5 @@ varying vec2 f_uv;
void main ()
{
gl_FragColor = texture2D (texture, f_uv) * text_color;
gl_FragColor = texture2D (texture, f_uv) * color;
}
+2 -2
View File
@@ -11,10 +11,10 @@ varying vec2 f_uv;
void main ()
{
float tex_w = 160.0;
float tex_w = 144.0;
float tex_h = 320.0;
float char_w = 10.0;
float char_w = 9.0;
float char_h = 20.0;
float chars_per_row = tex_w / char_w;
+6 -4
View File
@@ -2,20 +2,22 @@
precision mediump float;
uniform sampler2D texture;
uniform sampler2D background_image;
uniform bool has_texture;
uniform vec4 background_color;
varying vec2 f_uv;
void main ()
{
vec4 tex_color = texture2D (texture, f_uv);
vec4 tex_color = texture2D (background_image, f_uv);
if (has_texture)
{
gl_FragColor = tex_color;
gl_FragColor = vec4 (background_color.xyz, 1.0) * tex_color;
}
else
{
gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0);
gl_FragColor = background_color;
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.
+2
View File
@@ -86,11 +86,13 @@ graphics_render ()
entman_render (view, planes);
/* We don't care about blending elsewhere for now. */
glEnable (GL_SCISSOR_TEST);
glEnable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
uiman_render ();
glEnable (GL_DEPTH_TEST);
glDisable (GL_BLEND);
glDisable (GL_SCISSOR_TEST);
SDL_GL_SwapWindow (sdl_window);
+3 -2
View File
@@ -161,8 +161,9 @@ resources_init ()
RAT ("grass0", RLT ("res/textures/grass0.png"));
RAT ("clouds", RLT ("res/textures/clouds.png"));
RAT ("font0", RLT ("res/textures/font.png"));
RAT ("font0", RLT ("res/textures/font_9x20.png"));
RAT ("icons", RLT ("res/textures/icons.png"));
#undef RAP
#undef RLP
#undef RAT
+67 -25
View File
@@ -14,6 +14,8 @@ extern vec3 camera_position;
static Widget *ui_root;
static mat4 projection;
static Widget *hovered_widget, *clicked_widget;
void
uiman_init ()
{
@@ -22,24 +24,26 @@ uiman_init ()
glm_ortho (0.0, (float) sdl_window_w, (float) sdl_window_h, 0.0, -1.0, 1.0, projection);
Widget *debug_menu = Widget_container_new (FALSE);
Widget_set_texture (debug_menu, RESTEX ("terrain4"));
Widget_set_background_color (debug_menu, 0, 0, 0, 0.7);
Widget_set_position (debug_menu, 32, 32);
Widget_set_size (debug_menu, 300, 150);
Widget_set_size (debug_menu, 350, 150);
Widget_add_child (ui_root, debug_menu);
Widget_add_child (debug_menu, Widget_label_make_float ("Frame time: %.3f", &delta_time, TEXT_ALIGN_LEFT));
Widget_add_child (debug_menu, Widget_label_make_int ("Render distance: %d", &render_distance, TEXT_ALIGN_LEFT));
Widget_add_child (debug_menu, Widget_label_make_int ("Chunks rendered: %d", &n_frame_chunks, TEXT_ALIGN_LEFT));
Widget_add_child (debug_menu, Widget_label_make_int ("Entities rendered: %d", &n_frame_ents, TEXT_ALIGN_LEFT));
Widget_add_child_weighed (debug_menu, Widget_label_make_float ("Frame time: %.3f", &delta_time, TEXT_ALIGN_LEFT), 1);
Widget_add_child_weighed (debug_menu, Widget_label_make_int ("Render distance: %d", &render_distance, TEXT_ALIGN_LEFT), 1);
Widget_add_child_weighed (debug_menu, Widget_label_make_int ("Chunks rendered: %d", &n_frame_chunks, TEXT_ALIGN_LEFT), 1);
Widget_add_child_weighed (debug_menu, Widget_label_make_int ("Entities rendered: %d", &n_frame_ents, TEXT_ALIGN_LEFT), 1);
Widget *poscont = Widget_container_new (TRUE);
Widget_add_child (poscont, Widget_label_make_float ("X: %.0f", &camera_position[0], TEXT_ALIGN_LEFT));
Widget_add_child (poscont, Widget_label_make_float ("Y: %.0f", &camera_position[1], TEXT_ALIGN_CENTER));
Widget_add_child (poscont, Widget_label_make_float ("Z: %.0f", &camera_position[2], TEXT_ALIGN_RIGHT));
Widget_add_child (debug_menu, poscont);
Widget_add_child (debug_menu, Widget_label_make_flag_switch_button ("Toggle wireframe", "wireframe_enabled"));
Widget_add_child (debug_menu, Widget_label_make_flag_switch_button ("Toggle flight", "flight_enabled"));
Widget_add_child_weighed (poscont, Widget_label_make_float ("X: %.1f", &camera_position[0], TEXT_ALIGN_LEFT), 1);
Widget_add_child_weighed (poscont, Widget_label_make_float ("Y: %.1f", &camera_position[1], TEXT_ALIGN_CENTER), 1);
Widget_add_child_weighed (poscont, Widget_label_make_float ("Z: %.1f", &camera_position[2], TEXT_ALIGN_RIGHT), 1);
Widget_add_child_weighed (debug_menu, poscont, 1);
Widget *butcont = Widget_container_new (TRUE);
Widget_add_child_weighed (butcont, Widget_label_make_flag_switch_button ("Toggle wireframe", "wireframe_enabled"), 1);
Widget_add_child_weighed (butcont, Widget_label_make_flag_switch_button ("Toggle flight", "flight_enabled"), 1);
Widget_add_child_weighed (debug_menu, butcont, 1);
}
void
@@ -51,7 +55,7 @@ uiman_tick ()
void
uiman_render ()
{
Widget_render (ui_root, projection);
Widget_render (ui_root, projection, sdl_window_h);
}
gboolean
@@ -90,8 +94,22 @@ uiman_cb_mouse_motion (SDL_Event *event, void *data)
{
UNUSED (data);
Widget *widget = Widget_find_xy (ui_root, (vec2) { event->motion.x, event->motion.y });
UNUSED (widget);
Widget *new_hover = Widget_find_xy (ui_root, (vec2) { event->motion.x, event->motion.y });
if (new_hover != hovered_widget)
{
if (hovered_widget)
{
hovered_widget->hovered = FALSE;
}
if (new_hover)
{
new_hover->hovered = TRUE;
}
hovered_widget = new_hover;
}
/* This callback always eats the event, because why would the game
need mouse motion if the UI has stolen the focus? */
@@ -101,9 +119,40 @@ uiman_cb_mouse_motion (SDL_Event *event, void *data)
gboolean
uiman_cb_button_down (SDL_Event *event, void *data)
{
UNUSED (event, data);
UNUSED (data);
Widget *new_clicked = Widget_find_xy (ui_root, (vec2) { event->motion.x, event->motion.y });
if (new_clicked != clicked_widget)
{
if (clicked_widget && (clicked_widget->on_left_click || clicked_widget->on_right_click))
{
clicked_widget->clicked = FALSE;
}
if (new_clicked && (new_clicked->on_left_click || new_clicked->on_right_click))
{
new_clicked->clicked = TRUE;
}
clicked_widget = new_clicked;
}
return TRUE;
}
gboolean
uiman_cb_button_up (SDL_Event *event, void *data)
{
UNUSED (data);
Widget *widget = Widget_find_xy (ui_root, (vec2) { event->motion.x, event->motion.y });
if (clicked_widget)
{
clicked_widget->clicked = FALSE;
clicked_widget = NULL;
}
if (widget)
{
@@ -119,14 +168,7 @@ uiman_cb_button_down (SDL_Event *event, void *data)
return TRUE;
}
}
return FALSE;
}
gboolean
uiman_cb_button_up (SDL_Event *event, void *data)
{
UNUSED (event, data);
return FALSE;
}
+95 -38
View File
@@ -1,10 +1,5 @@
#include "widget.h"
/* TODO: padding */
/* TODO: movable and resizable windows */
/* TODO: "spinner" UI element */
/* TODO: "checkbox" UI element */
static SimpleMesh quad;
static unsigned int last_program;
@@ -17,7 +12,7 @@ ui_el_new_internal (WidgetKind kind)
e->kind = kind;
e->visible = true;
e->children = g_array_new (false, false, sizeof (Widget *));
e->layout_weight = 1;
glm_vec4_zero (e->background_color);
return e;
}
@@ -42,7 +37,7 @@ Widget_label_new (const char *text, TextAlignment alignment)
Widget *e = ui_el_new_internal (WIDGET_LABEL);
e->label.text = g_string_new (text);
e->label.text_alignment = alignment;
glm_vec4_one (e->label.text_color);
glm_vec4_one (e->label.color);
return e;
}
@@ -62,8 +57,8 @@ Widget_add_child_weighed (Widget *parent, Widget *child, float layout_weight)
void
Widget_set_on_tick (Widget *widget,
void (*on_tick) (Widget *, void *),
void *userdata)
void (*on_tick) (Widget *, void *),
void *userdata)
{
widget->on_tick = on_tick;
widget->tick_data = userdata;
@@ -71,8 +66,8 @@ Widget_set_on_tick (Widget *widget,
void
Widget_set_on_left_click (Widget *widget,
void (*on_left_click) (Widget *, void *),
void *userdata)
void (*on_left_click) (Widget *, void *),
void *userdata)
{
widget->on_left_click = on_left_click;
widget->left_click_data = userdata;
@@ -91,10 +86,28 @@ Widget_set_size (Widget *widget, float x, float y)
}
void
Widget_set_texture (Widget *widget, unsigned int texture)
Widget_set_background_image (Widget *widget, unsigned int image)
{
widget->texture = texture;
widget->has_texture = TRUE;
widget->background_image = image;
widget->has_background_image = TRUE;
}
void
Widget_set_background_color (Widget *widget, float r, float g, float b, float a)
{
glm_vec4_copy ((vec4) { r, g, b, a }, widget->background_color);
}
void
Widget_set_hovered_bg_color (Widget *widget, float r, float g, float b, float a)
{
glm_vec4_copy ((vec4) { r, g, b, a }, widget->hovered_bg_color);
}
void
Widget_set_clicked_bg_color (Widget *widget, float r, float g, float b, float a)
{
glm_vec4_copy ((vec4) { r, g, b, a }, widget->clicked_bg_color);
}
void
@@ -209,7 +222,7 @@ Widget_label_render_text (Widget *widget, mat4 projection)
gunichar ch = g_utf8_get_char (p);
program_set_float (RESPRG ("uitext"), "character", ch);
program_set_vec4 (RESPRG ("uitext"), "text_color", widget->label.text_color);
program_set_vec4 (RESPRG ("uitext"), "color", widget->label.color);
mat3 model;
glm_translate2d_make (model, (vec2) { widget->position[0] + offset + char_width, widget->position[1] });
@@ -228,44 +241,69 @@ void
Widget_container_layout (Widget *parent, gboolean horizontal)
{
float total_weights = 0.0;
float total_fixed = 0.0;
for (unsigned int i = 0; i < parent->children->len; ++i)
{
Widget *child = g_array_index (parent->children, Widget *, i);
total_weights += child->layout_weight;
if (child->layout_weight == 0.0)
{
total_fixed += horizontal ? child->size[0] : child->size[1];
}
else
{
total_weights += child->layout_weight;
}
}
float weights_size = ((horizontal ? parent->size[0] : parent->size[1]) - total_fixed) / total_weights;
if (weights_size < 0)
{
g_warning ("Fixed size children exceed the size of the parent container.");
}
float offset = 0.0;
for (unsigned int i = 0; i < parent->children->len; ++i)
{
Widget *child = g_array_index (parent->children, Widget *, i);
if (horizontal)
if (child->layout_weight == 0.0)
{
float weights_size = parent->size[0] / total_weights;
child->size[0] = child->layout_weight * weights_size;
child->size[1] = parent->size[1];
child->position[0] = parent->position[0] + offset;
child->position[1] = parent->position[1];
offset += child->size[0];
if (horizontal)
{
Widget_set_position (child, parent->position[0] + offset, parent->position[1]);
child->size[1] = parent->size[1];
offset += child->size[0];
}
else
{
Widget_set_position (child, parent->position[0], parent->position[1] + offset);
child->size[0] = parent->size[0];
offset += child->size[1];
}
}
else
{
float weights_size = parent->size[1] / total_weights;
child->size[1] = child->layout_weight * weights_size;
child->size[0] = parent->size[0];
child->position[1] = parent->position[1] + offset;
child->position[0] = parent->position[0];
offset += child->size[1];
if (horizontal)
{
Widget_set_position (child, parent->position[0] + offset, parent->position[1]);
Widget_set_size (child, child->layout_weight * weights_size, parent->size[1]);
offset += child->size[0];
}
else
{
Widget_set_position (child, parent->position[0], parent->position[1] + offset);
Widget_set_size (child, parent->size[0], child->layout_weight * weights_size);
offset += child->size[1];
}
}
}
}
void
Widget_render (Widget *widget, mat4 projection)
Widget_render (Widget *widget, mat4 projection, int window_height)
{
last_program = 0;
@@ -284,15 +322,31 @@ Widget_render (Widget *widget, mat4 projection)
last_program = program_use (RESPRG ("uiwidget"));
}
program_set_int (RESPRG ("uiwidget"), "has_texture", widget->has_texture);
texture_use (widget->texture, 0); /* If it doesn't have a texture, it'll be 0 anyway. */
program_set_int (RESPRG ("uiwidget"), "has_background_image", widget->has_background_image);
texture_use (widget->background_image, 0); /* If it doesn't have a texture, it'll be 0 anyway. */
program_set_vec4 (RESPRG ("uiwidget"), "background_color", widget->background_color);
if (widget->clicked)
{
program_set_vec4 (RESPRG ("uiwidget"), "background_color", widget->clicked_bg_color);
}
else if (widget->hovered)
{
program_set_vec4 (RESPRG ("uiwidget"), "background_color", widget->hovered_bg_color);
}
mat3 model;
glm_translate2d_make (model, widget->position);
glm_scale2d (model, widget->size);
program_set_mat3 (RESPRG ("uiwidget"), "model", model);
program_set_mat4 (RESPRG ("uiwidget"), "projection", projection);
/* X, Y is the lower left corner of the box. */
glScissor (widget->position[0], window_height - widget->position[1]
- widget->size[1], widget->size[0], widget->size[1]);
SimpleMesh_render (&quad, FALSE);
if (widget->kind == WIDGET_CONTAINER)
@@ -308,7 +362,7 @@ Widget_render (Widget *widget, mat4 projection)
for (unsigned int i = 0; i < widget->children->len; ++i)
{
Widget *child = g_array_index (widget->children, Widget *, i);
Widget_render (child, projection);
Widget_render (child, projection, window_height);
}
}
@@ -373,6 +427,9 @@ Widget *
Widget_label_make_flag_switch_button (const char *text, char *flag)
{
Widget *w = Widget_label_new (text, TEXT_ALIGN_CENTER);
Widget_set_background_color (w, 1, 1, 1, 0.1);
Widget_set_hovered_bg_color (w, 1, 1, 1, 0.2);
Widget_set_clicked_bg_color (w, 1, 1, 1, 0.3);
Widget_set_on_left_click (w, uicb_switch_flag, flag);
return w;
}
+18 -13
View File
@@ -13,7 +13,8 @@ typedef enum WidgetKind
{
WIDGET_PLAIN,
WIDGET_CONTAINER,
WIDGET_LABEL
WIDGET_LABEL,
WIDGET_ICON
} WidgetKind;
typedef struct ContainerWidget
@@ -31,7 +32,7 @@ typedef enum TextAlignment
typedef struct LabelWidget
{
GString *text;
vec4 text_color;
vec4 color;
TextAlignment text_alignment;
} LabelWidget;
@@ -47,13 +48,18 @@ typedef struct Widget
};
gboolean visible;
gboolean hovered, clicked;
vec2 position;
vec2 size;
float layout_weight;
gboolean has_texture;
unsigned int texture;
vec4 background_color;
vec4 hovered_bg_color;
vec4 clicked_bg_color;
gboolean has_background_image;
unsigned int background_image;
void (*on_left_click) (struct Widget *, void *);
void *left_click_data;
@@ -71,16 +77,15 @@ void Widget_add_child (Widget *parent, Widget *child);
void Widget_add_child_weighed (Widget *parent, Widget *child,
float layout_weight);
void Widget_set_on_tick (Widget *widget,
void (*on_tick) (Widget *, void *),
void *userdata);
void Widget_set_on_left_click (Widget *widget,
void (*on_left_click) (Widget *, void *),
void *userdata);
void Widget_set_on_tick (Widget *widget, void (*on_tick) (Widget *, void *), void *userdata);
void Widget_set_on_left_click (Widget *widget, void (*on_left_click) (Widget *, void *), void *userdata);
void Widget_set_position (Widget *widget, float x, float y);
void Widget_set_size (Widget *widget, float x, float y);
void Widget_set_texture (Widget *widget, unsigned int texture);
void Widget_set_background_image (Widget *widget, unsigned int image);
void Widget_set_background_color (Widget *widget, float r, float g, float b, float a);
void Widget_set_hovered_bg_color (Widget *widget, float r, float g, float b, float a);
void Widget_set_clicked_bg_color (Widget *widget, float r, float g, float b, float a);
void Widget_label_set_text (Widget *widget, const char *text);
void Widget_label_printf (Widget *widget, const char *format, ...);
@@ -89,7 +94,7 @@ Widget *Widget_find_xy (Widget *widget, vec2 point);
void ui_widget_mesh_init ();
void Widget_tick (Widget *widget);
void Widget_render (Widget *widget, mat4 projection);
void Widget_render (Widget *widget, mat4 projection, int window_height);
/* ---------------------------------------------- */
typedef struct LabelFormatData