Add independent X and Y scaling to text rendering functions (#1182)

* djui scale cool awesome

* fix autogen

* stop unnecessary yellow underlines

* Fix accidental bind removal
This commit is contained in:
Squishy 2026-05-01 18:17:44 -07:00 committed by GitHub
parent 0e2ba340fc
commit 0d95dfde11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 243 additions and 160 deletions

View file

@ -118,7 +118,7 @@ override_disallowed_functions = {
"src/game/mario.h": [ " init_mario" ],
"src/pc/djui/djui_console.h": [ " djui_console_create", "djui_console_message_create", "djui_console_message_dequeue" ],
"src/pc/djui/djui_chat_message.h": [ "create_from" ],
"src/pc/djui/djui_hud_utils.h": [ "djui_hud_clear_interp_data" ],
"src/pc/djui/djui_hud_utils.h": [ "djui_hud_clear_interp_data", "djui_hud_print_text", "djui_hud_print_text_interpolated" ],
"src/game/interaction.h": [ "process_interaction", "_handle_" ],
"src/game/sound_init.h": [ "_loop_", "thread4_", "set_sound_mode" ],
"src/pc/network/network_utils.h": [ "network_get_player_text_color[^_]" ],
@ -234,6 +234,8 @@ manual_index_documentation = """
- [cast_graph_node](#cast_graph_node)
- [get_uncolored_string](#get_uncolored_string)
- [gfx_set_command](#gfx_set_command)
- [djui_hud_print_text](#djui_hud_print_text)
- [djui_hud_print_text_interpolated](#djui_hud_print_text_interpolated)
<br />
@ -727,6 +729,64 @@ N/A
<br />
## [djui_hud_print_text](#djui_hud_print_text)
### Description
Prints DJUI HUD text onto the screen
### Lua Example
`djui_hud_print_text(message, x, y, scaleX, scaleY)`
### Parameters
| Field | Type |
| ----- | ---- |
| message | `string` |
| x | `number` |
| y | `number` |
| scaleX | `number` |
| scaleY | `number` |
### Returns
- None
### C Prototype
`void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scaleX, f32 scaleY);`
[:arrow_up_small:](#)
<br />
## [djui_hud_print_text_interpolated](#djui_hud_print_text_interpolated)
### Description
Prints interpolated DJUI HUD text onto the screen
### Lua Example
`djui_hud_print_text_interpolated(message, prevX, prevY, prevScaleX, prevScaleY, x, y, scaleX, scaleY)`
### Parameters
| Field | Type |
| ----- | ---- |
| message | `string` |
| prevX | `number` |
| prevY | `number` |
| prevScaleX | `number` |
| prevScaleY | `number` |
| x | `number` |
| y | `number` |
| scaleX | `number` |
| scaleY | `number` |
### Returns
- None
### C Prototype
`void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScaleX, f32 prevScaleY, f32 x, f32 y, f32 scaleX, f32 scaleY);`
[:arrow_up_small:](#)
<br />
"""
############################################################################

View file

@ -4040,27 +4040,6 @@ function djui_hud_measure_text(message)
-- ...
end
--- @param message string
--- @param x number
--- @param y number
--- @param scale number
--- Prints DJUI HUD text onto the screen
function djui_hud_print_text(message, x, y, scale)
-- ...
end
--- @param message string
--- @param prevX number
--- @param prevY number
--- @param prevScale number
--- @param x number
--- @param y number
--- @param scale number
--- Prints interpolated DJUI HUD text onto the screen
function djui_hud_print_text_interpolated(message, prevX, prevY, prevScale, x, y, scale)
-- ...
end
--- @param texInfo TextureInfo
--- @param x number
--- @param y number

View file

@ -441,3 +441,27 @@ end
function vtx_get_from_name(name)
-- ...
end
--- @param message string
--- @param x number
--- @param y number
--- @param scaleX number
--- @param scaleY number?
--- Prints DJUI HUD text onto the screen
function djui_hud_print_text(message, x, y, scaleX, scaleY)
-- ...
end
--- @param message string
--- @param prevX number
--- @param prevY number
--- @param prevScaleX number
--- @param prevScaleY number
--- @param x number
--- @param y number
--- @param scaleX number?
--- @param scaleY number?
--- Prints interpolated DJUI HUD text onto the screen
function djui_hud_print_text_interpolated(message, prevX, prevY, prevScaleX, prevScaleY, x, y, scaleX, scaleY)
-- ...
end

View file

@ -3532,61 +3532,6 @@ Measures the width and height of `message` in the current font
<br />
## [djui_hud_print_text](#djui_hud_print_text)
### Description
Prints DJUI HUD text onto the screen
### Lua Example
`djui_hud_print_text(message, x, y, scale)`
### Parameters
| Field | Type |
| ----- | ---- |
| message | `string` |
| x | `number` |
| y | `number` |
| scale | `number` |
### Returns
- None
### C Prototype
`void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scale);`
[:arrow_up_small:](#)
<br />
## [djui_hud_print_text_interpolated](#djui_hud_print_text_interpolated)
### Description
Prints interpolated DJUI HUD text onto the screen
### Lua Example
`djui_hud_print_text_interpolated(message, prevX, prevY, prevScale, x, y, scale)`
### Parameters
| Field | Type |
| ----- | ---- |
| message | `string` |
| prevX | `number` |
| prevY | `number` |
| prevScale | `number` |
| x | `number` |
| y | `number` |
| scale | `number` |
### Returns
- None
### C Prototype
`void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScale, f32 x, f32 y, f32 scale);`
[:arrow_up_small:](#)
<br />
## [djui_hud_render_texture](#djui_hud_render_texture)
### Description

View file

@ -25,6 +25,8 @@
- [cast_graph_node](#cast_graph_node)
- [get_uncolored_string](#get_uncolored_string)
- [gfx_set_command](#gfx_set_command)
- [djui_hud_print_text](#djui_hud_print_text)
- [djui_hud_print_text_interpolated](#djui_hud_print_text_interpolated)
<br />
@ -787,8 +789,6 @@
- [djui_hud_set_scissor](functions-3.md#djui_hud_set_scissor)
- [djui_hud_reset_scissor](functions-3.md#djui_hud_reset_scissor)
- [djui_hud_measure_text](functions-3.md#djui_hud_measure_text)
- [djui_hud_print_text](functions-3.md#djui_hud_print_text)
- [djui_hud_print_text_interpolated](functions-3.md#djui_hud_print_text_interpolated)
- [djui_hud_render_texture](functions-3.md#djui_hud_render_texture)
- [djui_hud_render_texture_tile](functions-3.md#djui_hud_render_texture_tile)
- [djui_hud_render_texture_interpolated](functions-3.md#djui_hud_render_texture_interpolated)
@ -2732,6 +2732,64 @@ N/A
<br />
## [djui_hud_print_text](#djui_hud_print_text)
### Description
Prints DJUI HUD text onto the screen
### Lua Example
`djui_hud_print_text(message, x, y, scaleX, scaleY)`
### Parameters
| Field | Type |
| ----- | ---- |
| message | `string` |
| x | `number` |
| y | `number` |
| scaleX | `number` |
| scaleY | `number` |
### Returns
- None
### C Prototype
`void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scaleX, f32 scaleY);`
[:arrow_up_small:](#)
<br />
## [djui_hud_print_text_interpolated](#djui_hud_print_text_interpolated)
### Description
Prints interpolated DJUI HUD text onto the screen
### Lua Example
`djui_hud_print_text_interpolated(message, prevX, prevY, prevScaleX, prevScaleY, x, y, scaleX, scaleY)`
### Parameters
| Field | Type |
| ----- | ---- |
| message | `string` |
| prevX | `number` |
| prevY | `number` |
| prevScaleX | `number` |
| prevScaleY | `number` |
| x | `number` |
| y | `number` |
| scaleX | `number` |
| scaleY | `number` |
### Returns
- None
### C Prototype
`void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScaleX, f32 prevScaleY, f32 x, f32 y, f32 scaleX, f32 scaleY);`
[:arrow_up_small:](#)
<br />
---
# functions from area.h

View file

@ -573,12 +573,13 @@ static Mtx *allocate_dl_translation_matrix() {
return matrix;
}
static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32 scale, struct InterpHud *interp) {
static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32 scaleX, f32 scaleY, struct InterpHud *interp) {
if (message == NULL) { return; }
gDjuiHudUtilsZ += 0.001f;
const struct DjuiFont* font = djui_hud_get_text_font();
f32 fontScale = font->defaultFontScale * scale;
f32 fontScaleX = font->defaultFontScale * scaleX;
f32 fontScaleY = font->defaultFontScale * scaleY;
// setup display list
if (font->textBeginDisplayList != NULL) {
@ -587,18 +588,20 @@ static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32
// translate position
djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION);
f32 translatedX = x + (font->xOffset * scale);
f32 translatedY = y + (font->yOffset * scale);
f32 translatedX = x + (font->xOffset * scaleX);
f32 translatedY = y + (font->yOffset * scaleY);
djui_hud_position_translate(&translatedX, &translatedY);
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// rotate
f32 translatedFontSize = fontScale;
djui_hud_size_translate(&translatedFontSize);
f32 translatedFontSizeX = fontScaleX;
f32 translatedFontSizeY = fontScaleY;
djui_hud_size_translate(&translatedFontSizeX);
djui_hud_size_translate(&translatedFontSizeY);
if (sHudUtilsState.rotation.degrees.prev != 0 || sHudUtilsState.rotation.degrees.curr != 0) {
djui_hud_create_interp_gfx(interp, INTERP_HUD_ROTATION);
f32 pivotTranslationX = font->defaultFontScale * translatedFontSize * sHudUtilsState.rotation.pivotX.curr;
f32 pivotTranslationY = font->defaultFontScale * translatedFontSize * sHudUtilsState.rotation.pivotY.curr;
f32 pivotTranslationX = font->defaultFontScale * translatedFontSizeX * sHudUtilsState.rotation.pivotX.curr;
f32 pivotTranslationY = font->defaultFontScale * translatedFontSizeY * sHudUtilsState.rotation.pivotY.curr;
create_dl_translation_matrix(DJUI_MTX_NOPUSH, +pivotTranslationX, -pivotTranslationY, 0);
create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sHudUtilsState.rotation.degrees.curr, 0, 0, 1);
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
@ -606,7 +609,7 @@ static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32
// compute font size
djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE);
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSize, translatedFontSize, 1.0f);
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSizeX, translatedFontSizeY, 1.0f);
// allocate the translation matrix for the vertical alignment
InterpHudGfx *valignGfx = djui_hud_create_interp_gfx(interp, INTERP_HUD_VALIGN);
@ -708,22 +711,25 @@ static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scale) {
void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scaleX, f32 scaleY) {
if (message == NULL) { return; }
if (djui_hud_text_font_is_legacy()) {
scale *= 0.5f;
scaleX *= 0.5f;
scaleY *= 0.5f;
}
djui_hud_print_text_internal(message, x, y, scale, NULL);
djui_hud_print_text_internal(message, x, y, scaleX, scaleY, NULL);
}
void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScale, f32 x, f32 y, f32 scale) {
void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScaleX, f32 prevScaleY, f32 x, f32 y, f32 scaleX, f32 scaleY) {
if (message == NULL) { return; }
if (djui_hud_text_font_is_legacy()) {
scale *= 0.5f;
prevScale *= 0.5f;
scaleX *= 0.5f;
scaleY *= 0.5f;
prevScaleX *= 0.5f;
prevScaleY *= 0.5f;
}
struct InterpHud *interp = djui_hud_create_interp();
@ -733,15 +739,15 @@ void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY,
interp->posY.prev = prevY;
interp->posX.curr = x;
interp->posY.curr = y;
interp->scaleX.prev = prevScale;
interp->scaleY.prev = prevScale;
interp->scaleX.curr = scale;
interp->scaleY.curr = scale;
interp->scaleX.prev = prevScaleX;
interp->scaleY.prev = prevScaleY;
interp->scaleX.curr = scaleX;
interp->scaleY.curr = scaleY;
interp->width = font->defaultFontScale;
interp->height = font->defaultFontScale;
}
djui_hud_print_text_internal(message, x, y, scale, interp);
djui_hud_print_text_internal(message, x, y, scaleX, scaleY, interp);
}
static inline bool is_power_of_two(u32 n) {

View file

@ -140,9 +140,9 @@ void djui_hud_reset_scissor(void);
/* |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);
void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scaleX, f32 scaleY);
/* |description|Prints interpolated DJUI HUD text onto the screen|descriptionEnd| */
void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScale, f32 x, f32 y, f32 scale);
void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScaleX, f32 prevScaleY, f32 x, f32 y, f32 scaleX, f32 scaleY);
/* |description|Renders a DJUI HUD texture onto the screen|descriptionEnd| */
void djui_hud_render_texture(struct TextureInfo* texInfo, f32 x, f32 y, f32 scaleW, f32 scaleH);
/* |description|Renders a DJUI HUD texture tile onto the screen|descriptionEnd| */

View file

@ -1005,6 +1005,69 @@ int smlua_func_gfx_set_command(lua_State* L) {
return 1;
}
/////////
// hud //
/////////
int smlua_func_djui_hud_print_text(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 4 && top != 5) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_print_text", 4, top);
return 0;
}
const char* message = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_print_text"); return 0; }
f32 x = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_print_text"); return 0; }
f32 y = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_print_text"); return 0; }
f32 scaleX = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_print_text"); return 0; }
f32 scaleY = top == 5 ? smlua_to_number(L, 5) : scaleX; // Copy Scale + Backwards Compatibility
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "djui_hud_print_text"); return 0; }
djui_hud_print_text(message, x, y, scaleX, scaleY);
return 1;
}
int smlua_func_djui_hud_print_text_interpolated(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 7 && top != 9) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_print_text_interpolated", 7, top);
return 0;
}
const char* message = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_print_text_interpolated"); return 0; }
f32 prevX = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_print_text_interpolated"); return 0; }
f32 prevY = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_print_text_interpolated"); return 0; }
f32 prevScaleX = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_print_text_interpolated"); return 0; }
f32 prevScaleY = top == 9 ? smlua_to_number(L, 5) : prevScaleX; // Copy Scale + Backwards Compatibility
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "djui_hud_print_text_interpolated"); return 0; }
f32 x = top == 9 ? smlua_to_number(L, 6) : smlua_to_number(L, 5); // Backwards Compatibility
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 6, "djui_hud_print_text_interpolated"); return 0; }
f32 y = top == 9 ? smlua_to_number(L, 7) : smlua_to_number(L, 6); // Backwards Compatibility
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 7, "djui_hud_print_text_interpolated"); return 0; }
f32 scaleX = top == 9 ? smlua_to_number(L, 8) : smlua_to_number(L, 7); // Backwards Compatibility
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 8, "djui_hud_print_text_interpolated"); return 0; }
f32 scaleY = top == 9 ? smlua_to_number(L, 9) : scaleX; // Copy Scale + Backwards Compatibility
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 9, "djui_hud_print_text_interpolated"); return 0; }
djui_hud_print_text_interpolated(message, prevX, prevY, prevScaleX, prevScaleY, x, y, scaleX, scaleY);
return 1;
}
//////////
// bind //
//////////
@ -1036,4 +1099,6 @@ void smlua_bind_functions(void) {
smlua_bind_function(L, "cast_graph_node", smlua_func_cast_graph_node);
smlua_bind_function(L, "get_uncolored_string", smlua_func_get_uncolored_string);
smlua_bind_function(L, "gfx_set_command", smlua_func_gfx_set_command);
smlua_bind_function(L, "djui_hud_print_text", smlua_func_djui_hud_print_text);
smlua_bind_function(L, "djui_hud_print_text_interpolated", smlua_func_djui_hud_print_text_interpolated);
}

View file

@ -12801,58 +12801,6 @@ int smlua_func_djui_hud_measure_text(lua_State* L) {
return 2;
}
int smlua_func_djui_hud_print_text(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 4) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_print_text", 4, top);
return 0;
}
const char* message = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_print_text"); return 0; }
f32 x = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_print_text"); return 0; }
f32 y = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_print_text"); return 0; }
f32 scale = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_print_text"); return 0; }
djui_hud_print_text(message, x, y, scale);
return 1;
}
int smlua_func_djui_hud_print_text_interpolated(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 7) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_print_text_interpolated", 7, top);
return 0;
}
const char* message = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_print_text_interpolated"); return 0; }
f32 prevX = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_print_text_interpolated"); return 0; }
f32 prevY = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_print_text_interpolated"); return 0; }
f32 prevScale = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_print_text_interpolated"); return 0; }
f32 x = smlua_to_number(L, 5);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "djui_hud_print_text_interpolated"); return 0; }
f32 y = smlua_to_number(L, 6);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 6, "djui_hud_print_text_interpolated"); return 0; }
f32 scale = smlua_to_number(L, 7);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 7, "djui_hud_print_text_interpolated"); return 0; }
djui_hud_print_text_interpolated(message, prevX, prevY, prevScale, x, y, scale);
return 1;
}
int smlua_func_djui_hud_render_texture(lua_State* L) {
if (L == NULL) { return 0; }
@ -37654,8 +37602,6 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "djui_hud_set_scissor", smlua_func_djui_hud_set_scissor);
smlua_bind_function(L, "djui_hud_reset_scissor", smlua_func_djui_hud_reset_scissor);
smlua_bind_function(L, "djui_hud_measure_text", smlua_func_djui_hud_measure_text);
smlua_bind_function(L, "djui_hud_print_text", smlua_func_djui_hud_print_text);
smlua_bind_function(L, "djui_hud_print_text_interpolated", smlua_func_djui_hud_print_text_interpolated);
smlua_bind_function(L, "djui_hud_render_texture", smlua_func_djui_hud_render_texture);
smlua_bind_function(L, "djui_hud_render_texture_tile", smlua_func_djui_hud_render_texture_tile);
smlua_bind_function(L, "djui_hud_render_texture_interpolated", smlua_func_djui_hud_render_texture_interpolated);

View file

@ -26,14 +26,14 @@ void djui_hud_print_outlined_text_interpolated(const char* text, f32 prevX, f32
// render outline
djui_hud_set_color(255 * outlineDarkness, 255 * outlineDarkness, 255 * outlineDarkness, a);
djui_hud_print_text_interpolated(text, prevX - prevOffset, prevY, prevScale, x - offset, y, scale);
djui_hud_print_text_interpolated(text, prevX + prevOffset, prevY, prevScale, x + offset, y, scale);
djui_hud_print_text_interpolated(text, prevX, prevY - prevOffset, prevScale, x, y - offset, scale);
djui_hud_print_text_interpolated(text, prevX, prevY + prevOffset, prevScale, x, y + offset, scale);
djui_hud_print_text_interpolated(text, prevX - prevOffset, prevY, prevScale, prevScale, x - offset, y, scale, scale);
djui_hud_print_text_interpolated(text, prevX + prevOffset, prevY, prevScale, prevScale, x + offset, y, scale, scale);
djui_hud_print_text_interpolated(text, prevX, prevY - prevOffset, prevScale, prevScale, x, y - offset, scale, scale);
djui_hud_print_text_interpolated(text, prevX, prevY + prevOffset, prevScale, prevScale, x, y + offset, scale, scale);
// render text
djui_hud_set_color(255, 255, 255, a);
djui_hud_print_text_interpolated(text, prevX, prevY, prevScale, x, y, scale);
djui_hud_print_text_interpolated(text, prevX, prevY, prevScale, prevScale, x, y, scale, scale);
// reset colors
djui_hud_set_color(255, 255, 255, 255);