From 7dd18aaa2ac54351b217862ca11bf84e650ff98c Mon Sep 17 00:00:00 2001 From: MysterD Date: Tue, 15 Feb 2022 22:08:01 -0800 Subject: [PATCH] Added text rendering to Lua API --- autogen/convert_constants.py | 3 +- autogen/convert_functions.py | 2 + docs/lua/functions.md | 159 +++++++++++++++++++++++++++ src/pc/djui/djui.c | 4 + src/pc/djui/djui_font.c | 66 +++++++++++ src/pc/djui/djui_gfx_utils.c | 140 +++++++++++++++++++++++ src/pc/djui/djui_gfx_utils.h | 27 +++++ src/pc/lua/smlua_functions_autogen.c | 99 +++++++++++++++++ src/pc/lua/smlua_hooks.h | 2 + 9 files changed, 501 insertions(+), 1 deletion(-) create mode 100644 src/pc/djui/djui_gfx_utils.c create mode 100644 src/pc/djui/djui_gfx_utils.h diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py index f036c9b2..b92b0b6d 100644 --- a/autogen/convert_constants.py +++ b/autogen/convert_constants.py @@ -17,6 +17,7 @@ in_files = [ "src/pc/network/network_player.h", "include/PR/os_cont.h", "src/game/interaction.c", + "src/pc/djui/djui_gfx_utils.h", ] exclude_constants = [ @@ -286,4 +287,4 @@ def main(): global totalConstants print("Total constants: " + str(totalConstants)) -main() \ No newline at end of file +main() diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 14f5464d..6e83bd7b 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -33,6 +33,7 @@ in_files = [ "src/game/level_info.h", "src/game/save_file.h", "src/game/sound_init.h", + "src/pc/djui/djui_gfx_utils.h", ] override_allowed_functions = { @@ -84,6 +85,7 @@ template = """/* THIS FILE IS AUTOGENERATED */ #include "src/game/level_info.h" #include "src/game/save_file.h" #include "src/game/sound_init.h" +#include "src/pc/djui/djui_gfx_utils.h" $[FUNCTIONS] diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 0cfc3eb8..fd58d577 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -26,6 +26,17 @@
+- djui_gfx_utils.h + - [djui_gfx_get_screen_height](#djui_gfx_get_screen_height) + - [djui_gfx_get_screen_width](#djui_gfx_get_screen_width) + - [djui_gfx_measure_text](#djui_gfx_measure_text) + - [djui_gfx_print_text](#djui_gfx_print_text) + - [djui_gfx_set_color](#djui_gfx_set_color) + - [djui_gfx_set_font](#djui_gfx_set_font) + - [djui_gfx_set_resolution](#djui_gfx_set_resolution) + +
+ - djui_popup.h - [djui_popup_create](#djui_popup_create) @@ -611,6 +622,154 @@
+--- +# functions from djui_gfx_utils.h + +
+ + +## [djui_gfx_get_screen_height](#djui_gfx_get_screen_height) + +### Lua Example +`local integerValue = djui_gfx_get_screen_height()` + +### Parameters +- None + +### Returns +- integer + +### C Prototype +`u32 djui_gfx_get_screen_height(void);` + +[:arrow_up_small:](#) + +
+ +## [djui_gfx_get_screen_width](#djui_gfx_get_screen_width) + +### Lua Example +`local integerValue = djui_gfx_get_screen_width()` + +### Parameters +- None + +### Returns +- integer + +### C Prototype +`u32 djui_gfx_get_screen_width(void);` + +[:arrow_up_small:](#) + +
+ +## [djui_gfx_measure_text](#djui_gfx_measure_text) + +### Lua Example +`local numberValue = djui_gfx_measure_text(message)` + +### Parameters +| Field | Type | +| ----- | ---- | +| message | string | + +### Returns +- number + +### C Prototype +`f32 djui_gfx_measure_text(const char* message);` + +[:arrow_up_small:](#) + +
+ +## [djui_gfx_print_text](#djui_gfx_print_text) + +### Lua Example +`djui_gfx_print_text(message, x, y, scale)` + +### Parameters +| Field | Type | +| ----- | ---- | +| message | string | +| x | float | +| y | float | +| scale | float | + +### Returns +- None + +### C Prototype +`void djui_gfx_print_text(const char* message, float x, float y, float scale);` + +[:arrow_up_small:](#) + +
+ +## [djui_gfx_set_color](#djui_gfx_set_color) + +### Lua Example +`djui_gfx_set_color(r, g, b, a)` + +### Parameters +| Field | Type | +| ----- | ---- | +| r | integer | +| g | integer | +| b | integer | +| a | integer | + +### Returns +- None + +### C Prototype +`void djui_gfx_set_color(u8 r, u8 g, u8 b, u8 a);` + +[:arrow_up_small:](#) + +
+ +## [djui_gfx_set_font](#djui_gfx_set_font) + +### Lua Example +`djui_gfx_set_font(fontType)` + +### Parameters +| Field | Type | +| ----- | ---- | +| fontType | integer | + +### Returns +- None + +### C Prototype +`void djui_gfx_set_font(enum DjuiFontType fontType);` + +[:arrow_up_small:](#) + +
+ +## [djui_gfx_set_resolution](#djui_gfx_set_resolution) + +### Lua Example +`djui_gfx_set_resolution(resolutionType)` + +### Parameters +| Field | Type | +| ----- | ---- | +| resolutionType | integer | + +### Returns +- None + +### C Prototype +`void djui_gfx_set_resolution(enum GfxUtilsResolution resolutionType);` + +[:arrow_up_small:](#) + +
+ --- # functions from djui_popup.h diff --git a/src/pc/djui/djui.c b/src/pc/djui/djui.c index 15ed389c..79dcb5a1 100644 --- a/src/pc/djui/djui.c +++ b/src/pc/djui/djui.c @@ -2,7 +2,9 @@ #include "../debuglog.h" #include "pc/cliopts.h" #include "game/level_update.h" +#include "pc/lua/smlua_hooks.h" #include "djui_panel_playerlist.h" +#include "djui_gfx_utils.h" static Gfx* sSavedDisplayListHead = NULL; @@ -53,6 +55,8 @@ void djui_render(void) { sSavedDisplayListHead = gDisplayListHead; create_dl_ortho_matrix(); + smlua_call_event_hooks(HOOK_ON_HUD_RENDER); + djui_panel_update(); djui_popup_update(); diff --git a/src/pc/djui/djui_font.c b/src/pc/djui/djui_font.c index cbeab3b0..b0bbb68c 100644 --- a/src/pc/djui/djui_font.c +++ b/src/pc/djui/djui_font.c @@ -92,6 +92,71 @@ static const struct DjuiFont sDjuiFontTitle = { .char_width = djui_font_title_char_width, }; + /////////////////////// + // font 3 (hud font) // +/////////////////////// + +/* + texture_hud_char_0, texture_hud_char_1, texture_hud_char_2, texture_hud_char_3, + texture_hud_char_4, texture_hud_char_5, texture_hud_char_6, texture_hud_char_7, + texture_hud_char_8, texture_hud_char_9, texture_hud_char_A, texture_hud_char_B, + texture_hud_char_C, texture_hud_char_D, texture_hud_char_E, texture_hud_char_F, + texture_hud_char_G, texture_hud_char_H, texture_hud_char_I, texture_hud_char_J, + texture_hud_char_K, texture_hud_char_L, texture_hud_char_M, texture_hud_char_N, + texture_hud_char_O, texture_hud_char_P, 0x0, texture_hud_char_R, + texture_hud_char_S, texture_hud_char_T, texture_hud_char_U, 0x0, + texture_hud_char_W, 0x0, texture_hud_char_Y, texture_hud_char_waluigi_head, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, texture_hud_char_multiply, texture_hud_char_coin, + texture_hud_char_mario_head, texture_hud_char_star, texture_hud_char_luigi_head, texture_hud_char_toad_head, + texture_hud_char_apostrophe, texture_hud_char_double_quote, +*/ + +static u8 djui_font_hud_index(char c) { + if (c == 'q' || c == 'Q') { return 50; } + if (c == 'v' || c == 'V') { return 50; } + if (c == 'x' || c == 'X') { return 50; } + if (c == 'z' || c == 'Z') { return 50; } + + switch (c) { + case '$': return 51; + case '*': return 53; + case '\'': return 56; + case '"': return 57; + } + + if (c >= '0' && c <= '9') { return 0 + c - '0'; } + if (c >= 'a' && c <= 'z') { return 10 + c - 'a'; } + if (c >= 'A' && c <= 'Z') { return 10 + c - 'A'; } + + if (c >= 58) { return 50; } + if (main_hud_lut[(int)c] == NULL) { return 50; } + + return c; +} + +static void djui_font_hud_render_char(char c) { + u8 index = djui_font_hud_index(c); + djui_gfx_render_texture(main_hud_lut[index], 16, 16, 16); +} + +static f32 djui_font_hud_char_width(UNUSED char c) { + return 0.75f; +} + +static const struct DjuiFont sDjuiFontHud = { + .charWidth = 1.0f, + .charHeight = 0.9f, + .lineHeight = 0.7f, + .defaultFontScale = 16.0f, + .rotatedUV = false, + .textBeginDisplayList = NULL, + .render_char = djui_font_hud_render_char, + .char_width = djui_font_hud_char_width, +}; + /////////////// // font list // /////////////// @@ -99,4 +164,5 @@ static const struct DjuiFont sDjuiFontTitle = { const struct DjuiFont* gDjuiFonts[] = { &sDjuiFontNormal, &sDjuiFontTitle, + &sDjuiFontHud, }; \ No newline at end of file diff --git a/src/pc/djui/djui_gfx_utils.c b/src/pc/djui/djui_gfx_utils.c new file mode 100644 index 00000000..f3a3b6f6 --- /dev/null +++ b/src/pc/djui/djui_gfx_utils.c @@ -0,0 +1,140 @@ +#include +#include +#include + +#include "pc/gfx/gfx_pc.h" +#include "pc/gfx/gfx_window_manager_api.h" +#include "pc/pc_main.h" + +#include "gfx_dimensions.h" +#include "config.h" +#include "djui.h" +#include "djui_gfx_utils.h" + +static enum GfxUtilsResolution sResolution = RESOLUTION_DJUI; +static enum DjuiFontType sFont = FONT_NORMAL; + +void djui_gfx_set_resolution(enum GfxUtilsResolution resolutionType) { + if (resolutionType >= RESOLUTION_COUNT) { return; } + sResolution = resolutionType; +} + +void djui_gfx_set_font(enum DjuiFontType fontType) { + if (fontType >= FONT_COUNT) { return; } + sFont = fontType; +} + +void djui_gfx_set_color(u8 r, u8 g, u8 b, u8 a) { + gDPSetEnvColor(gDisplayListHead++, r, g, b, a); +} + +u32 djui_gfx_get_screen_width(void) { + u32 windowWidth, windowHeight; + wm_api->get_dimensions(&windowWidth, &windowHeight); + + return (sResolution == RESOLUTION_N64) + ? (GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT) + : (windowWidth / djui_gfx_get_scale()); +} + +u32 djui_gfx_get_screen_height(void) { + u32 windowWidth, windowHeight; + wm_api->get_dimensions(&windowWidth, &windowHeight); + + return (sResolution == RESOLUTION_N64) + ? SCREEN_HEIGHT + : (windowHeight / djui_gfx_get_scale()); +} + +f32 djui_gfx_measure_text(const char* message) { + if (message == NULL) { return 0; } + const struct DjuiFont* font = gDjuiFonts[sFont]; + f32 width = 0; + const char* c = message; + while(*c != '\0') { + width += font->char_width(*c); + c++; + } + return width * font->defaultFontScale; +} + +void djui_gfx_print_text(const char* message, float x, float y, float scale) { + if (message == NULL) { return; } + const struct DjuiFont* font = gDjuiFonts[sFont]; + f32 fontScale = font->defaultFontScale * scale; + + // setup display list + if (font->textBeginDisplayList != NULL) { + gSPDisplayList(gDisplayListHead++, font->textBeginDisplayList); + } + + // translate position + f32 translatedX = x; + f32 translatedY = y; + if (sResolution == RESOLUTION_DJUI) { + djui_gfx_position_translate(&translatedX, &translatedY); + } else if (sResolution == RESOLUTION_N64) { + translatedX = GFX_DIMENSIONS_FROM_LEFT_EDGE(0) + x; + translatedY = SCREEN_HEIGHT - y; + } + create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0); + + // compute font size + f32 translatedFontSize = fontScale; + if (sResolution == RESOLUTION_DJUI) { + djui_gfx_size_translate(&translatedFontSize); + } + create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSize, translatedFontSize, 1.0f); + + // render the line + f32 addX = 0; + size_t length = strlen(message); + for (size_t i = 0; i < length; i++) { + char c = message[i]; + f32 charWidth = font->char_width(c); + + if (c == '\n' && c == ' ') { + addX += charWidth; + continue; + } + + // render + font->render_char(c); + create_dl_translation_matrix(DJUI_MTX_NOPUSH, charWidth + addX, 0, 0); + addX = 0; + } + + // pop + gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); +} + +void djui_gfx_utils_render(void) { + //struct DjuiColor fore = { .r = 255, .g = 255, .b = 255, .a = 255 }; + //struct DjuiColor back = { .r = 0, .g = 0, .b = 0, .a = 255 }; + //const struct DjuiFont* font = gDjuiFonts[2]; + //djui_gfx_print_text(font, "abcdefghijklmnopqrstuvwxyz:1234567890", 2, 2, 2, back); + //djui_gfx_print_text(font, "1234567890:abcdefghijklmnopqrstuvwxyz", 0, 0, 2, fore); + //float scale = 240.0f / gfx_current_dimensions.height; + + /*{ + f32 screenWidth = djui_gfx_get_screen_width(RESOLUTION_N64); + f32 width = djui_gfx_measure_text(font, "PAUSE", RESOLUTION_N64); + + f32 screenHeight = djui_gfx_get_screen_height(RESOLUTION_N64); + f32 height = 16; + + djui_gfx_print_text(font, "PAUSE", screenWidth - width, screenHeight - height - 32, 1.0f, fore, RESOLUTION_N64); + djui_gfx_print_text(font, "PAUSE", screenWidth - width * 2, screenHeight - height, 1.0f, fore, RESOLUTION_N64); + }*/ + + /*{ + f32 screenWidth = djui_gfx_get_screen_width(RESOLUTION_DJUI); + f32 width = djui_gfx_measure_text(font, "PAUSE", RESOLUTION_DJUI); + + f32 screenHeight = djui_gfx_get_screen_height(RESOLUTION_DJUI); + f32 height = 16; + + djui_gfx_print_text(FONT_NORMAL, "PAUSE", screenWidth - width, screenHeight - height - 32, 1.0f, fore, RESOLUTION_DJUI); + djui_gfx_print_text(FONT_NORMAL, "PAUSE", screenWidth - width * 2, screenHeight - height, 1.0f, fore, RESOLUTION_DJUI); + }*/ +} \ No newline at end of file diff --git a/src/pc/djui/djui_gfx_utils.h b/src/pc/djui/djui_gfx_utils.h new file mode 100644 index 00000000..56e8cefc --- /dev/null +++ b/src/pc/djui/djui_gfx_utils.h @@ -0,0 +1,27 @@ +#ifndef DJUI_GFX_UTILS_H +#define DJUI_GFX_UTILS_H + +enum GfxUtilsResolution { + RESOLUTION_DJUI, + RESOLUTION_N64, + RESOLUTION_COUNT, +}; + +enum DjuiFontType { + FONT_NORMAL, + FONT_MENU, + FONT_HUD, + FONT_COUNT, +}; + +void djui_gfx_set_resolution(enum GfxUtilsResolution resolutionType); +void djui_gfx_set_font(enum DjuiFontType fontType); +void djui_gfx_set_color(u8 r, u8 g, u8 b, u8 a); + +u32 djui_gfx_get_screen_width(void); +u32 djui_gfx_get_screen_height(void); + +f32 djui_gfx_measure_text(const char* message); +void djui_gfx_print_text(const char* message, float x, float y, float scale); + +#endif \ No newline at end of file diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 4c9d439f..031877ea 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -19,6 +19,7 @@ #include "src/game/level_info.h" #include "src/game/save_file.h" #include "src/game/sound_init.h" +#include "src/pc/djui/djui_gfx_utils.h" ////////////// // camera.h // @@ -203,6 +204,95 @@ int smlua_func_djui_chat_message_create(lua_State* L) { return 1; } + ////////////////////// + // djui_gfx_utils.h // +////////////////////// + +int smlua_func_djui_gfx_get_screen_height(UNUSED lua_State* L) { + if(!smlua_functions_valid_param_count(L, 0)) { return 0; } + + + lua_pushinteger(L, djui_gfx_get_screen_height()); + + return 1; +} + +int smlua_func_djui_gfx_get_screen_width(UNUSED lua_State* L) { + if(!smlua_functions_valid_param_count(L, 0)) { return 0; } + + + lua_pushinteger(L, djui_gfx_get_screen_width()); + + return 1; +} + +int smlua_func_djui_gfx_measure_text(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + const char* message = smlua_to_string(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushnumber(L, djui_gfx_measure_text(message)); + + return 1; +} + +int smlua_func_djui_gfx_print_text(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 4)) { return 0; } + + const char* message = smlua_to_string(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + float x = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + float y = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + float scale = smlua_to_number(L, 4); + if (!gSmLuaConvertSuccess) { return 0; } + + djui_gfx_print_text(message, x, y, scale); + + return 1; +} + +int smlua_func_djui_gfx_set_color(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 4)) { return 0; } + + u8 r = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + u8 g = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u8 b = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + u8 a = smlua_to_integer(L, 4); + if (!gSmLuaConvertSuccess) { return 0; } + + djui_gfx_set_color(r, g, b, a); + + return 1; +} + +int smlua_func_djui_gfx_set_font(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + int fontType = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + + djui_gfx_set_font(fontType); + + return 1; +} + +int smlua_func_djui_gfx_set_resolution(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + int resolutionType = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { return 0; } + + djui_gfx_set_resolution(resolutionType); + + return 1; +} + ////////////////// // djui_popup.h // ////////////////// @@ -3406,6 +3496,15 @@ void smlua_bind_functions_autogen(void) { // djui_chat_message.h smlua_bind_function(L, "djui_chat_message_create", smlua_func_djui_chat_message_create); + // djui_gfx_utils.h + smlua_bind_function(L, "djui_gfx_get_screen_height", smlua_func_djui_gfx_get_screen_height); + smlua_bind_function(L, "djui_gfx_get_screen_width", smlua_func_djui_gfx_get_screen_width); + smlua_bind_function(L, "djui_gfx_measure_text", smlua_func_djui_gfx_measure_text); + smlua_bind_function(L, "djui_gfx_print_text", smlua_func_djui_gfx_print_text); + smlua_bind_function(L, "djui_gfx_set_color", smlua_func_djui_gfx_set_color); + smlua_bind_function(L, "djui_gfx_set_font", smlua_func_djui_gfx_set_font); + smlua_bind_function(L, "djui_gfx_set_resolution", smlua_func_djui_gfx_set_resolution); + // djui_popup.h smlua_bind_function(L, "djui_popup_create", smlua_func_djui_popup_create); diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index 87824e79..33f01543 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -12,6 +12,7 @@ enum LuaHookedEventType { HOOK_ON_PVP_ATTACK, HOOK_ON_PLAYER_CONNECTED, HOOK_ON_PLAYER_DISCONNECTED, + HOOK_ON_HUD_RENDER, HOOK_MAX, }; @@ -24,6 +25,7 @@ static char* LuaHookedEventTypeName[] = { "HOOK_ON_PVP_ATTACK", "HOOK_ON_PLAYER_CONNECTED", "HOOK_ON_PLAYER_DISCONNECTED", + "HOOK_ON_HUD_RENDER", "HOOK_MAX" };