UI system revamp

This commit is contained in:
2025-06-07 10:23:44 +02:00
parent 1dad00ace0
commit 04b28f0bcb
20 changed files with 502 additions and 180 deletions
+2 -2
View File
@@ -2,12 +2,12 @@
precision mediump float;
uniform vec3 color;
uniform vec4 color;
uniform sampler2D texture;
varying vec2 f_uv;
void main ()
{
gl_FragColor = texture2D (texture, f_uv) * vec4 (color, 1.0);
gl_FragColor = vec4 (color.xyz, 1.0);
}
+4 -21
View File
@@ -1,31 +1,14 @@
#version 100
attribute vec4 position;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 model;
uniform float time;
uniform float character;
uniform mat3 model;
varying vec2 f_uv;
void main ()
{
float tex_w = 128.0;
float tex_h = 128.0;
float char_w = 8.0;
float char_h = 16.0;
float chars_per_row = tex_w / char_w;
float x = mod (character, chars_per_row);
float y = floor (character / chars_per_row);
vec2 char_offset = vec2 (x * char_w / tex_w, y * char_h / tex_h);
vec2 char_size = vec2 (char_w / tex_w, char_h / tex_h);
f_uv = char_offset + uv * char_size;
gl_Position = model * position;
f_uv = uv;
gl_Position = vec4 (model * vec3 (position.xy, 1.0), 1.0);
}
+14
View File
@@ -0,0 +1,14 @@
#version 100
precision mediump float;
uniform vec4 color;
uniform sampler2D texture;
varying vec2 f_uv;
void main ()
{
gl_FragColor = texture2D (texture, f_uv) * vec4 (color.xyz, 1.0);
}
+30
View File
@@ -0,0 +1,30 @@
#version 100
attribute vec3 position;
attribute vec2 uv;
uniform mat3 model;
uniform float character;
varying vec2 f_uv;
void main ()
{
float tex_w = 128.0;
float tex_h = 128.0;
float char_w = 8.0;
float char_h = 16.0;
float chars_per_row = tex_w / char_w;
float x = mod (character, chars_per_row);
float y = floor (character / chars_per_row);
vec2 char_offset = vec2 (x * char_w / tex_w, y * char_h / tex_h);
vec2 char_size = vec2 (char_w / tex_w, char_h / tex_h);
f_uv = char_offset + uv * char_size;
gl_Position = vec4 (model * vec3 (position.xy, 1.0), 1.0);
}
+19 -25
View File
@@ -120,19 +120,16 @@ chunkman_tick (vec3 position)
{
for (int x = cx - RENDER_DISTANCE - 1; x <= cx + RENDER_DISTANCE + 1; ++x)
{
if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= (RENDER_DISTANCE + 1) * (RENDER_DISTANCE + 1))
{
if (chunkman_get_Chunk_at (x, z) == NULL)
{
chunkman_generate_Chunk_at (x, z);
++frame_chunks;
}
if (chunkman_get_Chunk_at (x, z) == NULL)
{
chunkman_generate_Chunk_at (x, z);
++frame_chunks;
}
if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET)
{
return;
}
}
if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET)
{
return;
}
}
}
@@ -140,20 +137,17 @@ chunkman_tick (vec3 position)
{
for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x)
{
if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= RENDER_SQR)
{
if (chunkman_get_ChunkMesh_at (x, z) == NULL)
{
chunkman_generate_ChunkMesh_at (x, z);
++frame_chunks;
}
if (chunkman_get_ChunkMesh_at (x, z) == NULL)
{
chunkman_generate_ChunkMesh_at (x, z);
++frame_chunks;
}
if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET)
{
return;
}
}
}
if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET)
{
return;
}
}
}
}
-3
View File
@@ -97,9 +97,6 @@ entman_render_entity (Entity *entity, void *userdata)
return;
}
/* TODO: Fix this up. It still isn't perfect, when you look up,
sometimes the entities get culled. */
#if FRUSTUM_CULL
vec3 aabb[2];
entity_compute_aabb (entity, aabb[0], aabb[1]);
+52 -29
View File
@@ -5,7 +5,29 @@ extern vec3 camera_rotation;
static GList *handlers = NULL;
bool
rotate_camera (SDL_Event *event, void *userdata)
evt_pred_key (SDL_Event *event, void *data)
{
unsigned int expected_key = GPOINTER_TO_INT (data);
return event->key.key == expected_key;
}
bool
evt_pred_mouse (SDL_Event *event, void *data)
{
unsigned int expected_button = GPOINTER_TO_INT (data);
return event->button.button == expected_button;
}
bool
evt_pred_flag (SDL_Event *event, void *data)
{
UNUSED (event);
char *flag = data;
return flags_get (flag);
}
bool
evt_cb_rotate_camera (SDL_Event *event, void *userdata)
{
UNUSED (userdata);
camera_rotation[0] -= event->motion.xrel / 100.f;
@@ -16,19 +38,7 @@ rotate_camera (SDL_Event *event, void *userdata)
}
bool
key_predicate (SDL_Event *event, void *data)
{
if (event->type != SDL_EVENT_KEY_DOWN && event->type != SDL_EVENT_KEY_UP)
{
return false;
}
unsigned int expected_key = GPOINTER_TO_INT (data);
return event->key.key == expected_key;
}
bool
flag_off (SDL_Event *event, void *data)
evt_cb_flag_off (SDL_Event *event, void *data)
{
UNUSED (event);
char *flag = data;
@@ -37,7 +47,7 @@ flag_off (SDL_Event *event, void *data)
}
bool
flag_on (SDL_Event *event, void *data)
evt_cb_flag_on (SDL_Event *event, void *data)
{
UNUSED (event);
char *flag = data;
@@ -46,29 +56,42 @@ flag_on (SDL_Event *event, void *data)
}
bool
flag_switch (SDL_Event *event, void *data)
evt_cb_flag_switch (SDL_Event *event, void *data)
{
UNUSED (event);
char *flag = data;
flags_set (flag, !flags_get (flag));
flags_switch (flag);
return true;
}
void
evtman_init ()
{
evtman_add_handler (0, SDL_EVENT_KEY_DOWN, key_predicate, GINT_TO_POINTER(SDLK_W), flag_on, "moving_forward");
evtman_add_handler (0, SDL_EVENT_KEY_UP, key_predicate, GINT_TO_POINTER(SDLK_W), flag_off, "moving_forward");
evtman_add_handler (0, SDL_EVENT_KEY_DOWN, key_predicate, GINT_TO_POINTER(SDLK_S), flag_on, "moving_backward");
evtman_add_handler (0, SDL_EVENT_KEY_UP, key_predicate, GINT_TO_POINTER(SDLK_S), flag_off, "moving_backward");
evtman_add_handler (0, SDL_EVENT_KEY_DOWN, key_predicate, GINT_TO_POINTER(SDLK_A), flag_on, "moving_left");
evtman_add_handler (0, SDL_EVENT_KEY_UP, key_predicate, GINT_TO_POINTER(SDLK_A), flag_off, "moving_left");
evtman_add_handler (0, SDL_EVENT_KEY_DOWN, key_predicate, GINT_TO_POINTER(SDLK_D), flag_on, "moving_right");
evtman_add_handler (0, SDL_EVENT_KEY_UP, key_predicate, GINT_TO_POINTER(SDLK_D), flag_off, "moving_right");
#define KEY(k) GINT_TO_POINTER(k)
evtman_add_handler (2, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY(SDLK_F1), evt_cb_flag_switch, "wireframe_enabled");
/* The UI effectively eats most SDL events, as it needs it for it's
own calculations. */
evtman_add_handler (1, SDL_EVENT_KEY_DOWN, evt_pred_flag, "ui_has_focus", uiman_cb_key_down, NULL);
evtman_add_handler (1, SDL_EVENT_KEY_UP, evt_pred_flag, "ui_has_focus", uiman_cb_key_up, NULL);
evtman_add_handler (1, SDL_EVENT_MOUSE_MOTION, evt_pred_flag, "ui_has_focus", uiman_cb_mouse_motion, NULL);
evtman_add_handler (1, SDL_EVENT_MOUSE_BUTTON_DOWN, evt_pred_flag, "ui_has_focus", uiman_cb_button_down, NULL);
evtman_add_handler (1, SDL_EVENT_MOUSE_BUTTON_UP, evt_pred_flag, "ui_has_focus", uiman_cb_button_up, NULL);
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, key_predicate, GINT_TO_POINTER(SDLK_F1), flag_switch, "wireframe_enabled");
evtman_add_handler (0, SDL_EVENT_MOUSE_MOTION, NULL, NULL, rotate_camera, NULL);
#undef KEY
}
void
@@ -105,7 +128,7 @@ evtman_handle_SDL_Event (SDL_Event *event)
if ((h->filter == 0 || h->filter == event->type)
&& (!h->predicate || h->predicate (event, h->predicate_data)))
{
if (h->callback (event, h->callback_data))
if (h->callback && h->callback (event, h->callback_data))
{
break;
}
+1
View File
@@ -7,6 +7,7 @@
#include "handler.h"
#include "../flags.h"
#include "../util.h"
#include "../ui/uiman.h"
void evtman_init ();
+6
View File
@@ -8,6 +8,12 @@ flags_init ()
flags = g_hash_table_new (g_str_hash, g_str_equal);
}
void
flags_switch (char *flag)
{
flags_set (flag, !flags_get (flag));
}
void
flags_set (char *flag, bool value)
{
+16
View File
@@ -4,6 +4,22 @@
#include <glib-2.0/glib.h>
/*
A short list of most flags used in the game:
wireframe_enabled
moving_forward
moving_backward
moving_left
moving_right
ui_has_focus
*/
void flags_init ();
void flags_switch (char *flag);
void flags_set (char *flag, bool value);
bool flags_get (char *flag);
+13
View File
@@ -1,3 +1,4 @@
#include "program.h"
void
@@ -78,6 +79,12 @@ program_set_vec3 (int program, const char *name, vec3 value)
glUniform3f (glGetUniformLocation (program, name), value[0], value[1], value[2]);
}
void
program_set_vec4 (int program, const char *name, vec4 value)
{
glUniform4f (glGetUniformLocation (program, name), value[0], value[1], value[2], value[3]);
}
void
program_set_vec3_ind (int program, const char *name, float x, float y, float z)
{
@@ -96,6 +103,12 @@ program_set_int_array (int program, const char *name, size_t count, int *value)
glUniform1iv (glGetUniformLocation (program, name), count, value);
}
void
program_set_mat3 (int program, const char *name, mat3 value)
{
glUniformMatrix3fv (glGetUniformLocation (program, name), 1, GL_FALSE, (float *) value);
}
void
program_set_mat4 (int program, const char *name, mat4 value)
{
+2
View File
@@ -15,5 +15,7 @@ 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);
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);
void program_set_mat3 (int program, const char *name, mat3 value);
void program_set_mat4 (int program, const char *name, mat4 value);
void program_print (int program);
+1 -1
View File
@@ -3,7 +3,7 @@
extern vec3 camera_position;
extern int last_time;
static SDL_Window *sdl_window;
SDL_Window *sdl_window;
static SDL_GLContext gl_context;
#define WINDOW_WIDTH 800
+1
View File
@@ -54,6 +54,7 @@ SDL_AppIterate (void *appstate)
game_state_tick (SDL_GetTicks ());
entman_tick ();
chunkman_tick (camera_position);
uiman_tick ();
graphics_render ();
return SDL_APP_CONTINUE;
+4
View File
@@ -1,5 +1,8 @@
#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;
@@ -152,6 +155,7 @@ resources_init ()
RAP ("chunk", RLP ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
RAP ("clouds", RLP ("res/shaders/clouds.vert", "res/shaders/clouds.frag"));
RAP ("uielement", RLP ("res/shaders/uielement.vert", "res/shaders/uielement.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"));
-9
View File
@@ -3,8 +3,6 @@
extern vec3 camera_position;
extern vec3 camera_rotation;
extern Entity *player_entity, *sky_entity;
extern UIElement *player_pos, *n_ents, *n_chunks, *frame_time;
extern int n_frame_ents, n_frame_chunks;
float delta_time;
int last_time;
@@ -32,13 +30,6 @@ game_state_tick (int ticks)
sky. */
sky_entity->position[0] = camera_position[0];
sky_entity->position[2] = camera_position[2];
g_string_printf (player_pos->text, "Position (X:%2.1f, Y:%2.1f, Z:%2.1f)",
player_entity->position[0], player_entity->position[1],
player_entity->position[2]);
g_string_printf (n_ents->text, "Entities rendered: %d", n_frame_ents);
g_string_printf (n_chunks->text, "Chunks rendered: %d", n_frame_chunks);
g_string_printf (frame_time->text, "Frame time: %.3f", delta_time);
if (flags_get ("moving_forward"))
{
+194 -47
View File
@@ -1,8 +1,10 @@
#include "uielement.h"
/* TODO: Convert to mat3's and 2D affine transformations. */
/* TODO: Alpha blending. */
static SimpleMesh quad;
static unsigned int last_program;
void
ui_element_mesh_init ()
@@ -10,68 +12,213 @@ ui_element_mesh_init ()
quad = SimpleMesh_make_quad1 ();
}
void
UIElement_add_child (UIElement *parent, UIElement *child)
static inline UIElement *
ui_el_new_internal (UIKind kind)
{
g_sequence_append (parent->children, child);
/* new0 instead of new is important, otherwise there's trash memory
in the function pointers */
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;
}
UIElement *
UIElement_root_new ()
{
UIElement *e = ui_el_new_internal (UI_KIND_ROOT);
return e;
}
UIElement *
UIElement_container_new (bool horizontal)
{
UIElement *e = ui_el_new_internal (UI_KIND_CONTAINER);
e->container.horizontal = horizontal;
return e;
}
UIElement *
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);
return e;
}
void
uiel_render_internal (gpointer data, gpointer userdata)
UIElement_set_on_tick (UIElement *element,
void (*on_tick) (struct UIElement *self, void *userdata),
void *userdata)
{
UNUSED (userdata);
UIElement *element = data;
UIElement_render (element);
element->on_tick = on_tick;
element->userdata = userdata;
}
void
UIElement_add_child (UIElement *parent, UIElement *child)
{
child->parent = parent;
g_array_append_val (parent->children, child);
}
void
UILabel_render_text (UIElement *element, mat3 parent_model)
{
mat3 model;
glm_mat3_copy (parent_model, model);
float abs_scale_x = glm_vec2_norm ((vec2) { model[0][0], model[1][0] });
float abs_scale_y = glm_vec2_norm ((vec2) { model[0][1], model[1][1] });
/* I have no idea about all those calculations, but trial and error
shows they work. */
glm_translate2d (model, (vec2) { -1.0 + abs_scale_y / abs_scale_x * 0.5, 0.0 });
glm_scale2d (model, (vec2) { abs_scale_y / abs_scale_x * 0.5, 1.0 });
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, RESTEX ("font0"));
if (last_program != RESPRG ("uitext"))
{
program_use (RESPRG ("uitext"));
last_program = 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);
glm_translate2d (model, (vec2) { 1.5f, 0.0f });
}
}
void
UIContainer_layout (UIElement *element)
{
if (element->children->len == 0)
{
return;
}
float size = 1.0 / element->children->len;
float start_pos = 1.0 - size;
float step = size * 2.0;
for (guint i = 0; i < element->children->len; ++i)
{
UIElement *child = g_array_index (element->children, UIElement *, i);
if (element->container.horizontal)
{
child->position[0] = -start_pos + (i * step);
child->scale[0] = size;
}
else
{
child->position[1] = start_pos - (i * step);
child->scale[1] = size;
}
}
}
void
UIElement_render_with_model (UIElement *element, mat3 parent_model)
{
if (!element->visible)
{
return;
}
if (last_program != RESPRG ("uielement"))
{
program_use (RESPRG ("uielement"));
last_program = RESPRG ("uielement");
}
mat3 model;
glm_mat3_copy (parent_model, model);
glm_translate2d (model, element->position);
glm_scale2d (model, element->scale);
if (element->kind == UI_KIND_CONTAINER)
{
UIContainer_layout (element);
}
if (element->kind != UI_KIND_ROOT)
{
program_set_mat3 (RESPRG ("uielement"), "model", model);
program_set_vec4 (RESPRG ("uielement"), "color", element->background_color);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, element->image);
SimpleMesh_render (&quad);
}
if (element->kind == UI_KIND_LABEL)
{
/* Here, we additionally render the text. */
UILabel_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);
}
}
void
UIElement_tick (UIElement *element)
{
if (element->on_tick)
{
element->on_tick (element, element->userdata);
}
for (guint i = 0; i < element->children->len; ++i)
{
UIElement *child = g_array_index (element->children, UIElement *, i);
UIElement_tick (child);
}
}
void
UIElement_render (UIElement *element)
{
if (element->parent == NULL)
if (element->kind == UI_KIND_ROOT && element->parent == NULL)
{
SimpleMesh_bind (&quad);
program_use (RESPRG ("uielement"));
}
if (element->visible)
{
/* First, we render the background as a quad of
`background_color'. */
last_program = RESPRG ("uielement");
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, 0);
mat4 model = GLM_MAT4_IDENTITY_INIT;
glm_translate (model, element->position);
glm_scale (model, element->scale);
program_set_mat4 (RESPRG ("uielement"), "model", model);
program_set_vec3 (RESPRG ("uielement"), "color", element->background_color);
SimpleMesh_render (&quad);
/* Now, the tedious, boring, and so on task of rendering the
text, the worst fate of an OpenGL programmer. */
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, RESTEX ("font0"));
program_set_vec3 (RESPRG ("uielement"), "color", element->text_color);
for (size_t i = 0; i < element->text->len; ++i)
{
vec3 pos;
float x = -element->scale[0] + (element->scale[1] / 2) + (element->scale[1] * i);
glm_vec3_add (element->position, (vec3) { x, 0.0, 0.0 }, pos);
glm_mat4_copy (GLM_MAT4_IDENTITY, model);
glm_translate (model, pos);
glm_scale (model, (vec3) { element->scale[1] / 2, element->scale[1], 1.0 });
program_set_mat4 (RESPRG ("uielement"), "model", model);
program_set_float (RESPRG ("uielement"), "character", element->text->str[i]);
SimpleMesh_render (&quad);
}
}
if (element->children != NULL)
{
g_sequence_foreach (element->children, uiel_render_internal, NULL);
mat3 identity = GLM_MAT3_IDENTITY_INIT;
UIElement_render_with_model (element, identity);
}
}
void
UILabel_on_tick_show_int (UIElement *element, void *userdata)
{
int *value = userdata;
g_string_printf (element->label.text, "%d", *value);
}
void
UILabel_on_tick_show_float (UIElement *element, void *userdata)
{
float *value = userdata;
g_string_printf (element->label.text, "%3.2f", *value);
}
+45 -12
View File
@@ -10,25 +10,58 @@
#include "../gl/mesh.h"
#include "../gl/program.h"
typedef enum UIKind
{
UI_KIND_ROOT,
UI_KIND_CONTAINER,
UI_KIND_LABEL,
} UIKind;
typedef struct UIContainer
{
bool horizontal;
} UIContainer;
typedef struct UILabel
{
vec4 color;
GString *text;
} UILabel;
typedef struct UIElement
{
UIKind kind;
struct UIElement *parent;
GSequence *children;
void (*on_left_click) (struct UIElement *self);
void (*on_right_click) (struct UIElement *self);
void (*on_tick) (struct UIElement *self);
void *userdata;
GArray *children;
vec2 position;
vec2 scale;
vec4 background_color;
unsigned int image;
bool visible;
vec3 text_color;
vec3 background_color;
vec3 position;
vec3 scale;
GString *text;
void *userdata;
void (*on_left_click) (struct UIElement *self, void *userdata);
void (*on_right_click) (struct UIElement *self, void *userdata);
void (*on_tick) (struct UIElement *self, void *userdata);
union {
UIContainer container;
UILabel label;
};
} UIElement;
void ui_element_mesh_init ();
void UIElement_render (UIElement *element);
UIElement *UIElement_root_new ();
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_tick (UIElement *element, void (*on_tick) (struct UIElement *self, void *userdata), void *userdata);
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);
+85 -31
View File
@@ -1,54 +1,108 @@
#include "uiman.h"
UIElement *player_pos, *n_ents, *n_chunks, *frame_time;
extern SDL_Window *sdl_window;
extern float delta_time;
extern int n_frame_ents, n_frame_chunks;
static UIElement ui_root;
#define UINEWROOT() ((UIElement) { .parent = NULL, .children = g_sequence_new (NULL), .visible = false })
#define UINEW(pare) ((UIElement) { .parent = pare, .text_color = { 1.0, 1.0, 1.0 }, .visible = true, .text = g_string_new (NULL) })
#define UIADD(pare, child) (UIElement_add_child (pare, child))
static UIElement *ui_root;
void
uiman_init ()
{
ui_element_mesh_init ();
ui_root = UINEWROOT ();
player_pos = malloc (sizeof (UIElement));
*player_pos = UINEW (&ui_root);
glm_vec3_copy ((vec3) { -0.65, 0.92, 0.0 }, player_pos->position);
glm_vec3_copy ((vec3) { 0.3, 0.03, 1.0 }, player_pos->scale);
UIADD (&ui_root, player_pos);
ui_root = UIElement_root_new ();
n_ents = malloc (sizeof (UIElement));
*n_ents = UINEW (&ui_root);
glm_vec3_copy ((vec3) { -0.65, 0.81, 0.0 }, n_ents->position);
glm_vec3_copy ((vec3) { 0.3, 0.03, 1.0 }, n_ents->scale);
glm_vec3_copy ((vec3) { 0.7, 1.0, 0.7 }, n_ents->text_color);
UIADD (&ui_root, n_ents);
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);
n_chunks = malloc (sizeof (UIElement));
*n_chunks = UINEW (&ui_root);
glm_vec3_copy ((vec3) { -0.65, 0.70, 0.0 }, n_chunks->position);
glm_vec3_copy ((vec3) { 0.3, 0.03, 1.0 }, n_chunks->scale);
UIADD (&ui_root, n_chunks);
UIElement *frame_time = UIElement_label_new ("Frame time: ");
UIElement *container2 = UIElement_container_new (true);
UIElement *entities_rendered = UIElement_label_new ("Entities rendered: ");
UIElement *chunks_rendered = UIElement_label_new ("Chunks rendered: ");
frame_time = malloc (sizeof (UIElement));
*frame_time = UINEW (&ui_root);
glm_vec3_copy ((vec3) { -0.65, 0.59, 0.0 }, frame_time->position);
glm_vec3_copy ((vec3) { 0.3, 0.03, 1.0 }, frame_time->scale);
UIADD (&ui_root, frame_time);
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_add_child (container2, entities_rendered);
UIElement_add_child (container2, chunks_rendered);
UIElement_add_child (container, frame_time);
UIElement_add_child (container, container2);
UIElement_add_child (ui_root, container);
}
void
uiman_tick ()
{
UIElement_tick (ui_root);
}
void
uiman_render ()
{
UIElement_render (&ui_root);
UIElement_render (ui_root);
}
bool
uiman_cb_switch_focus (SDL_Event *event, void *data)
{
UNUSED (event, data);
flags_switch ("ui_has_focus");
SDL_SetWindowRelativeMouseMode (sdl_window, !flags_get ("ui_has_focus"));
return true;
}
bool
uiman_cb_key_down (SDL_Event *event, void *data)
{
UNUSED (event, data);
return false;
}
bool
uiman_cb_key_up (SDL_Event *event, void *data)
{
UNUSED (event, data);
return false;
}
bool
uiman_cb_mouse_motion (SDL_Event *event, void *data)
{
UNUSED (event, data);
return true;
}
bool
uiman_cb_button_down (SDL_Event *event, void *data)
{
UNUSED (event, data);
return false;
}
bool
uiman_cb_button_up (SDL_Event *event, void *data)
{
UNUSED (event, data);
return false;
}
bool
uiman_cb_mouse_wheel (SDL_Event *event, void *data)
{
UNUSED (event, data);
return false;
}
bool
uiman_cb_text_input (SDL_Event *event, void *data)
{
UNUSED (event, data);
return false;
}
+13
View File
@@ -1,6 +1,19 @@
#pragma once
#include "uielement.h"
#include "../flags.h"
#include "../state.h"
void uiman_init ();
void uiman_tick ();
void uiman_render ();
bool uiman_cb_switch_focus (SDL_Event *event, void *data);
bool uiman_cb_key_down (SDL_Event *event, void *data);
bool uiman_cb_key_up (SDL_Event *event, void *data);
bool uiman_cb_mouse_motion (SDL_Event *event, void *data);
bool uiman_cb_button_down (SDL_Event *event, void *data);
bool uiman_cb_button_up (SDL_Event *event, void *data);
bool uiman_cb_mouse_wheel (SDL_Event *event, void *data);
bool uiman_cb_text_input (SDL_Event *event, void *data);