diff --git a/game/src/chunk/chunkman.c b/game/src/chunk/chunkman.c index f6a8885..85d97b4 100644 --- a/game/src/chunk/chunkman.c +++ b/game/src/chunk/chunkman.c @@ -206,7 +206,7 @@ chunkman_render (vec3 position, vec4 planes[6]) } program_set_vec3_ind (RESPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM); - ChunkMesh_render (mesh); + ChunkMesh_render (mesh, flags_get ("wireframe_enabled")); n_frame_chunks++; } } diff --git a/game/src/chunk/chunkmesh.c b/game/src/chunk/chunkmesh.c index c642dec..8e75005 100644 --- a/game/src/chunk/chunkmesh.c +++ b/game/src/chunk/chunkmesh.c @@ -101,7 +101,7 @@ ChunkMesh_bind (ChunkMesh *mesh) } void -ChunkMesh_render (ChunkMesh *mesh) +ChunkMesh_render (ChunkMesh *mesh, bool wireframe) { glBindBuffer (GL_ARRAY_BUFFER, mesh->pbo); glEnableVertexAttribArray (0); @@ -110,13 +110,6 @@ ChunkMesh_render (ChunkMesh *mesh) glBindBuffer (GL_ARRAY_BUFFER, mesh->mbo); glEnableVertexAttribArray (1); glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, sizeof (float) * 4, 0); - - if (flags_get ("wireframe_enabled")) - { - glDrawElements (GL_LINES, CHUNK_SIZE * 6, GL_UNSIGNED_INT, 0); - } - else - { - glDrawElements (GL_TRIANGLES, CHUNK_SIZE * 6, GL_UNSIGNED_INT, 0); - } + + glDrawElements (wireframe ? GL_LINES : GL_TRIANGLES, CHUNK_SIZE * 6, GL_UNSIGNED_INT, 0); } diff --git a/game/src/chunk/chunkmesh.h b/game/src/chunk/chunkmesh.h index 0772f88..3e5e4a7 100644 --- a/game/src/chunk/chunkmesh.h +++ b/game/src/chunk/chunkmesh.h @@ -3,7 +3,6 @@ #include #include -#include "../flags.h" #include "chunk.h" #define TERRAIN_TEXTURES 5 @@ -21,4 +20,4 @@ typedef struct ChunkMesh ChunkMesh *ChunkMesh_build (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc); void ChunkMesh_bind (ChunkMesh *mesh); -void ChunkMesh_render (ChunkMesh *mesh); +void ChunkMesh_render (ChunkMesh *mesh, bool wireframe); diff --git a/game/src/entity/entman.c b/game/src/entity/entman.c index 0c8955c..a4874bd 100644 --- a/game/src/entity/entman.c +++ b/game/src/entity/entman.c @@ -174,7 +174,7 @@ entman_render_entity (Entity *entity, void *userdata) if (entity->program != last_program) { - program_use (entity->program); + last_program = program_use (entity->program); } program_set_mat4 (entity->program, "model", model); @@ -183,19 +183,16 @@ entman_render_entity (Entity *entity, void *userdata) if (entity->texture != last_texture) { glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, entity->texture); + last_texture = texture_use (entity->texture); } if (entity->mesh_type != last_type) { SimpleMesh_bind (&to_render); + last_type = entity->mesh_type; } - - last_program = entity->program; - last_type = entity->mesh_type; - last_texture = entity->texture; - SimpleMesh_render (&to_render); + SimpleMesh_render (&to_render, flags_get ("wireframe_enabled")); n_frame_ents++; } diff --git a/game/src/event/evtman.c b/game/src/event/evtman.c index 58aaccb..825ddb3 100644 --- a/game/src/event/evtman.c +++ b/game/src/event/evtman.c @@ -80,16 +80,16 @@ evtman_init () evtman_add_handler (1, SDL_EVENT_MOUSE_WHEEL, evt_pred_flag, "ui_has_focus", uiman_cb_mouse_wheel, NULL); evtman_add_handler (1, SDL_EVENT_TEXT_INPUT, evt_pred_flag, "ui_has_focus", uiman_cb_text_input, NULL); - evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_W), evt_cb_flag_on, "moving_forward"); - evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_W), evt_cb_flag_off, "moving_forward"); - evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_S), evt_cb_flag_on, "moving_backward"); - evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_S), evt_cb_flag_off, "moving_backward"); - evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_A), evt_cb_flag_on, "moving_left"); - evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_A), evt_cb_flag_off, "moving_left"); - evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_D), evt_cb_flag_on, "moving_right"); - evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_D), evt_cb_flag_off, "moving_right"); - evtman_add_handler (0, SDL_EVENT_MOUSE_MOTION, NULL, NULL, evt_cb_rotate_camera, NULL); - evtman_add_handler (0, SDL_EVENT_MOUSE_BUTTON_DOWN, evt_pred_mouse, KEY (3), uiman_cb_switch_focus, NULL); + evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_W), evt_cb_flag_on, "moving_forward"); + evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_W), evt_cb_flag_off, "moving_forward"); + evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_S), evt_cb_flag_on, "moving_backward"); + evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_S), evt_cb_flag_off, "moving_backward"); + evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_A), evt_cb_flag_on, "moving_left"); + evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_A), evt_cb_flag_off, "moving_left"); + evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_D), evt_cb_flag_on, "moving_right"); + evtman_add_handler (0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_D), evt_cb_flag_off, "moving_right"); + evtman_add_handler (0, SDL_EVENT_MOUSE_MOTION, NULL, NULL, evt_cb_rotate_camera, NULL); + evtman_add_handler (0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_TAB), uiman_cb_switch_focus, NULL); #undef KEY } diff --git a/game/src/gl/mesh.c b/game/src/gl/mesh.c index 6450dfb..219ee2e 100644 --- a/game/src/gl/mesh.c +++ b/game/src/gl/mesh.c @@ -20,16 +20,9 @@ SimpleMesh_bind (SimpleMesh *mesh) } void -SimpleMesh_render (SimpleMesh *mesh) +SimpleMesh_render (SimpleMesh *mesh, bool wireframe) { - if (flags_get ("wireframe_enabled")) - { - glDrawElements (GL_LINES, mesh->indices_len, GL_UNSIGNED_INT, 0); - } - else - { - glDrawElements (GL_TRIANGLES, mesh->indices_len, GL_UNSIGNED_INT, 0); - } + glDrawElements (wireframe ? GL_LINES : GL_TRIANGLES, mesh->indices_len, GL_UNSIGNED_INT, 0); } SimpleMesh diff --git a/game/src/gl/mesh.h b/game/src/gl/mesh.h index ef4ceee..c52596f 100644 --- a/game/src/gl/mesh.h +++ b/game/src/gl/mesh.h @@ -14,7 +14,7 @@ typedef struct SimpleMesh } SimpleMesh; void SimpleMesh_bind (SimpleMesh *mesh); -void SimpleMesh_render (SimpleMesh *mesh); +void SimpleMesh_render (SimpleMesh *mesh, bool wireframe); SimpleMesh SimpleMesh_make_quad1 (); SimpleMesh SimpleMesh_make_quad2 (); diff --git a/game/src/gl/program.c b/game/src/gl/program.c index 31f45c2..a912390 100644 --- a/game/src/gl/program.c +++ b/game/src/gl/program.c @@ -1,6 +1,13 @@ #include "program.h" +unsigned int +program_use (int program) +{ + glUseProgram (program); + return program; +} + void shader_fail (int shader) { @@ -42,7 +49,7 @@ program_fail (int program) } } -int +unsigned int program_create (const char *v_src, const char *f_src) { int success = 0; diff --git a/game/src/gl/program.h b/game/src/gl/program.h index f05c42a..bd81e52 100644 --- a/game/src/gl/program.h +++ b/game/src/gl/program.h @@ -5,12 +5,10 @@ #include "../util.h" -/* Just for clarity sake. */ -#define program_use glUseProgram - +unsigned int program_use (int program); void shader_fail (int shader); void program_fail (int program); -int program_create (const char *v_src, const char *f_src); +unsigned int program_create (const char *v_src, const char *f_src); 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_vec3 (int program, const char *name, vec3 value); diff --git a/game/src/gl/texture.c b/game/src/gl/texture.c index efeedaf..c5baf45 100644 --- a/game/src/gl/texture.c +++ b/game/src/gl/texture.c @@ -1,5 +1,12 @@ #include "texture.h" +unsigned int +texture_use (unsigned int texture) +{ + glBindTexture (GL_TEXTURE_2D, texture); + return texture; +} + unsigned int texture_create (int width, int height, unsigned char *data) { diff --git a/game/src/gl/texture.h b/game/src/gl/texture.h index 587abdd..c22f1d2 100644 --- a/game/src/gl/texture.h +++ b/game/src/gl/texture.h @@ -2,4 +2,5 @@ #include +unsigned int texture_use (unsigned int texture); unsigned int texture_create (int width, int height, unsigned char *data); diff --git a/game/src/resources.c b/game/src/resources.c index 862f83c..daf6eb9 100644 --- a/game/src/resources.c +++ b/game/src/resources.c @@ -1,8 +1,5 @@ #include "resources.h" -/* TODO: Warn if program doesn't exist, make program_use and - texture_use return the textures/ */ - static GHashTable *programs; static GHashTable *textures; @@ -79,12 +76,22 @@ resources_add_texture (char *key, unsigned int texture) unsigned int resources_get_program (char *key) { + if (!g_hash_table_contains (programs, key)) + { + WARN ("Program `%s' does not exist. Careful!", key); + } + return GPOINTER_TO_INT (g_hash_table_lookup (programs, key)); } unsigned int resources_get_texture (char *key) { + if (!g_hash_table_contains (textures, key)) + { + WARN ("Texture `%s' does not exist. Careful!", key); + } + return GPOINTER_TO_INT (g_hash_table_lookup (textures, key)); } diff --git a/game/src/ui/uielement.c b/game/src/ui/uielement.c index da46871..97b24b2 100644 --- a/game/src/ui/uielement.c +++ b/game/src/ui/uielement.c @@ -1,7 +1,8 @@ #include "uielement.h" -/* TODO: Convert to mat3's and 2D affine transformations. */ /* TODO: Alpha blending. */ +/* TODO: Texture support in the uielement shader. */ +/* TODO: UTF-8 support */ static SimpleMesh quad; static unsigned int last_program; @@ -20,8 +21,6 @@ ui_el_new_internal (UIKind kind) UIElement *e = g_new0 (UIElement, 1); e->kind = kind; e->visible = true; - glm_vec4_zero (e->background_color); - glm_vec2_zero (e->position); glm_vec2_one (e->scale); e->children = g_array_new (false, false, sizeof (UIElement *)); return e; @@ -47,7 +46,7 @@ UIElement_label_new (const char *text) { UIElement *e = ui_el_new_internal (UI_KIND_LABEL); e->label.text = g_string_new (text); - glm_vec4_one (e->label.color); + glm_vec4_one (e->label.text_color); return e; } @@ -60,6 +59,39 @@ UIElement_set_on_tick (UIElement *element, element->userdata = userdata; } +void +UIElement_set_on_left_click (UIElement *element, + void (*on_left_click) (struct UIElement *self, void *userdata), + void *userdata) +{ + element->on_left_click = on_left_click; + element->userdata = userdata; +} + +void +UIElement_set_background_color (UIElement *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) +{ + glm_vec4_copy ((vec4) { r, g, b, a }, element->hover_background_color); +} + +void +UIElement_set_position (UIElement *element, float x, float y) +{ + glm_vec2_copy ((vec2) { x, y }, element->position); +} + +void +UIElement_set_scale (UIElement *element, float x, float y) +{ + glm_vec2_copy ((vec2) { x, y }, element->scale); +} + void UIElement_add_child (UIElement *parent, UIElement *child) { @@ -68,7 +100,7 @@ UIElement_add_child (UIElement *parent, UIElement *child) } void -UILabel_render_text (UIElement *element, mat3 parent_model) +UIElement_label_render_text (UIElement *element, mat3 parent_model) { mat3 model; glm_mat3_copy (parent_model, model); @@ -86,16 +118,15 @@ UILabel_render_text (UIElement *element, mat3 parent_model) if (last_program != RESPRG ("uitext")) { - program_use (RESPRG ("uitext")); - last_program = RESPRG ("uitext"); + last_program = program_use (RESPRG ("uitext")); } for (guint i = 0; i < element->label.text->len; ++i) { program_set_mat3 (RESPRG ("uitext"), "model", model); program_set_float (RESPRG ("uitext"), "character", element->label.text->str[i]); - program_set_vec4 (RESPRG ("uitext"), "color", element->label.color); - SimpleMesh_render (&quad); + program_set_vec4 (RESPRG ("uitext"), "color", element->label.text_color); + SimpleMesh_render (&quad, false); /* UI always without wireframe. */ glm_translate2d (model, (vec2) { 1.5f, 0.0f }); } } @@ -139,8 +170,7 @@ UIElement_render_with_model (UIElement *element, mat3 parent_model) if (last_program != RESPRG ("uielement")) { - program_use (RESPRG ("uielement")); - last_program = RESPRG ("uielement"); + last_program = program_use (RESPRG ("uielement")); } mat3 model; @@ -156,18 +186,20 @@ UIElement_render_with_model (UIElement *element, mat3 parent_model) if (element->kind != UI_KIND_ROOT) { program_set_mat3 (RESPRG ("uielement"), "model", model); - program_set_vec4 (RESPRG ("uielement"), "color", element->background_color); + program_set_vec4 (RESPRG ("uielement"), "color", + element->hovered ? element->hover_background_color + : element->background_color); glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, element->image); + texture_use (element->texture); - SimpleMesh_render (&quad); + SimpleMesh_render (&quad, false); } if (element->kind == UI_KIND_LABEL) { /* Here, we additionally render the text. */ - UILabel_render_text (element, model); + UIElement_label_render_text (element, model); } for (guint i = 0; i < element->children->len; ++i) @@ -177,6 +209,45 @@ UIElement_render_with_model (UIElement *element, mat3 parent_model) } } +static bool +UIElement_hit_test (UIElement *element, mat3 parent_model, vec2 point) +{ + mat3 model; + glm_mat3_copy (parent_model, model); + glm_translate2d (model, element->position); + glm_scale2d (model, element->scale); + + mat3 inv; + glm_mat3_inv (model, inv); + + vec3 local; + glm_mat3_mulv (inv, (vec3) { point[0], point[1], 1.0 }, local); + + 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) +{ + mat3 model; + glm_mat3_copy (parent_model, model); + glm_translate2d (model, element->position); + glm_scale2d (model, element->scale); + + 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); + if (hit) + return hit; + } + + if (element->kind != UI_KIND_ROOT && UIElement_hit_test (element, parent_model, mouse_ui_pos)) + return element; + + return NULL; +} + void UIElement_tick (UIElement *element) { @@ -195,12 +266,12 @@ UIElement_tick (UIElement *element) void UIElement_render (UIElement *element) { + last_program = -1; + if (element->kind == UI_KIND_ROOT && element->parent == NULL) { SimpleMesh_bind (&quad); - program_use (RESPRG ("uielement")); - last_program = RESPRG ("uielement"); - + glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, 0); @@ -210,15 +281,46 @@ UIElement_render (UIElement *element) } void -UILabel_on_tick_show_int (UIElement *element, void *userdata) +UIElement_label_set_text (UIElement *element, const char *text) { - int *value = userdata; - g_string_printf (element->label.text, "%d", *value); + g_string_overwrite (element->label.text, 0, text); } void -UILabel_on_tick_show_float (UIElement *element, void *userdata) +UIElement_label_printf (UIElement *element, const char *format, ...) +{ + va_list args; + va_start (args, format); + g_string_vprintf (element->label.text, format, args); + va_end (args); +} + +void +uicb_label_show_int (UIElement *element, void *userdata) +{ + int *value = userdata; + UIElement_label_printf (element, "%d", *value); +} + +void +uicb_label_show_float (UIElement *element, void *userdata) { float *value = userdata; - g_string_printf (element->label.text, "%3.2f", *value); + UIElement_label_printf (element, "%3.2f", *value); +} + +void +uicb_flag_switch (UIElement *element, void *userdata) +{ + UNUSED (element); + char *flag = userdata; + flags_switch (flag); +} + +void +uicb_debug_print (UIElement *element, void *userdata) +{ + UNUSED (element); + char *text = userdata; + INFO ("%s", text); } diff --git a/game/src/ui/uielement.h b/game/src/ui/uielement.h index c9f08bf..0a3fd0d 100644 --- a/game/src/ui/uielement.h +++ b/game/src/ui/uielement.h @@ -7,6 +7,7 @@ #include "../util.h" #include "../resources.h" +#include "../flags.h" #include "../gl/mesh.h" #include "../gl/program.h" @@ -14,7 +15,7 @@ typedef enum UIKind { UI_KIND_ROOT, UI_KIND_CONTAINER, - UI_KIND_LABEL, + UI_KIND_LABEL } UIKind; typedef struct UIContainer @@ -24,7 +25,7 @@ typedef struct UIContainer typedef struct UILabel { - vec4 color; + vec4 text_color; GString *text; } UILabel; @@ -36,11 +37,13 @@ typedef struct UIElement vec2 position; vec2 scale; - vec4 background_color; - unsigned int image; + vec4 background_color, hover_background_color; + unsigned int texture; bool visible; + bool hovered; void *userdata; + bool ignores_events; void (*on_left_click) (struct UIElement *self, void *userdata); void (*on_right_click) (struct UIElement *self, void *userdata); @@ -59,9 +62,23 @@ UIElement *UIElement_container_new (bool 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 *self, void *userdata), void *userdata); void UIElement_set_on_tick (UIElement *element, void (*on_tick) (struct UIElement *self, void *userdata), 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 UILabel_on_tick_show_int (UIElement *element, void *userdata); -void UILabel_on_tick_show_float (UIElement *element, void *userdata); +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_print (UIElement *element, void *userdata); diff --git a/game/src/ui/uiman.c b/game/src/ui/uiman.c index aa2adc6..1d86740 100644 --- a/game/src/ui/uiman.c +++ b/game/src/ui/uiman.c @@ -3,8 +3,10 @@ extern SDL_Window *sdl_window; extern float delta_time; extern int n_frame_ents, n_frame_chunks; +extern vec3 camera_position; static UIElement *ui_root; +static UIElement *hovered_element; void uiman_init () @@ -13,26 +15,47 @@ uiman_init () ui_root = UIElement_root_new (); UIElement *container = UIElement_container_new (false); - container->scale[0] = 0.4; - container->scale[1] = 0.07; - container->position[0] = -0.5; - container->position[1] = 0.83; - glm_vec3_copy ((vec4) { 1.0, 0.0, 0.0, 1.0 }, container->background_color); + UIElement_set_position (container, -0.5, 0.75); + UIElement_set_scale (container, 0.4, 0.15); + UIElement_set_background_color (container, 1.0, 0.0, 0.0, 1.0); UIElement *frame_time = UIElement_label_new ("Frame time: "); - UIElement *container2 = UIElement_container_new (true); + UIElement_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); + 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); - UIElement_set_on_tick (frame_time, UILabel_on_tick_show_float, &delta_time); - UIElement_set_on_tick (entities_rendered, UILabel_on_tick_show_int, &n_frame_ents); - UIElement_set_on_tick (chunks_rendered, UILabel_on_tick_show_int, &n_frame_chunks); - + UIElement *container2 = UIElement_container_new (true); UIElement_add_child (container2, entities_rendered); UIElement_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]); + UIElement *container3 = UIElement_container_new (true); + UIElement_add_child (container3, pos_x); + UIElement_add_child (container3, pos_y); + UIElement_add_child (container3, pos_z); + + UIElement *wireframe_button = UIElement_label_new ("Toggle wireframe"); + UIElement_set_background_color (wireframe_button, 0.2, 0.2, 0.2, 1.0); + UIElement_set_hover_background_color (wireframe_button, 0.3, 0.3, 0.3, 1.0); + UIElement_set_on_left_click (wireframe_button, uicb_flag_switch, "wireframe_enabled"); + + 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, wireframe_button); UIElement_add_child (ui_root, container); } @@ -49,6 +72,12 @@ uiman_render () UIElement_render (ui_root); } +static inline void +screen_to_ui_coords (int mouse_x, int mouse_y, int screen_w, int screen_h, vec2 out_coords) { + out_coords[0] = (float) mouse_x / (float) screen_w * 2.0 - 1.0; + out_coords[1] = 1.0 - (float) mouse_y / (float) screen_h * 2.0; +} + bool uiman_cb_switch_focus (SDL_Event *event, void *data) { @@ -75,14 +104,64 @@ uiman_cb_key_up (SDL_Event *event, void *data) bool uiman_cb_mouse_motion (SDL_Event *event, void *data) { - UNUSED (event, data); + /* What even is in data at this point? No fucking idea. */ + UNUSED (data); + int win_w, win_h; + SDL_GetWindowSize (sdl_window, &win_w, &win_h); + + 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); + + if (element != hovered_element) + { + if (hovered_element) + { + hovered_element->hovered = false; + } + + if (element) + { + element->hovered = true; + } + + hovered_element = element; + } + + /* This callback always eats the event, because why would the game + need mouse motion if the UI has stolen the focus? */ return true; } bool uiman_cb_button_down (SDL_Event *event, void *data) { - UNUSED (event, data); + UNUSED (data); + + int win_w, win_h; + SDL_GetWindowSize (sdl_window, &win_w, &win_h); + + 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); + + if (element) + { + if (event->button.button == SDL_BUTTON_LEFT && element->on_left_click) + { + element->on_left_click (element, element->userdata); + return true; + } + + if (event->button.button == SDL_BUTTON_RIGHT && element->on_right_click) + { + element->on_right_click (element, element->userdata); + return true; + } + } + return false; } diff --git a/game/src/ui/uiman.h b/game/src/ui/uiman.h index 0617d2d..42e4d01 100644 --- a/game/src/ui/uiman.h +++ b/game/src/ui/uiman.h @@ -3,6 +3,7 @@ #include "uielement.h" #include "../flags.h" #include "../state.h" +#include "../camera.h" void uiman_init (); void uiman_tick (); diff --git a/game/src/util.h b/game/src/util.h index 333e0f6..4d9e71c 100644 --- a/game/src/util.h +++ b/game/src/util.h @@ -3,8 +3,8 @@ #include #include -#define GAME_NAME "Wschód" -#define GAME_VERSION "0.1" +#define GAME_NAME "Wschod" +#define GAME_VERSION "0.2" #define COLOR_BLUE "\x1B[34m" #define COLOR_RED "\x1B[31m"