From 586d39e6444ab1964e18b9ddeecccf31b64e2de6 Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Sun, 26 Nov 2023 21:32:19 +0200 Subject: [PATCH] help overlay --- cudoku.c | 148 ++++++++++++++++++++++------------------------ cudoku.h | 14 +---- main.c | 19 +++--- shaders/font.frag | 2 +- shaders/font.vert | 5 +- ui.c | 38 +++++++----- ui.h | 9 +-- z_math.h | 1 - 8 files changed, 115 insertions(+), 121 deletions(-) diff --git a/cudoku.c b/cudoku.c index 5a0ca7f..32d02a1 100644 --- a/cudoku.c +++ b/cudoku.c @@ -74,9 +74,10 @@ void draw_win(Cudoku *game) { draw_text(time_text, 48.f, constraints, &text_color, ALIGN_CENTER); } -void draw_grid(Size window_size) { +void draw_board(Cudoku *game, Size window_size) { Color bg_color = {240.0f, 235.0f, 227.0f, 255.f}; Color color = {0.0f, 0.0f, 0.0f, 255.f}; + Size cell_size = {window_size.width / 9, window_size.height / 9}; UIConstraints constraints = {0}; set_x_constraint(&constraints, 0, UI_CONSTRAINT_FIXED); set_y_constraint(&constraints, 0, UI_CONSTRAINT_FIXED); @@ -85,7 +86,7 @@ void draw_grid(Size window_size) { draw_quad(constraints, &bg_color, 0.0, ALIGN_TOP_LEFT); - for (int i = 1; i < 10; i++) { + for (int i = 1; i < 9; i++) { set_x_constraint(&constraints, i * 100, UI_CONSTRAINT_FIXED); set_y_constraint(&constraints, 0, UI_CONSTRAINT_FIXED); if (i % 3 == 0) { @@ -106,6 +107,21 @@ void draw_grid(Size window_size) { } draw_quad(constraints, &color, 0.0, ALIGN_TOP_LEFT); } + + set_x_constraint(&constraints, 0, UI_CONSTRAINT_FIXED); + set_y_constraint(&constraints, 0, UI_CONSTRAINT_FIXED); + set_width_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); + set_height_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); + + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 9; j++) { + Sizef text_size = calculate_text_size("7", 72.f); + set_y_constraint(&constraints, i * 100 + cell_size.height / 2.f - text_size.height / 2.f, UI_CONSTRAINT_FIXED); + set_x_constraint(&constraints, j * 100 + cell_size.width / 2.f - text_size.width / 2.f, UI_CONSTRAINT_FIXED); + // TODO: + draw_text("7", 72.f, constraints, &color, ALIGN_TOP_LEFT); + } + } } unsigned int prepare_bg(bool use_texture, unsigned int *texture) { @@ -612,87 +628,65 @@ bool toggle_help(Cudoku *game) { return false; } -void draw_ui_element_at(Shader shader, unsigned int vao, unsigned int vbo, Matrix4x4 *projection, Vec2 pos, Size size, Color color) { - use_shader(shader); - - set_mat4f(shader, "transform", (float *)projection->m); - set_vec4f(shader, "aColor", color.r, color.g, color.b, color.a); - - glBindVertexArray(vao); - - float vertices[6][2] = { - {pos.x, pos.y + size.height}, - {pos.x, pos.y}, - {pos.x + size.width, pos.y}, - - {pos.x, pos.y + size.height}, - {pos.x + size.width, pos.y}, - {pos.x + size.width, pos.y + size.height}, +void draw_help(Timer *timer) { + int const text_padding = 10; + float const help_font_size = 24.f; + float const closing_in_font_size = 18.f; + Color const bg_color = { + .r = 0.f, + .g = 0.f, + .b = 0.f, + .a = 185.f + }; + Color const text_color = { + 237.f, + 255.f, + 255.f, + 255.f, + }; + Color const closing_in_text_color = { + .r = 255.0f, + .g = 150.0f, + .b = 0.0f, + .a = 255.0f, }; - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); - glBindBuffer(GL_ARRAY_BUFFER, 0); + int overlay_height = 0; + int overlay_width = 0; + int total_help_texts_height = 10; - glDrawArrays(GL_TRIANGLES, 0, 6); + for (int i = 0; i < HELP_TEXT_SIZE; i++) { + Sizef text_size = calculate_text_size(help_texts[i], help_font_size); + overlay_height += text_size.height + text_padding; + overlay_width = max(overlay_width, text_size.width + text_padding * 2); + } + Size size = {.width = overlay_width, .height = overlay_height + text_padding * 2}; + UIConstraints constraints = {0}; + set_width_constraint(&constraints, size.width, UI_CONSTRAINT_FIXED); + set_height_constraint(&constraints, size.height, UI_CONSTRAINT_FIXED); + draw_quad(constraints, &bg_color, 0.0, ALIGN_TOP_LEFT); - glBindVertexArray(0); + set_x_constraint(&constraints, text_padding, UI_CONSTRAINT_FIXED); + for (int i = 0; i < HELP_TEXT_SIZE; i++) { + Sizef text_size = calculate_text_size(help_texts[i], help_font_size); + set_y_constraint(&constraints, total_help_texts_height, UI_CONSTRAINT_FIXED); + set_width_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); + set_height_constraint(&constraints, 1, UI_CONSTRAINT_FIXED); + draw_text(help_texts[i], help_font_size, constraints, &text_color, ALIGN_TOP_LEFT); + + total_help_texts_height += text_size.height + text_padding; + } + + if (timer->is_running) { + char closing_in_text[128]; + snprintf(closing_in_text, sizeof(closing_in_text), "Hiding in %ds", (int)timer_remaining(timer) + 1); + Sizef closing_in_text_size = calculate_text_size(closing_in_text, closing_in_font_size); + set_x_constraint(&constraints, overlay_width - closing_in_text_size.width - text_padding, UI_CONSTRAINT_FIXED); + set_y_constraint(&constraints, text_padding, UI_CONSTRAINT_FIXED); + draw_text(closing_in_text, closing_in_font_size, constraints, &closing_in_text_color, ALIGN_TOP_LEFT); + } } -/* void draw_help_overlay(Timer *timer) { */ -/* int total_help_texts_height = 20; */ - -/* int const text_padding = 10; */ -/* float const text_scale = 0.3f; */ -/* int overlay_height = 0; */ -/* int overlay_width = 0; */ - -/* for (int i = 0; i < HELP_TEXT_SIZE; i++) { */ -/* /1* Size text_size = calculate_text_size(help_texts[i], text_scale); *1/ */ -/* /1* overlay_height += text_size.height + text_padding; *1/ */ -/* /1* overlay_width = max(overlay_width, text_size.width + text_padding * 2); *1/ */ -/* } */ -/* Size size = {.width = overlay_width, .height = overlay_height + text_padding * 2}; */ -/* /1* Vec2 pos = { *1/ */ -/* /1* .x = 0, *1/ */ -/* /1* .y = window_height - size.height *1/ */ -/* /1* }; *1/ */ -/* Color color = { */ -/* .r = 0.1f, */ -/* .g = 0.1f, */ -/* .b = 0.1f, */ -/* .a = 0.95f */ -/* }; */ -/* /1* draw_ui_element_at(overlay_shader, overlay_vao, overlay_vbo, projection, pos, size, color); *1/ */ - -/* for (int i = 0; i < HELP_TEXT_SIZE; i++) { */ -/* /1* Size text_size = calculate_text_size(help_texts[i], text_scale); *1/ */ -/* /1* Vec2 text_pos = { *1/ */ -/* /1* .x = text_padding, *1/ */ -/* /1* .y = window_height - total_help_texts_height - (text_padding * 2) *1/ */ -/* /1* }; *1/ */ -/* /1* total_help_texts_height += text_size.height + text_padding; *1/ */ -/* /1* draw_text_at(font_shader, help_texts[i], text_pos, text_scale, font_vao, font_vbo, (float *)projection->m, NULL); *1/ */ -/* } */ - -/* if (timer->is_running) { */ -/* char closing_in_text[128]; */ -/* /1* snprintf(closing_in_text, sizeof(closing_in_text), "Hiding in %ds", (int)timer_remaining(timer) + 1); *1/ */ -/* /1* Size closing_in_text_size = calculate_text_size(closing_in_text, text_scale / 2.0); *1/ */ -/* /1* Vec2 closing_in_text_pos = { *1/ */ -/* /1* .x = overlay_width - closing_in_text_size.width, *1/ */ -/* /1* .y = window_height - closing_in_text_size.height - text_padding, *1/ */ -/* /1* }; *1/ */ -/* /1* Color closing_in_text_color = { *1/ */ -/* /1* .r = 255.0f, *1/ */ -/* /1* .g = 150.0f, *1/ */ -/* /1* .b = 0.0f, *1/ */ -/* /1* .a = 1.0f, *1/ */ -/* /1* }; *1/ */ -/* /1* draw_text_at(font_shader, closing_in_text, closing_in_text_pos, text_scale / 2.0, font_vao, font_vbo, (float *)projection->m, &closing_in_text_color); *1/ */ -/* } */ -/* } */ - void draw_timer(Timer *timer) { if (!timer->is_running) return; diff --git a/cudoku.h b/cudoku.h index 1cdeb70..d047f3a 100644 --- a/cudoku.h +++ b/cudoku.h @@ -42,17 +42,7 @@ void toggle_selection(Cudoku *game); void generate_random_board(Cudoku *game); void reset_board(Cudoku *game); bool toggle_help(Cudoku *game); -void draw_help_overlay( - Shader overlay_shader, - Shader font_shader, - unsigned int overlay_vao, - unsigned int overlay_vbo, - unsigned int font_vao, - unsigned int font_vbo, - Matrix4x4 *projection, - int window_height, - Timer *timer -); +void draw_help(Timer *timer); void draw_timer(Timer *timer); void draw_win(Cudoku *game); -void draw_grid(Size window_size); +void draw_board(Cudoku *game, Size window_size); diff --git a/main.c b/main.c index 54b0397..8374b66 100644 --- a/main.c +++ b/main.c @@ -151,11 +151,20 @@ int main(int argc, char *argv[]) { last_t = now; if (!use_texture) { - draw_grid(window_size); + draw_board(&game, window_size); } draw_timer(&game.timer); + if (timer_ended(&game.help_timer)) { + timer_stop(&game.help_timer); + game.should_draw_help = false; + } + + if (game.should_draw_help) { + draw_help(&game.help_timer); + } + if (game.has_won) { draw_win(&game); } @@ -222,14 +231,6 @@ int main(int argc, char *argv[]) { /* /1* draw_text_at(font_shader, text, text_pos, text_scale, font_vao, font_vbo, (float *)projection.m, &text_color); *1/ */ /* /1* } *1/ */ - /* if (timer_ended(&game.help_timer)) { */ - /* timer_stop(&game.help_timer); */ - /* game.should_draw_help = false; */ - /* } */ - - /* /1* if (game.should_draw_help) *1/ */ - /* /1* draw_help_overlay(selection_shader, font_shader, selection_vao, selection_vbo, font_vao, font_vbo, &projection, height, &game.help_timer); *1/ */ - /* /1* glXSwapBuffers(display, window); *1/ */ /* } */ diff --git a/shaders/font.frag b/shaders/font.frag index a96f0d8..9140f1a 100644 --- a/shaders/font.frag +++ b/shaders/font.frag @@ -1,9 +1,9 @@ #version 330 core in vec2 v_TexCoords; +in vec4 textColor; out vec4 FragColor; uniform sampler2D text; -uniform vec4 textColor; const float smoothness = 0.05; const float outlineDistance = 0.50; diff --git a/shaders/font.vert b/shaders/font.vert index 9d69682..004d09b 100644 --- a/shaders/font.vert +++ b/shaders/font.vert @@ -4,9 +4,11 @@ layout (location = 0) in vec2 vertex; // per instance layout (location = 1) in vec4 offset; layout (location = 2) in int tex_index; -layout (location = 3) in mat4 model; // this takes locations 3,4,5,6 +layout (location = 3) in vec4 color; +layout (location = 4) in mat4 model; // this takes locations 4,5,6,7 out vec2 v_TexCoords; +out vec4 textColor; uniform mat4 projection; // buffer for all the 96 ascii characters' texcoords uniform vec2 texcoords[96 * 4]; @@ -15,4 +17,5 @@ void main() { vec2 pos = vec2((vertex.x) * offset.z, (vertex.y) * offset.w); gl_Position = projection * model * vec4(pos + offset.xy, 0.0, 1.0); v_TexCoords = texcoords[tex_index * 4 + gl_VertexID]; + textColor = color; } diff --git a/ui.c b/ui.c index 22e4870..cb96c53 100644 --- a/ui.c +++ b/ui.c @@ -13,12 +13,12 @@ #include "ui.h" #include "x11.h" -#define FONT_PIXEL_SIZE 128 +#define FONT_PIXEL_SIZE 64 Display *display; Window window; -Context zephr_context; +Context zephr_context = {0}; Shader font_shader; Shader ui_shader; unsigned int font_vao; @@ -215,7 +215,7 @@ int init_ui(const char* font_path, Size window_size) { // font quad vbo glBindBuffer(GL_ARRAY_BUFFER, font_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 2, quad_vertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); @@ -228,17 +228,20 @@ int init_ui(const char* font_path, Size window_size) { glVertexAttribIPointer(2, 1, GL_INT, sizeof(TextInstance), (void *)sizeof(Vec4f)); glVertexAttribDivisor(2, 1); glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) + sizeof(int))); + glVertexAttribDivisor(3, 1); glEnableVertexAttribArray(4); glEnableVertexAttribArray(5); glEnableVertexAttribArray(6); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) + sizeof(int))); + glEnableVertexAttribArray(7); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 2 + sizeof(int))); glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 3 + sizeof(int))); glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 4 + sizeof(int))); - glVertexAttribDivisor(3, 1); + glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, sizeof(TextInstance), (void *)(sizeof(Vec4f) * 5 + sizeof(int))); glVertexAttribDivisor(4, 1); glVertexAttribDivisor(5, 1); glVertexAttribDivisor(6, 1); + glVertexAttribDivisor(7, 1); // font ebo glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_ebo); @@ -356,6 +359,11 @@ bool zephr_should_quit() { /* This MUST be called at the end of the frame if you wish to draw text */ void zephr_batch_text_draw() { + use_shader(font_shader); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, zephr_context.font.atlas_texture_id); + glBindVertexArray(font_vao); + glBindBuffer(GL_ARRAY_BUFFER, font_instance_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(TextInstance) * zephr_context.texts.size, zephr_context.texts.data, GL_DYNAMIC_DRAW); @@ -527,7 +535,7 @@ void apply_alignment(Alignment align, Vec2f *pos, Sizef size) { } } -void draw_quad(UIConstraints constraints, Color *color, float border_radius, Alignment align) { +void draw_quad(UIConstraints constraints, const Color *color, float border_radius, Alignment align) { use_shader(ui_shader); if (color) { @@ -579,7 +587,7 @@ void draw_quad(UIConstraints constraints, Color *color, float border_radius, Ali glBindVertexArray(0); } -void draw_circle(UIConstraints constraints, Color *color, Alignment align) { +void draw_circle(UIConstraints constraints, const Color *color, Alignment align) { float radius = 0.f; if (constraints.width > constraints.height) { @@ -590,7 +598,7 @@ void draw_circle(UIConstraints constraints, Color *color, Alignment align) { draw_quad(constraints, color, radius, align); } -void draw_triangle(UIConstraints constraints, Color *color, Alignment align) { +void draw_triangle(UIConstraints constraints, const Color *color, Alignment align) { use_shader(ui_shader); if (color) { @@ -632,12 +640,11 @@ void draw_triangle(UIConstraints constraints, Color *color, Alignment align) { glBindVertexArray(0); } -void draw_text(const char* text, int font_size, UIConstraints constraints, Color *color, Alignment alignment) { +void draw_text(const char* text, int font_size, UIConstraints constraints, const Color *color, Alignment alignment) { use_shader(font_shader); + Color text_color = { 0 }; if (color) { - set_vec4f(font_shader, "textColor", color->r / 255.f, color->g / 255.f, color->b / 255.f, color->a / 255.f); - } else { - set_vec4f(font_shader, "textColor", 0.f, 0.f, 0.f, 1.f); + text_color = (Color){ color->r / 255.f, color->g / 255.f, color->b / 255.f, color->a / 255.f }; } set_mat4f(font_shader, "projection", (float *)zephr_context.projection.m); @@ -654,6 +661,7 @@ void draw_text(const char* text, int font_size, UIConstraints constraints, Color Matrix4x4 model = identity(); apply_scale(&model, (Sizef){font_scale, font_scale}); + // rotate around the center point of the text apply_translation(&model, (Vec2f){-text_size.width * font_scale / 2.f, -text_size.height * font_scale / 2.f}); apply_rotation(&model, to_radians(constraints.rotation)); apply_translation(&model, (Vec2f){text_size.width *font_scale / 2.f, text_size.height * font_scale / 2.f}); @@ -668,10 +676,6 @@ void draw_text(const char* text, int font_size, UIConstraints constraints, Color float first_char_bearing_w = zephr_context.font.characters[(int)text[0]].bearing.width; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, zephr_context.font.atlas_texture_id); - glBindVertexArray(font_vao); - // we use the original text and character sizes in the loop and then we just // scale up or down the model matrix to get the desired font size. // this way everything works out fine and we get to transform the text using the @@ -688,8 +692,10 @@ void draw_text(const char* text, int font_size, UIConstraints constraints, Color TextInstance instance = { .position = (Vec4f){xpos, ypos, ch.size.width, ch.size.height}, .tex_coords_index = (int)text[c] - 32, + .color = text_color, .model = {0}, }; + memcpy(instance.model, model.m, sizeof(float[4][4])); add_text_instance(&zephr_context.texts, instance); diff --git a/ui.h b/ui.h index 6882baa..f0aab3f 100644 --- a/ui.h +++ b/ui.h @@ -20,6 +20,7 @@ typedef struct ZephFont { typedef struct TextInstance { Vec4f position; int tex_coords_index; + Color color; float model[4][4]; } TextInstance; @@ -79,8 +80,8 @@ void set_y_constraint(UIConstraints *constraints, float value, UIConstraint type void set_width_constraint(UIConstraints *constraints, float value, UIConstraint type); void set_height_constraint(UIConstraints *constraints, float value, UIConstraint type); void set_rotation_constraint(UIConstraints *constraints, float angle_d); -void draw_quad(UIConstraints constraints, Color *color, float border_radius, Alignment align); -void draw_circle(UIConstraints constraints, Color *color, Alignment align); -void draw_triangle(UIConstraints constraints, Color *color, Alignment align); -void draw_text(const char* text, int font_size, UIConstraints constraints, Color *color, Alignment align); +void draw_quad(UIConstraints constraints, const Color *color, float border_radius, Alignment align); +void draw_circle(UIConstraints constraints, const Color *color, Alignment align); +void draw_triangle(UIConstraints constraints, const Color *color, Alignment align); +void draw_text(const char* text, int font_size, UIConstraints constraints, const Color *color, Alignment align); Sizef calculate_text_size(const char *text, int font_size); diff --git a/z_math.h b/z_math.h index f93e128..901891d 100644 --- a/z_math.h +++ b/z_math.h @@ -31,7 +31,6 @@ typedef struct Vec4f { float w; } Vec4f; - typedef struct Color { float r; float g;