From d59a59ac8b98841abaee8b9bf8af1c7962cabfac Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 30 Sep 2021 16:38:57 +0200 Subject: [PATCH] Add status message --- .gitmodules | 3 ++ deps/dragonport | 1 + src/CMakeLists.txt | 1 + src/client/debug_menu.c | 72 +++++++++++------------------------------ src/client/game.c | 6 ++-- src/client/game.h | 2 +- src/client/gui.c | 23 ++++++------- src/client/gui.h | 2 +- src/client/input.c | 42 ++++++++++++++++++++++-- src/client/input.h | 4 ++- src/util.c | 19 ++++++----- src/util.h | 2 +- 12 files changed, 96 insertions(+), 81 deletions(-) create mode 160000 deps/dragonport diff --git a/.gitmodules b/.gitmodules index cb21f4a..9722994 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "deps/endian.h"] path = deps/endian.h url = https://github.com/mikepb/endian.h +[submodule "deps/dragonport"] + path = deps/dragonport + url = https://github.com/dragonblocks/dragonport diff --git a/deps/dragonport b/deps/dragonport new file mode 160000 index 0000000..a6c5dd9 --- /dev/null +++ b/deps/dragonport @@ -0,0 +1 @@ +Subproject commit a6c5dd9faf12ac38b1868c7ad742947a7dbeb905 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 52745dd..242e83d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,7 @@ set(SOURCES_COMMON signal_handlers.c util.c "${DEPS_DIR}/dragontype/implementation.c" + "${DEPS_DIR}/dragonport/asprintf.c" "${DEPS_DIR}/perlin/perlin.c" ) diff --git a/src/client/debug_menu.c b/src/client/debug_menu.c index 5900256..352222f 100644 --- a/src/client/debug_menu.c +++ b/src/client/debug_menu.c @@ -8,6 +8,7 @@ #include "day.h" #include "environment.h" #include "perlin.h" +#include "util.h" #include "version.h" typedef enum @@ -51,7 +52,7 @@ void debug_menu_init() .scale = {1.0f, 1.0f}, .scale_type = GST_TEXT, .affect_parent_scale = false, - .text = "", + .text = strdup(""), .image = NULL, .text_color = (v4f32) {1.0f, 1.0f, 1.0f, 1.0f}, .bg_color = (v4f32) {0.0f, 0.0f, 0.0f, 0.0f}, @@ -71,122 +72,87 @@ void debug_menu_toggle() void debug_menu_update_version() { - char text[BUFSIZ]; - sprintf(text, "Dragonblocks Alpha %s", VERSION); - gui_set_text(gui_elements[DME_VERSION], text); + gui_set_text(gui_elements[DME_VERSION], format_string("Dragonblocks Alpha %s", VERSION)); } void debug_menu_update_fps(int fps) { - char text[BUFSIZ]; - sprintf(text, "%d FPS", fps); - gui_set_text(gui_elements[DME_FPS], text); + gui_set_text(gui_elements[DME_FPS], format_string("%d FPS", fps)); } void debug_menu_update_pos() { - char text[BUFSIZ]; - sprintf(text, "(%.1f %.1f %.1f)", client_player.pos.x, client_player.pos.y, client_player.pos.z); - gui_set_text(gui_elements[DME_POS], text); + gui_set_text(gui_elements[DME_POS], format_string("(%.1f %.1f %.1f)", client_player.pos.x, client_player.pos.y, client_player.pos.z)); } void debug_menu_update_yaw() { - char text[BUFSIZ]; - sprintf(text, "yaw = %.1f", client_player.yaw / M_PI * 180.0); - gui_set_text(gui_elements[DME_YAW], text); + gui_set_text(gui_elements[DME_YAW], format_string("yaw = %.1f", client_player.yaw / M_PI * 180.0)); } void debug_menu_update_pitch() { - char text[BUFSIZ]; - sprintf(text, "pitch = %.1f", client_player.pitch / M_PI * 180.0); - gui_set_text(gui_elements[DME_PITCH], text); + gui_set_text(gui_elements[DME_PITCH], format_string("pitch = %.1f", client_player.pitch / M_PI * 180.0)); } void debug_menu_update_time() { int hours, minutes; split_time_of_day(&hours, &minutes); - - char text[BUFSIZ]; - sprintf(text, "%02d:%02d", hours, minutes); - gui_set_text(gui_elements[DME_TIME], text); + gui_set_text(gui_elements[DME_TIME], format_string("%02d:%02d", hours, minutes)); } void debug_menu_update_daylight() { - char text[BUFSIZ]; - sprintf(text, "daylight = %.2f", get_daylight()); - gui_set_text(gui_elements[DME_DAYLIGHT], text); + gui_set_text(gui_elements[DME_DAYLIGHT], format_string("daylight = %.2f", get_daylight())); } void debug_menu_update_sun_angle() { - char text[BUFSIZ]; - sprintf(text, "sun angle = %.1f", fmod(get_sun_angle() / M_PI * 180.0, 360.0)); - gui_set_text(gui_elements[DME_SUN_ANGLE], text); + gui_set_text(gui_elements[DME_SUN_ANGLE], format_string("sun angle = %.1f", fmod(get_sun_angle() / M_PI * 180.0, 360.0))); } void debug_menu_update_humidity() { - char text[BUFSIZ]; - sprintf(text, "humidity = %.2f", get_humidity((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z})); - gui_set_text(gui_elements[DME_HUMIDITY], text); + gui_set_text(gui_elements[DME_HUMIDITY], format_string("humidity = %.2f", get_humidity((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z}))); } void debug_menu_update_temperature() { - char text[BUFSIZ]; - sprintf(text, "temperature = %.2f", get_temperature((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z})); - gui_set_text(gui_elements[DME_TEMPERATURE], text); + gui_set_text(gui_elements[DME_TEMPERATURE], format_string("temperature = %.2f", get_temperature((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z}))); } void debug_menu_update_seed() { - char text[BUFSIZ]; - sprintf(text, "seed = %d", seed); - gui_set_text(gui_elements[DME_SEED], text); + gui_set_text(gui_elements[DME_SEED], format_string("seed = %d", seed)); } void debug_menu_update_flight() { - char text[BUFSIZ]; - sprintf(text, "flight: %s", client_player.fly ? "enabled" : "disabled"); - gui_set_text(gui_elements[DME_FLIGHT], text); + gui_set_text(gui_elements[DME_FLIGHT], format_string("flight: %s", client_player.fly ? "enabled" : "disabled")); } void debug_menu_update_collision() { - char text[BUFSIZ]; - sprintf(text, "collision: %s", client_player.collision ? "enabled" : "disabled"); - gui_set_text(gui_elements[DME_COLLISION], text); + gui_set_text(gui_elements[DME_COLLISION], format_string("collision: %s", client_player.collision ? "enabled" : "disabled")); } void debug_menu_update_timelapse() { - char text[BUFSIZ]; - sprintf(text, "timelapse: %s", timelapse ? "enabled" : "disabled"); - gui_set_text(gui_elements[DME_TIMELAPSE], text); + gui_set_text(gui_elements[DME_TIMELAPSE], format_string("timelapse: %s", timelapse ? "enabled" : "disabled")); } void debug_menu_update_fullscreen() { - char text[BUFSIZ]; - sprintf(text, "fullscreen: %s", window.fullscreen ? "enabled" : "disabled"); - gui_set_text(gui_elements[DME_FULLSCREEN], text); + gui_set_text(gui_elements[DME_FULLSCREEN], format_string("fullscreen: %s", window.fullscreen ? "enabled" : "disabled")); } void debug_menu_update_opengl() { - char text[BUFSIZ]; - sprintf(text, "OpenGL %s", glGetString(GL_VERSION)); - gui_set_text(gui_elements[DME_OPENGL], text); + gui_set_text(gui_elements[DME_OPENGL], format_string("OpenGL %s", glGetString(GL_VERSION))); } void debug_menu_update_gpu() { - char text[BUFSIZ]; - sprintf(text, "%s", glGetString(GL_RENDERER)); - gui_set_text(gui_elements[DME_GPU], text); + gui_set_text(gui_elements[DME_GPU], format_string("%s", glGetString(GL_RENDERER))); } diff --git a/src/client/game.c b/src/client/game.c index 0564dbf..62c33dd 100644 --- a/src/client/game.c +++ b/src/client/game.c @@ -83,7 +83,7 @@ static void game_loop(Client *client) frames++; - input_tick(); + input_tick(dtime); client_player_tick(dtime); debug_menu_update_time(); @@ -157,7 +157,7 @@ bool game(Client *client) return true; } -void take_screenshot() +char *take_screenshot() { // renderbuffer for depth & stencil buffer GLuint RBO; @@ -217,6 +217,8 @@ void take_screenshot() glDeleteRenderbuffers(1, &RBO); glDeleteTextures(2, textures); glDeleteFramebuffers(2, FBOs); + + return strdup(filename); } void game_on_resize(int width, int height) diff --git a/src/client/game.h b/src/client/game.h index 9941264..d28a4c5 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -4,7 +4,7 @@ #include "client/client.h" bool game(Client *client); -void take_screenshot(); +char *take_screenshot(); void game_on_resize(int width, int height); #endif diff --git a/src/client/gui.c b/src/client/gui.c index 76ca68f..86f8547 100644 --- a/src/client/gui.c +++ b/src/client/gui.c @@ -286,6 +286,8 @@ GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def) if (element->def.text) { element->def.text = strdup(element->def.text); element->text = font_create(element->def.text); + } else { + element->text = NULL; } bintree_insert(&parent->children, &element->def.z_index, element); @@ -300,14 +302,15 @@ GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def) return element; } -void gui_set_text(GUIElement *element, const char *text) +void gui_set_text(GUIElement *element, char *text) { - if (! element->def.text || strcmp(element->def.text, text)) { - element->def.text = strdup(text); - font_delete(element->text); - element->text = font_create(text); - gui_update_transform(element); - } + if (element->def.text) + free(element->def.text); + + element->def.text = text; + font_delete(element->text); + element->text = font_create(text); + gui_update_transform(element); } // transform code @@ -334,13 +337,11 @@ static void calculate_element_scale(GUIElement *element) switch (element->def.scale_type) { case GST_IMAGE: - assert(element->def.image); element->scale.x *= element->def.image->width; element->scale.y *= element->def.image->height; break; case GST_TEXT: - assert(element->text); element->scale.x *= element->text->size.x; element->scale.y *= element->text->size.y; break; @@ -405,8 +406,8 @@ static void list_calculate_element_scale(void *key, unused void *value, unused v static void calculate_element_transform(GUIElement *element) { element->pos = (v2f32) { - element->parent->pos.x + element->def.offset.x + element->def.pos.x * element->parent->scale.x - element->def.align.x * element->scale.x, - element->parent->pos.y + element->def.offset.y + element->def.pos.y * element->parent->scale.y - element->def.align.y * element->scale.y, + floor(element->parent->pos.x + element->def.offset.x + element->def.pos.x * element->parent->scale.x - element->def.align.x * element->scale.x), + floor(element->parent->pos.y + element->def.offset.y + element->def.pos.y * element->parent->scale.y - element->def.align.y * element->scale.y), }; mat4x4_translate(element->transform, element->pos.x - element->def.margin.x, element->pos.y - element->def.margin.y, 0.0f); diff --git a/src/client/gui.h b/src/client/gui.h index 44b6c65..b48d210 100644 --- a/src/client/gui.h +++ b/src/client/gui.h @@ -52,7 +52,7 @@ void gui_deinit(); void gui_on_resize(int width, int height); void gui_render(); GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def); -void gui_set_text(GUIElement *element, const char *text); +void gui_set_text(GUIElement *element, char *text); void gui_update_transform(GUIElement *element); extern GUIElement gui_root; diff --git a/src/client/input.c b/src/client/input.c index 687d6f3..c59c541 100644 --- a/src/client/input.c +++ b/src/client/input.c @@ -1,4 +1,6 @@ #include +#include +#include #include "client/camera.h" #include "client/client.h" #include "client/client_player.h" @@ -8,6 +10,7 @@ #include "client/input.h" #include "client/window.h" #include "day.h" +#include "util.h" typedef struct { @@ -19,6 +22,7 @@ typedef struct static struct { GUIElement *pause_menu; + GUIElement *status_message; bool paused; KeyListener pause_listener; KeyListener fullscreen_listener; @@ -94,8 +98,19 @@ static KeyListener create_key_listener(int key) }; } -void input_tick() +static void set_status_message(char *message) { + gui_set_text(input.status_message, message); + input.status_message->def.text_color.w = 2.0f; +} + +void input_tick(f64 dtime) +{ + if (input.status_message->def.text_color.w > 1.0f) + input.status_message->def.text_color.w -= dtime * 1.0f; + else if (input.status_message->def.text_color.w > 0.0f) + input.status_message->def.text_color.w -= dtime * 1.0f; + do_key_listener(&input.pause_listener); do_key_listener(&input.fullscreen_listener); @@ -127,11 +142,13 @@ void input_tick() if (input.fly_listener.fired) { client_player.fly = ! client_player.fly; debug_menu_update_flight(); + set_status_message(format_string("Flight %s", client_player.fly ? "Enabled" : "Disabled")); } if (input.collision_listener.fired) { client_player.collision = ! client_player.collision; debug_menu_update_collision(); + set_status_message(format_string("Collision %s", client_player.collision ? "Enabled" : "Disabled")); } if (input.timelapse_listener.fired) { @@ -139,13 +156,17 @@ void input_tick() timelapse = ! timelapse; set_time_of_day(current_time); debug_menu_update_timelapse(); + set_status_message(format_string("Timelapse %s", timelapse ? "Enabled" : "Disabled")); } if (input.debug_menu_listener.fired) debug_menu_toggle(); - if (input.screenshot_listener.fired) - take_screenshot(); + if (input.screenshot_listener.fired) { + char *screenshot_filename = take_screenshot(); + set_status_message(format_string("Screenshot saved to %s", screenshot_filename)); + free(screenshot_filename); + } } client_player.velocity.x = 0.0f; @@ -192,6 +213,21 @@ void input_init() .bg_color = {0.0f, 0.0f, 0.0f, 0.4f}, }); + input.status_message = gui_add(&gui_root, (GUIElementDefinition) { + .pos = {0.5f, 0.25f}, + .z_index = 0.1f, + .offset = {0, 0}, + .margin = {0, 0}, + .align = {0.5f, 0.5f}, + .scale = {1.0f, 1.0f}, + .scale_type = GST_TEXT, + .affect_parent_scale = false, + .text = strdup(""), + .image = NULL, + .text_color = {1.0f, 0.91f, 0.13f, 0.0f}, + .bg_color = {0.0f, 0.0f, 0.0f, 0.0f}, + }); + glfwSetInputMode(window.handle, GLFW_STICKY_KEYS, GL_TRUE); enter_game(); diff --git a/src/client/input.h b/src/client/input.h index 97f7e9f..3789050 100644 --- a/src/client/input.h +++ b/src/client/input.h @@ -1,7 +1,9 @@ #ifndef _INPUT_H_ #define _INPUT_H_ -void input_tick(); +#include + +void input_tick(f64 dtime); void input_init(); void input_on_cursor_pos(double current_x, double current_y); diff --git a/src/util.c b/src/util.c index 464529b..c1c1c2d 100644 --- a/src/util.c +++ b/src/util.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "map.h" #include "util.h" @@ -57,14 +58,6 @@ char *address_string(struct sockaddr_in6 *addr) return result; } -// convert #RRGGBB color to v3f32 -v3f32 html_to_v3f32(const char *html) -{ - unsigned int r, g, b; - sscanf(html, "#%2x%2x%2x", &r, &g, &b); - return (v3f32) {(f32) r / 255.0f, (f32) g / 255.0f, (f32) b / 255.0f}; -} - // compress data using ZLib and store result(buffer allocated by malloc) in compressed void my_compress(const void *uncompressed, size_t uncompressed_size, char **compressed, size_t *compressed_size) { @@ -119,3 +112,13 @@ f64 clamp(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; } + +char *format_string(const char *format, ...) +{ + va_list args; + va_start(args, format); + char *ptr; + vasprintf(&ptr, format, args); + va_end(args); + return ptr; +} diff --git a/src/util.h b/src/util.h index 25623de..ddcec81 100644 --- a/src/util.h +++ b/src/util.h @@ -23,10 +23,10 @@ void syscall_error(const char *err); // print system call r void internal_error(const char *err); // print general error message and exit char *read_string(int fd, size_t bufsiz); // read from fd until \0 or EOF terminator char *address_string(struct sockaddr_in6 *addr); // convert IPv6 address to human readable, return allocated buffer -v3f32 html_to_v3f32(const char *html); // convert #RRGGBB color to v3f32 void my_compress(const void *uncompressed, size_t uncompressed_size, char **compressed, size_t *compressed_size); // compress data using ZLib and store result(buffer allocated by malloc) in compressed bool my_decompress(const char *compressed, size_t compressed_size, void *decompressed, size_t expected_decompressed_size); // decompress data and put result into decompressed, return false if decompressed size does not match expected_decompressed_size bool within_simulation_distance(v3f64 player_pos, v3s32 block_pos, u32 simulation_distance); // return true if a player is close enough to a block to access it f64 clamp(f64 v, f64 min, f64 max); +char *format_string(const char *format, ...); #endif -- 2.44.0