From de25c5437b60f1cb52c49a2f14bf325ac5f47fdb Mon Sep 17 00:00:00 2001 From: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Sun, 5 Apr 2026 02:00:03 +0200 Subject: [PATCH] Make djui_hud_measure_text compute text height (#1177) - Change `djui_hud_measure_text` to return both text width and height - New syntax is: `local width, height = djui_hud_measure_text(text)` - Old syntax still works, but only returns `width` - Fix incorrect char height for some fonts - Fix nametags interpolation using the wrong scale --- autogen/lua_definitions/functions.lua | 5 +++-- docs/lua/functions-3.md | 7 ++++--- src/pc/djui/djui_font.c | 8 +++---- src/pc/djui/djui_hud_utils.c | 23 +++++++++++++------- src/pc/djui/djui_hud_utils.h | 4 ++-- src/pc/lua/smlua_functions_autogen.c | 10 +++++++-- src/pc/nametags.c | 30 ++++++++++++++++----------- 7 files changed, 54 insertions(+), 33 deletions(-) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 00d52fad7..564f56b9e 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -4033,8 +4033,9 @@ function djui_hud_reset_scissor() end --- @param message string ---- @return number ---- Measures the length of `message` in the current font +--- @return number width +--- @return number height +--- Measures the width and height of `message` in the current font function djui_hud_measure_text(message) -- ... end diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md index 572b46f94..0dcd65edb 100644 --- a/docs/lua/functions-3.md +++ b/docs/lua/functions-3.md @@ -3511,10 +3511,10 @@ Resets the scissor rectangle to a fullscreen state ## [djui_hud_measure_text](#djui_hud_measure_text) ### Description -Measures the length of `message` in the current font +Measures the width and height of `message` in the current font ### Lua Example -`local numberValue = djui_hud_measure_text(message)` +`local width, height = djui_hud_measure_text(message)` ### Parameters | Field | Type | @@ -3523,9 +3523,10 @@ Measures the length of `message` in the current font ### Returns - `number` +- `number` ### C Prototype -`f32 djui_hud_measure_text(const char* message);` +`void djui_hud_measure_text(const char* message, RET f32 *width, RET f32 *height);` [:arrow_up_small:](#) diff --git a/src/pc/djui/djui_font.c b/src/pc/djui/djui_font.c index 4b649d784..312c999d0 100644 --- a/src/pc/djui/djui_font.c +++ b/src/pc/djui/djui_font.c @@ -79,7 +79,7 @@ static f32 djui_font_title_char_width(const char* text) { static const struct DjuiFont sDjuiFontTitle = { .charWidth = 1.0f, - .charHeight = 0.9f, + .charHeight = 0.95f, .lineHeight = 0.7f, .xOffset = 0.0f, .yOffset = 0.0f, @@ -142,7 +142,7 @@ static f32 djui_font_hud_char_width(UNUSED const char* text) { static const struct DjuiFont sDjuiFontHud = { .charWidth = 1.0f, - .charHeight = 0.9f, + .charHeight = 1.0f, .lineHeight = 1.25f, .xOffset = 0.0f, .yOffset = 0.0f, @@ -238,7 +238,7 @@ static f32 djui_font_custom_hud_char_width(const char* text) { static const struct DjuiFont sDjuiFontCustomHud = { .charWidth = 1.0f, - .charHeight = 0.9f, + .charHeight = 0.7f, .lineHeight = 0.7f, .xOffset = -0.25f, .yOffset = -10.25f, @@ -252,7 +252,7 @@ static const struct DjuiFont sDjuiFontCustomHud = { static const struct DjuiFont sDjuiFontCustomHudRecolor = { .charWidth = 1.0f, - .charHeight = 0.9f, + .charHeight = 0.7f, .lineHeight = 0.7f, .xOffset = -0.25f, .yOffset = -10.25f, diff --git a/src/pc/djui/djui_hud_utils.c b/src/pc/djui/djui_hud_utils.c index 2e5d675d2..205f4ea05 100644 --- a/src/pc/djui/djui_hud_utils.c +++ b/src/pc/djui/djui_hud_utils.c @@ -519,10 +519,14 @@ void djui_hud_reset_scissor(void) { gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - BORDER_HEIGHT); } -f32 djui_hud_measure_text(const char* message) { - if (message == NULL) { return 0; } +void djui_hud_measure_text(const char* message, RET f32 *width, RET f32 *height) { + if (message == NULL) { return; } const struct DjuiFont* font = djui_hud_get_text_font(); - f32 width = 0, maxWidth = 0; + + f32 maxWidth = 0.f; + *width = 0.f; + *height = font->charHeight; + char *c = (char *) message; const char *end = message + strlen(message); while (*c != '\0') { @@ -534,14 +538,15 @@ f32 djui_hud_measure_text(const char* message) { // new line if (*c == '\n') { - maxWidth = max(width, maxWidth); - width = 0; + maxWidth = max(*width, maxWidth); + *width = 0; + *height += font->lineHeight; } // tab: align to the next (4 x space width) else if (*c == '\t') { f32 tabWidth = 4 * font->char_width(" ") * (djui_hud_text_font_is_legacy() ? 0.5f : 1.0f); - width += tabWidth - fmodf(width, tabWidth); + *width += tabWidth - fmodf(*width, tabWidth); } // unprintable chars @@ -551,12 +556,14 @@ f32 djui_hud_measure_text(const char* message) { // regular chars else { - width += font->char_width(c) * (djui_hud_text_font_is_legacy() ? 0.5f : 1.0f); + *width += font->char_width(c) * (djui_hud_text_font_is_legacy() ? 0.5f : 1.0f); } c = djui_unicode_next_char(c); } - return max(width, maxWidth) * font->defaultFontScale; + + *width = max(*width, maxWidth) * font->defaultFontScale; + *height *= font->defaultFontScale * (djui_hud_text_font_is_legacy() ? 0.5f : 1.0f); } static Mtx *allocate_dl_translation_matrix() { diff --git a/src/pc/djui/djui_hud_utils.h b/src/pc/djui/djui_hud_utils.h index 569b18a9b..8dedde65b 100644 --- a/src/pc/djui/djui_hud_utils.h +++ b/src/pc/djui/djui_hud_utils.h @@ -137,8 +137,8 @@ void djui_hud_set_scissor(f32 x, f32 y, f32 width, f32 height); /* |description|Resets the scissor rectangle to a fullscreen state|descriptionEnd| */ void djui_hud_reset_scissor(void); -/* |description|Measures the length of `message` in the current font|descriptionEnd| */ -f32 djui_hud_measure_text(const char* message); +/* |description|Measures the width and height of `message` in the current font|descriptionEnd| */ +void djui_hud_measure_text(const char* message, RET f32 *width, RET f32 *height); /* |description|Prints DJUI HUD text onto the screen|descriptionEnd| */ void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scale); /* |description|Prints interpolated DJUI HUD text onto the screen|descriptionEnd| */ diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 47dcd1e4c..a41d6f864 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -12790,9 +12790,15 @@ int smlua_func_djui_hud_measure_text(lua_State* L) { const char* message = smlua_to_string(L, 1); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_measure_text"); return 0; } - lua_pushnumber(L, djui_hud_measure_text(message)); + f32 width; + f32 height; - return 1; + djui_hud_measure_text(message, &width, &height); + + lua_pushnumber(L, width); + lua_pushnumber(L, height); + + return 2; } int smlua_func_djui_hud_print_text(lua_State* L) { diff --git a/src/pc/nametags.c b/src/pc/nametags.c index c39a1a249..52dff8163 100644 --- a/src/pc/nametags.c +++ b/src/pc/nametags.c @@ -135,12 +135,7 @@ void nametags_render(void) { struct MarioState *m = &gMarioStates[playerIndex]; struct NetworkPlayer *np = &gNetworkPlayers[playerIndex]; - u8* color = network_get_player_text_color(m->playerIndex); - f32 measure = djui_hud_measure_text(nametag->name) * nametag->scale * 0.5f; - nametag->pos[1] -= 16 * nametag->scale; - - u8 alpha = (playerIndex == 0 ? 255 : MIN(np->fadeOpacity << 3, 255)) * clamp(FADE_SCALE - nametag->scale, 0.f, 1.f); - + // init interpolation struct StateExtras* e = &sStateExtras[playerIndex]; if (!e->inited) { vec3f_copy(e->prevPos, nametag->pos); @@ -158,20 +153,31 @@ void nametags_render(void) { gSPViewport(gDisplayListHead++, viewport); } + f32 width, height; + djui_hud_measure_text(nametag->name, &width, &height); + f32 currHalfWidth = width * nametag->scale * 0.5f; + f32 currHalfHeight = height * nametag->scale * 0.5f; + f32 currNametagPosY = nametag->pos[1] - currHalfHeight; + f32 prevHalfWidth = width * e->prevScale * 0.5f; + f32 prevHalfHeight = height * e->prevScale * 0.5f; + f32 prevNametagPosY = e->prevPos[1] - prevHalfHeight; + const u8 *color = network_get_player_text_color(m->playerIndex); + u8 alpha = (playerIndex == 0 ? 255 : MIN(np->fadeOpacity << 3, 255)) * clamp(FADE_SCALE - nametag->scale, 0.f, 1.f); + // render name djui_hud_print_outlined_text_interpolated(nametag->name, - e->prevPos[0] - measure, e->prevPos[1], e->prevScale, - nametag->pos[0] - measure, nametag->pos[1], nametag->scale, + e->prevPos[0] - prevHalfWidth, prevNametagPosY, e->prevScale, + nametag->pos[0] - currHalfWidth, currNametagPosY, nametag->scale, color[0], color[1], color[2], alpha, 0.25); // render power meter if (playerIndex != 0 && gNametagsSettings.showHealth) { djui_hud_set_color(255, 255, 255, alpha); - f32 healthScale = 90 * nametag->scale; - f32 prevHealthScale = 90 * e->prevScale; + f32 currHealthSize = 90 * nametag->scale; + f32 prevHealthSize = 90 * e->prevScale; hud_render_power_meter_interpolated(m->health, - e->prevPos[0] - (prevHealthScale * 0.5f), e->prevPos[1] - 72 * nametag->scale, prevHealthScale, prevHealthScale, - nametag->pos[0] - ( healthScale * 0.5f), nametag->pos[1] - 72 * nametag->scale, healthScale, healthScale + e->prevPos[0] - (prevHealthSize * 0.5f), prevNametagPosY - 72 * e->prevScale, prevHealthSize, prevHealthSize, + nametag->pos[0] - (currHealthSize * 0.5f), currNametagPosY - 72 * nametag->scale, currHealthSize, currHealthSize ); }