diff --git a/game/src/state.h b/game/src/state.h index d3fe675..c6fc25b 100644 --- a/game/src/state.h +++ b/game/src/state.h @@ -4,7 +4,6 @@ #include "flags.h" #include "chunk/chunkman.h" #include "entity/entman.h" -#include "ui/uielement.h" void game_state_init (int ticks); void game_state_tick (int ticks); diff --git a/game/src/ui/uielement.h b/game/src/ui/uielement.h deleted file mode 100644 index ebd694e..0000000 --- a/game/src/ui/uielement.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include - -#include "../util.h" -#include "../resources.h" -#include "../flags.h" -#include "../gl/mesh.h" -#include "../gl/program.h" - -typedef enum UIKind - { - UI_KIND_ROOT, - UI_KIND_CONTAINER, - UI_KIND_LABEL - } UIKind; - -typedef struct UIContainer -{ - gboolean horizontal; -} UIContainer; - -typedef struct UILabel -{ - vec4 text_color; - GString *text; - enum { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT } alignment; -} UILabel; - -typedef struct UIElement -{ - UIKind kind; - struct UIElement *parent; - GArray *children; - - vec2 position; - vec2 scale; - vec4 background_color, hover_background_color; - unsigned int texture; - gboolean visible; - gboolean hovered; - - void (*on_left_click) (struct UIElement *, void *); - void *left_click_data; - void (*on_right_click) (struct UIElement *, void *); - void *right_click_data; - void (*on_tick) (struct UIElement *, void *); - void *tick_data; - - union { - UIContainer container; - UILabel label; - }; -} UIElement; - -void ui_element_mesh_init (); - -UIElement *UIElement_root_new (); -UIElement *UIElement_container_new (gboolean horizontal); -UIElement *UIElement_label_new (const char *text); - -void UIElement_add_child (UIElement *parent, UIElement *child); - -void UIElement_set_on_left_click (UIElement *element, void (*on_left_click) (struct UIElement *, void *), void *userdata); -void UIElement_set_on_tick (UIElement *element, void (*on_tick) (struct UIElement *, void *), void *userdata); - -void UIElement_set_background_color (UIElement *element, float r, float g, float b, float a); -void UIElement_set_hover_background_color (UIElement *element, float r, float g, float b, float a); -void UIElement_set_position (UIElement *element, float x, float y); -void UIElement_set_scale (UIElement *element, float x, float y); - -UIElement *UIElement_find_xy (UIElement *element, mat3 parent_model, vec2 mouse_ui_pos); -void UIElement_tick (UIElement *element); -void UIElement_render (UIElement *element); - -void UIElement_label_set_text (UIElement *element, const char *text); -void UIElement_label_printf (UIElement *element, const char *format, ...); - -void uicb_label_show_int (UIElement *element, void *userdata); -void uicb_label_show_float (UIElement *element, void *userdata); - -void uicb_flag_switch (UIElement *element, void *userdata); -void uicb_debug (UIElement *element, void *userdata); diff --git a/game/src/ui/uiman.c b/game/src/ui/uiman.c index 061e431..e614b23 100644 --- a/game/src/ui/uiman.c +++ b/game/src/ui/uiman.c @@ -5,81 +5,81 @@ extern float delta_time; extern int n_frame_ents, n_frame_chunks; extern vec3 camera_position; -static UIElement *ui_root; -static UIElement *hovered_element; +static Widget *ui_root; +static Widget *hovered_element; void uiman_init () { ui_element_mesh_init (); - ui_root = UIElement_root_new (); + ui_root = Widget_root_new (); - UIElement *container = UIElement_container_new (false); - UIElement_set_position (container, -0.5, 0.75); - UIElement_set_scale (container, 0.4, 0.15); - UIElement_set_background_color (container, 0.0, 0.0, 0.0, 0.8); + Widget *container = Widget_container_new (false); + Widget_set_position (container, -0.5, 0.75); + Widget_set_scale (container, 0.4, 0.15); + Widget_set_background_color (container, 0.0, 0.0, 0.0, 0.8); - UIElement *frame_time = UIElement_label_new ("Frame time: "); - UIElement_set_on_tick (frame_time, uicb_label_show_float, &delta_time); + Widget *frame_time = Widget_label_new ("Frame time: "); + Widget_set_on_tick (frame_time, uicb_label_show_float, &delta_time); - UIElement *game_name = UIElement_label_new (NULL); - UIElement_label_printf (game_name, "%s %s", GAME_NAME, GAME_VERSION); + Widget *game_name = Widget_label_new (NULL); + Widget_label_printf (game_name, "%s %s", GAME_NAME, GAME_VERSION); - UIElement *entities_rendered = UIElement_label_new ("Entities rendered: "); - UIElement *chunks_rendered = UIElement_label_new ("Chunks rendered: "); - UIElement_set_on_tick (entities_rendered, uicb_label_show_int, &n_frame_ents); - UIElement_set_on_tick (chunks_rendered, uicb_label_show_int, &n_frame_chunks); + Widget *entities_rendered = Widget_label_new ("Entities rendered: "); + Widget *chunks_rendered = Widget_label_new ("Chunks rendered: "); + Widget_set_on_tick (entities_rendered, uicb_label_show_int, &n_frame_ents); + Widget_set_on_tick (chunks_rendered, uicb_label_show_int, &n_frame_chunks); - UIElement *container2 = UIElement_container_new (true); - UIElement_add_child (container2, entities_rendered); - UIElement_add_child (container2, chunks_rendered); + Widget *container2 = Widget_container_new (true); + Widget_add_child (container2, entities_rendered); + Widget_add_child (container2, chunks_rendered); - UIElement *pos_x = UIElement_label_new ("X: "); - UIElement *pos_y = UIElement_label_new ("Y: "); - UIElement *pos_z = UIElement_label_new ("Z: "); - UIElement_set_on_tick (pos_x, uicb_label_show_float, &camera_position[0]); - UIElement_set_on_tick (pos_y, uicb_label_show_float, &camera_position[1]); - UIElement_set_on_tick (pos_z, uicb_label_show_float, &camera_position[2]); + Widget *pos_x = Widget_label_new ("X: "); + Widget *pos_y = Widget_label_new ("Y: "); + Widget *pos_z = Widget_label_new ("Z: "); + Widget_set_on_tick (pos_x, uicb_label_show_float, &camera_position[0]); + Widget_set_on_tick (pos_y, uicb_label_show_float, &camera_position[1]); + Widget_set_on_tick (pos_z, uicb_label_show_float, &camera_position[2]); - UIElement *container3 = UIElement_container_new (true); - UIElement_add_child (container3, pos_x); - UIElement_add_child (container3, pos_y); - UIElement_add_child (container3, pos_z); + Widget *container3 = Widget_container_new (true); + Widget_add_child (container3, pos_x); + Widget_add_child (container3, pos_y); + Widget_add_child (container3, pos_z); - UIElement *wireframe_button = UIElement_label_new ("Toggle wireframe"); - UIElement_set_background_color (wireframe_button, 1.0, 1.0, 1.0, 0.2); - UIElement_set_hover_background_color (wireframe_button, 1.0, 1.0, 1.0, 0.3); - UIElement_set_on_left_click (wireframe_button, uicb_flag_switch, "wireframe_enabled"); + Widget *wireframe_button = Widget_label_new ("Toggle wireframe"); + Widget_set_background_color (wireframe_button, 1.0, 1.0, 1.0, 0.2); + Widget_set_hover_background_color (wireframe_button, 1.0, 1.0, 1.0, 0.3); + Widget_set_on_left_click (wireframe_button, uicb_flag_switch, "wireframe_enabled"); - UIElement *flight_button = UIElement_label_new ("Toggle flight"); - UIElement_set_background_color (flight_button, 1.0, 1.0, 1.0, 0.2); - UIElement_set_hover_background_color (flight_button, 1.0, 1.0, 1.0, 0.3); - UIElement_set_on_left_click (flight_button, uicb_flag_switch, "flight_enabled"); + Widget *flight_button = Widget_label_new ("Toggle flight"); + Widget_set_background_color (flight_button, 1.0, 1.0, 1.0, 0.2); + Widget_set_hover_background_color (flight_button, 1.0, 1.0, 1.0, 0.3); + Widget_set_on_left_click (flight_button, uicb_flag_switch, "flight_enabled"); - UIElement *container4 = UIElement_container_new (true); - UIElement_add_child (container4, wireframe_button); - UIElement_add_child (container4, flight_button); + Widget *container4 = Widget_container_new (true); + Widget_add_child (container4, wireframe_button); + Widget_add_child (container4, flight_button); - UIElement_add_child (container, game_name); - UIElement_add_child (container, frame_time); - UIElement_add_child (container, container2); - UIElement_add_child (container, container3); - UIElement_add_child (container, container4); + Widget_add_child (container, game_name); + Widget_add_child (container, frame_time); + Widget_add_child (container, container2); + Widget_add_child (container, container3); + Widget_add_child (container, container4); - UIElement_add_child (ui_root, container); + Widget_add_child (ui_root, container); } void uiman_tick () { - UIElement_tick (ui_root); + Widget_tick (ui_root); } void uiman_render () { - UIElement_render (ui_root); + Widget_render (ui_root); } static inline void @@ -122,7 +122,7 @@ uiman_cb_mouse_motion (SDL_Event *event, void *data) vec2 ui_pos; screen_to_ui_coords (event->motion.x, event->motion.y, win_w, win_h, ui_pos); - UIElement *element = UIElement_find_xy (ui_root, GLM_MAT3_IDENTITY, ui_pos); + Widget *element = Widget_find_xy (ui_root, GLM_MAT3_IDENTITY, ui_pos); if (element != hovered_element) { @@ -155,7 +155,7 @@ uiman_cb_button_down (SDL_Event *event, void *data) vec2 ui_pos; screen_to_ui_coords (event->motion.x, event->motion.y, win_w, win_h, ui_pos); - UIElement *element = UIElement_find_xy (ui_root, GLM_MAT3_IDENTITY, ui_pos); + Widget *element = Widget_find_xy (ui_root, GLM_MAT3_IDENTITY, ui_pos); if (element) { diff --git a/game/src/ui/uiman.h b/game/src/ui/uiman.h index 54efe11..ba4b431 100644 --- a/game/src/ui/uiman.h +++ b/game/src/ui/uiman.h @@ -1,6 +1,6 @@ #pragma once -#include "uielement.h" +#include "widget.h" #include "../flags.h" #include "../state.h" #include "../camera.h" diff --git a/game/src/ui/uielement.c b/game/src/ui/widget.c similarity index 67% rename from game/src/ui/uielement.c rename to game/src/ui/widget.c index 6597803..a14f815 100644 --- a/game/src/ui/uielement.c +++ b/game/src/ui/widget.c @@ -1,5 +1,11 @@ -#include "uielement.h" +#include "widget.h" +/* TODO: Layout container children scaling, so some children can be + smaller, some bigger, etc. Perhaps android-esque LinearLayout + weight? */ +/* TODO: Text alignment in labels. */ +/* TODO: Padding. */ +/* TODO: Widget borders. */ /* TODO: Texture support in the uielement shader. */ static SimpleMesh quad; @@ -11,46 +17,46 @@ ui_element_mesh_init () quad = SimpleMesh_make_quad1 (); } -static inline UIElement * +static inline Widget * ui_el_new_internal (UIKind kind) { /* new0 instead of new is important, otherwise there's trash memory in the function pointers */ - UIElement *e = g_new0 (UIElement, 1); + Widget *e = g_new0 (Widget, 1); e->kind = kind; e->visible = true; glm_vec2_one (e->scale); - e->children = g_array_new (false, false, sizeof (UIElement *)); + e->children = g_array_new (false, false, sizeof (Widget *)); return e; } -UIElement * -UIElement_root_new () +Widget * +Widget_root_new () { - UIElement *e = ui_el_new_internal (UI_KIND_ROOT); + Widget *e = ui_el_new_internal (UI_KIND_ROOT); return e; } -UIElement * -UIElement_container_new (gboolean horizontal) +Widget * +Widget_container_new (gboolean horizontal) { - UIElement *e = ui_el_new_internal (UI_KIND_CONTAINER); + Widget *e = ui_el_new_internal (UI_KIND_CONTAINER); e->container.horizontal = horizontal; return e; } -UIElement * -UIElement_label_new (const char *text) +Widget * +Widget_label_new (const char *text) { - UIElement *e = ui_el_new_internal (UI_KIND_LABEL); + Widget *e = ui_el_new_internal (UI_KIND_LABEL); e->label.text = g_string_new (text); glm_vec4_one (e->label.text_color); return e; } void -UIElement_set_on_tick (UIElement *element, - void (*on_tick) (struct UIElement *self, void *userdata), +Widget_set_on_tick (Widget *element, + void (*on_tick) (struct Widget *self, void *userdata), void *userdata) { element->on_tick = on_tick; @@ -58,8 +64,8 @@ UIElement_set_on_tick (UIElement *element, } void -UIElement_set_on_left_click (UIElement *element, - void (*on_left_click) (struct UIElement *, void *), +Widget_set_on_left_click (Widget *element, + void (*on_left_click) (struct Widget *, void *), void *userdata) { element->on_left_click = on_left_click; @@ -67,38 +73,38 @@ UIElement_set_on_left_click (UIElement *element, } void -UIElement_set_background_color (UIElement *element, float r, float g, float b, float a) +Widget_set_background_color (Widget *element, float r, float g, float b, float a) { glm_vec4_copy ((vec4) { r, g, b, a }, element->background_color); } void -UIElement_set_hover_background_color (UIElement *element, float r, float g, float b, float a) +Widget_set_hover_background_color (Widget *element, float r, float g, float b, float a) { glm_vec4_copy ((vec4) { r, g, b, a }, element->hover_background_color); } void -UIElement_set_position (UIElement *element, float x, float y) +Widget_set_position (Widget *element, float x, float y) { glm_vec2_copy ((vec2) { x, y }, element->position); } void -UIElement_set_scale (UIElement *element, float x, float y) +Widget_set_scale (Widget *element, float x, float y) { glm_vec2_copy ((vec2) { x, y }, element->scale); } void -UIElement_add_child (UIElement *parent, UIElement *child) +Widget_add_child (Widget *parent, Widget *child) { child->parent = parent; g_array_append_val (parent->children, child); } void -UIElement_label_render_text (UIElement *element, mat3 parent_model) +Widget_label_render_text (Widget *element, mat3 parent_model) { mat3 model; glm_mat3_copy (parent_model, model); @@ -135,7 +141,7 @@ UIElement_label_render_text (UIElement *element, mat3 parent_model) } void -UIContainer_layout (UIElement *element) +UIContainer_layout (Widget *element) { if (element->children->len == 0) { @@ -148,7 +154,7 @@ UIContainer_layout (UIElement *element) for (guint i = 0; i < element->children->len; ++i) { - UIElement *child = g_array_index (element->children, UIElement *, i); + Widget *child = g_array_index (element->children, Widget *, i); if (element->container.horizontal) { @@ -164,7 +170,7 @@ UIContainer_layout (UIElement *element) } void -UIElement_render_with_model (UIElement *element, mat3 parent_model) +Widget_render_with_model (Widget *element, mat3 parent_model) { if (!element->visible) { @@ -202,18 +208,18 @@ UIElement_render_with_model (UIElement *element, mat3 parent_model) if (element->kind == UI_KIND_LABEL) { /* Here, we additionally render the text. */ - UIElement_label_render_text (element, model); + Widget_label_render_text (element, model); } for (guint i = 0; i < element->children->len; ++i) { - UIElement *child = g_array_index (element->children, UIElement *, i); - UIElement_render_with_model (child, model); + Widget *child = g_array_index (element->children, Widget *, i); + Widget_render_with_model (child, model); } } static gboolean -UIElement_hit_test (UIElement *element, mat3 parent_model, vec2 point) +Widget_hit_test (Widget *element, mat3 parent_model, vec2 point) { mat3 model; glm_mat3_copy (parent_model, model); @@ -229,8 +235,8 @@ UIElement_hit_test (UIElement *element, mat3 parent_model, vec2 point) return local[0] >= -1.0f && local[0] <= 1.0f && local[1] >= -1.0f && local[1] <= 1.0f; } -UIElement * -UIElement_find_xy (UIElement *element, mat3 parent_model, vec2 mouse_ui_pos) +Widget * +Widget_find_xy (Widget *element, mat3 parent_model, vec2 mouse_ui_pos) { mat3 model; glm_mat3_copy (parent_model, model); @@ -239,20 +245,20 @@ UIElement_find_xy (UIElement *element, mat3 parent_model, vec2 mouse_ui_pos) for (int i = element->children->len - 1; i >= 0; --i) { - UIElement *child = g_array_index (element->children, UIElement *, i); - UIElement *hit = UIElement_find_xy (child, model, mouse_ui_pos); + Widget *child = g_array_index (element->children, Widget *, i); + Widget *hit = Widget_find_xy (child, model, mouse_ui_pos); if (hit) return hit; } - if (element->kind != UI_KIND_ROOT && UIElement_hit_test (element, parent_model, mouse_ui_pos)) + if (element->kind != UI_KIND_ROOT && Widget_hit_test (element, parent_model, mouse_ui_pos)) return element; return NULL; } void -UIElement_tick (UIElement *element) +Widget_tick (Widget *element) { if (element->on_tick) { @@ -261,13 +267,13 @@ UIElement_tick (UIElement *element) for (guint i = 0; i < element->children->len; ++i) { - UIElement *child = g_array_index (element->children, UIElement *, i); - UIElement_tick (child); + Widget *child = g_array_index (element->children, Widget *, i); + Widget_tick (child); } } void -UIElement_render (UIElement *element) +Widget_render (Widget *element) { last_program = -1; @@ -279,18 +285,18 @@ UIElement_render (UIElement *element) glBindTexture (GL_TEXTURE_2D, 0); mat3 identity = GLM_MAT3_IDENTITY_INIT; - UIElement_render_with_model (element, identity); + Widget_render_with_model (element, identity); } } void -UIElement_label_set_text (UIElement *element, const char *text) +Widget_label_set_text (Widget *element, const char *text) { g_string_overwrite (element->label.text, 0, text); } void -UIElement_label_printf (UIElement *element, const char *format, ...) +Widget_label_printf (Widget *element, const char *format, ...) { va_list args; va_start (args, format); @@ -299,21 +305,21 @@ UIElement_label_printf (UIElement *element, const char *format, ...) } void -uicb_label_show_int (UIElement *element, void *userdata) +uicb_label_show_int (Widget *element, void *userdata) { int *value = userdata; - UIElement_label_printf (element, "%d", *value); + Widget_label_printf (element, "%d", *value); } void -uicb_label_show_float (UIElement *element, void *userdata) +uicb_label_show_float (Widget *element, void *userdata) { float *value = userdata; - UIElement_label_printf (element, "%3.2f", *value); + Widget_label_printf (element, "%3.2f", *value); } void -uicb_flag_switch (UIElement *element, void *userdata) +uicb_flag_switch (Widget *element, void *userdata) { UNUSED (element); char *flag = userdata; @@ -321,7 +327,7 @@ uicb_flag_switch (UIElement *element, void *userdata) } void -uicb_debug (UIElement *element, void *userdata) +uicb_debug (Widget *element, void *userdata) { UNUSED (element); char *text = userdata; diff --git a/game/src/ui/widget.h b/game/src/ui/widget.h new file mode 100644 index 0000000..699c3f1 --- /dev/null +++ b/game/src/ui/widget.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include + +#include "../util.h" +#include "../resources.h" +#include "../flags.h" +#include "../gl/mesh.h" +#include "../gl/program.h" + +typedef enum UIKind + { + UI_KIND_ROOT, + UI_KIND_CONTAINER, + UI_KIND_LABEL + } UIKind; + +typedef struct UIContainer +{ + gboolean horizontal; +} UIContainer; + +typedef struct UILabel +{ + vec4 text_color; + GString *text; + enum { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT } alignment; +} UILabel; + +typedef struct Widget +{ + UIKind kind; + struct Widget *parent; + GArray *children; + + vec2 position; + vec2 scale; + vec4 background_color, hover_background_color; + unsigned int texture; + gboolean visible; + gboolean hovered; + + void (*on_left_click) (struct Widget *, void *); + void *left_click_data; + void (*on_right_click) (struct Widget *, void *); + void *right_click_data; + void (*on_tick) (struct Widget *, void *); + void *tick_data; + + union { + UIContainer container; + UILabel label; + }; +} Widget; + +void ui_element_mesh_init (); + +Widget *Widget_root_new (); +Widget *Widget_container_new (gboolean horizontal); +Widget *Widget_label_new (const char *text); + +void Widget_add_child (Widget *parent, Widget *child); + +void Widget_set_on_left_click (Widget *element, void (*on_left_click) (struct Widget *, void *), void *userdata); +void Widget_set_on_tick (Widget *element, void (*on_tick) (struct Widget *, void *), void *userdata); + +void Widget_set_background_color (Widget *element, float r, float g, float b, float a); +void Widget_set_hover_background_color (Widget *element, float r, float g, float b, float a); +void Widget_set_position (Widget *element, float x, float y); +void Widget_set_scale (Widget *element, float x, float y); + +Widget *Widget_find_xy (Widget *element, mat3 parent_model, vec2 mouse_ui_pos); +void Widget_tick (Widget *element); +void Widget_render (Widget *element); + +void Widget_label_set_text (Widget *element, const char *text); +void Widget_label_printf (Widget *element, const char *format, ...); + +void uicb_label_show_int (Widget *element, void *userdata); +void uicb_label_show_float (Widget *element, void *userdata); + +void uicb_flag_switch (Widget *element, void *userdata); +void uicb_debug (Widget *element, void *userdata);