diff --git a/game/res/shaders/uiwidget.frag b/game/res/shaders/uiwidget.frag index 3a2970e..d480d44 100644 --- a/game/res/shaders/uiwidget.frag +++ b/game/res/shaders/uiwidget.frag @@ -3,21 +3,26 @@ precision mediump float; uniform sampler2D background_image; -uniform bool has_texture; +uniform bool has_background_image; uniform vec4 background_color; +uniform float border_width; +uniform vec4 border_color; +uniform vec2 widget_size; + varying vec2 f_uv; void main () { - vec4 tex_color = texture2D (background_image, f_uv); + vec2 border_uv = vec2 (border_width) / widget_size; + + float x_border = step (f_uv.x, border_uv.x) + step (1.0 - border_uv.x, f_uv.x); + float y_border = step (f_uv.y, border_uv.y) + step (1.0 - border_uv.y, f_uv.y); + float is_border = clamp (x_border + y_border, 0.0, 1.0); - if (has_texture) - { - gl_FragColor = vec4 (background_color.xyz, 1.0) * tex_color; - } - else - { - gl_FragColor = background_color; - } + vec4 bgc = has_background_image + ? mix (texture2D (background_image, f_uv), background_color, 0.5) + : background_color; + + gl_FragColor = mix (bgc, border_color, is_border); } diff --git a/game/src/gl/program.c b/game/src/gl/program.c index 0105855..75d071c 100644 --- a/game/src/gl/program.c +++ b/game/src/gl/program.c @@ -78,6 +78,12 @@ program_create (const char *v_src, const char *f_src) return program; } +void +program_set_vec2 (int program, const char *name, vec2 value) +{ + glUniform2f (glGetUniformLocation (program, name), value[0], value[1]); +} + void program_set_vec3 (int program, const char *name, vec3 value) { diff --git a/game/src/gl/program.h b/game/src/gl/program.h index 13432b9..0e3d7b8 100644 --- a/game/src/gl/program.h +++ b/game/src/gl/program.h @@ -11,6 +11,7 @@ unsigned int program_create (const char *v_src, const char *f_src); void program_set_int (int program, const char *name, int value); void program_set_float (int program, const char *name, float value); void program_set_int_array (int program, const char *name, size_t count, int *value); +void program_set_vec2 (int program, const char *name, vec2 value); void program_set_vec3 (int program, const char *name, vec3 value); void program_set_vec3_ind (int program, const char *name, float x, float y, float z); void program_set_vec4 (int program, const char *name, vec4 value); diff --git a/game/src/ui/uiman.c b/game/src/ui/uiman.c index 9b667a1..9f38db4 100644 --- a/game/src/ui/uiman.c +++ b/game/src/ui/uiman.c @@ -24,9 +24,12 @@ 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_background_color (debug_menu, 0, 0, 0, 0.7); - Widget_set_position (debug_menu, 32, 32); - Widget_set_size (debug_menu, 350, 125); + Widget_set_background_image (debug_menu, RESTEX ("terrain1")); + VEC4_SETI (debug_menu->background_color, 0, 0, 0, 0.7); + VEC2_SETI (debug_menu->position, 32, 32); + VEC2_SETI (debug_menu->size, 350, 150); + debug_menu->border_width = 2; + VEC4_SETI (debug_menu->border_color, 0, 0, 0, 1); 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); @@ -39,6 +42,9 @@ uiman_init () 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_add_child_weighed (debug_menu, Widget_label_make_flag_switch_button ("Toggle wireframe", "wireframe_enabled"), 1); + Widget_add_child_weighed (debug_menu, Widget_label_make_flag_switch_button ("Toggle flying", "flight_enabled"), 1); } void diff --git a/game/src/ui/widget.c b/game/src/ui/widget.c index 55280f9..d171676 100644 --- a/game/src/ui/widget.c +++ b/game/src/ui/widget.c @@ -55,6 +55,13 @@ Widget_add_child_weighed (Widget *parent, Widget *child, float layout_weight) Widget_add_child (parent, child); } +void +Widget_set_background_image (Widget *widget, unsigned int image) +{ + widget->has_background_image = TRUE; + widget->background_image = image; +} + void Widget_set_on_tick (Widget *widget, void (*on_tick) (Widget *, void *), @@ -73,43 +80,6 @@ Widget_set_on_left_click (Widget *widget, widget->left_click_data = userdata; } -void -Widget_set_position (Widget *widget, float x, float y) -{ - glm_vec2_copy ((vec2) { x, y }, widget->position); -} - -void -Widget_set_size (Widget *widget, float x, float y) -{ - glm_vec2_copy ((vec2) { x, y }, widget->size); -} - -void -Widget_set_background_image (Widget *widget, unsigned int image) -{ - 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 Widget_label_set_text (Widget *widget, const char *text) { @@ -242,20 +212,19 @@ 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); - if (child->layout_weight == 0.0) - { - total_fixed += horizontal ? child->size[0] : child->size[1]; - } - else - { - total_weights += child->layout_weight; - } - } + Widget *child; + + WIDGET_FOREACH_CHILD (parent, i, child) { + 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; @@ -265,41 +234,39 @@ Widget_container_layout (Widget *parent, gboolean horizontal) } float offset = 0.0; - for (unsigned int i = 0; i < parent->children->len; ++i) - { - Widget *child = g_array_index (parent->children, Widget *, i); - if (child->layout_weight == 0.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 - { - 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]; - } - } - } + WIDGET_FOREACH_CHILD (parent, i, child) { + if (child->layout_weight == 0.0) + { + if (horizontal) + { + VEC2_SETI (child->position, parent->position[0] + offset, parent->position[1]); + child->size[1] = parent->size[1]; + offset += child->size[0]; + } + else + { + VEC2_SETI (child->position, parent->position[0], parent->position[1] + offset); + child->size[0] = parent->size[0]; + offset += child->size[1]; + } + } + else + { + if (horizontal) + { + VEC2_SETI (child->position, parent->position[0] + offset, parent->position[1]); + VEC2_SETI (child->size, child->layout_weight * weights_size, parent->size[1]); + offset += child->size[0]; + } + else + { + VEC2_SETI (child->position, parent->position[0], parent->position[1] + offset); + VEC2_SETI (child->size, parent->size[0], child->layout_weight * weights_size); + offset += child->size[1]; + } + } + } } void @@ -327,6 +294,10 @@ Widget_render (Widget *widget, mat4 projection, int window_height) program_set_vec4 (RESPRG ("uiwidget"), "background_color", widget->background_color); + program_set_float (RESPRG ("uiwidget"), "border_width", widget->border_width); + program_set_vec4 (RESPRG ("uiwidget"), "border_color", widget->border_color); + program_set_vec2 (RESPRG ("uiwidget"), "widget_size", widget->size); + if (widget->clicked) { program_set_vec4 (RESPRG ("uiwidget"), "background_color", widget->clicked_bg_color); @@ -358,12 +329,11 @@ Widget_render (Widget *widget, mat4 projection, int window_height) { Widget_label_render_text (widget, projection); } - - for (unsigned int i = 0; i < widget->children->len; ++i) - { - Widget *child = g_array_index (widget->children, Widget *, i); - Widget_render (child, projection, window_height); - } + + Widget *child; + WIDGET_FOREACH_CHILD (widget, i, child) { + Widget_render (child, projection, window_height); + } } /* --------- */ @@ -428,9 +398,11 @@ 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); + VEC4_SETI (w->background_color, 1, 1, 1, 0.1); + VEC4_SETI (w->hovered_bg_color, 1, 1, 1, 0.2); + VEC4_SETI (w->clicked_bg_color, 1, 1, 1, 0.3); + w->border_width = 2; + VEC4_SETI (w->border_color, 1, 1, 1, 0.5); Widget_set_on_left_click (w, uicb_switch_flag, flag); return w; } diff --git a/game/src/ui/widget.h b/game/src/ui/widget.h index 03caa8f..9095320 100644 --- a/game/src/ui/widget.h +++ b/game/src/ui/widget.h @@ -9,12 +9,15 @@ #include "../gl/mesh.h" #include "../gl/program.h" +#define WIDGET_FOREACH_CHILD(widget, i, child) \ + 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_CHECKBOX + WIDGET_LABEL } WidgetKind; typedef struct ContainerWidget @@ -62,6 +65,9 @@ typedef struct Widget gboolean has_background_image; unsigned int background_image; + unsigned int border_width; + vec4 border_color; + void (*on_left_click) (struct Widget *, void *); void *left_click_data; void (*on_right_click) (struct Widget *, void *); @@ -78,16 +84,10 @@ void Widget_add_child (Widget *parent, Widget *child); void Widget_add_child_weighed (Widget *parent, Widget *child, float layout_weight); +void Widget_set_background_image (Widget *widget, unsigned int image); 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_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, ...); diff --git a/game/src/util.h b/game/src/util.h index df242fa..8083aef 100644 --- a/game/src/util.h +++ b/game/src/util.h @@ -11,6 +11,9 @@ #define UNUSED_2(arg, ...) (void) arg, UNUSED_3 (__VA_ARGS__, 0) #define UNUSED_3(arg, ...) (void) arg +#define VEC2_SETI(v, x, y) glm_vec2_copy((vec2) { x, y }, v) +#define VEC4_SETI(v, r, g, b, a) glm_vec4_copy((vec4) { r, g, b, a }, v) + /* GLib log levels: