From 8afe062be1ff6d172f04fbffdc620daf5a06b98b Mon Sep 17 00:00:00 2001 From: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Sat, 4 Apr 2026 01:37:16 +0200 Subject: [PATCH] Fix nametags color and rendering order (#1150) * Fix nametags color and rendering order * make growing_array_init reuse array and buffer if they were already allocated * use prim color for text color * isaac review * update text color descriptions * small optimization --- autogen/convert_functions.py | 1 + autogen/lua_definitions/functions.lua | 32 ++++-- docs/lua/functions-3.md | 74 +++++++++++- docs/lua/functions-6.md | 20 ---- docs/lua/functions.md | 4 +- src/game/area.c | 3 + src/game/level_update.c | 2 + src/game/memory.c | 44 +++++-- src/game/object_helpers.c | 15 --- src/game/object_helpers.h | 1 - src/game/object_list_processor.c | 2 + src/pc/crash_handler.c | 2 +- src/pc/djui/djui.c | 1 + src/pc/djui/djui_gfx.c | 8 +- src/pc/djui/djui_hud_utils.c | 106 ++++++++++++----- src/pc/djui/djui_hud_utils.h | 14 ++- src/pc/djui/djui_inputbox.c | 1 + src/pc/djui/djui_text.c | 7 +- src/pc/lua/smlua_functions_autogen.c | 75 ++++++++---- src/pc/nametags.c | 158 ++++++++++++++++---------- 20 files changed, 395 insertions(+), 175 deletions(-) diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 9a9f7d53a..19d9ad16b 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -118,6 +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/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[^_]" ], diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 08b0b1587..00d52fad7 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -3837,7 +3837,7 @@ function djui_hud_set_font(fontType) end --- @return DjuiColor ---- Gets the current DJUI HUD color +--- Gets the current DJUI HUD global color function djui_hud_get_color() -- ... end @@ -3846,16 +3846,36 @@ end --- @param g integer --- @param b integer --- @param a integer ---- Sets the current DJUI HUD color +--- Sets the current DJUI HUD global color function djui_hud_set_color(r, g, b, a) -- ... end ---- Resets the current DJUI HUD color +--- Resets the current DJUI HUD global color function djui_hud_reset_color() -- ... end +--- @return DjuiColor +--- Gets the current DJUI HUD text default color. This color is overridden by color codes +function djui_hud_get_text_color() + -- ... +end + +--- @param r integer +--- @param g integer +--- @param b integer +--- @param a integer +--- Sets the current DJUI HUD text default color. This color is overridden by color codes +function djui_hud_set_text_color(r, g, b, a) + -- ... +end + +--- Resets the current DJUI HUD text default color. This color is overridden by color codes +function djui_hud_reset_text_color() + -- ... +end + --- @return integer rotation --- @return number pivotX --- @return number pivotY @@ -9077,12 +9097,6 @@ function cur_obj_check_anim_frame_in_range(startFrame, rangeLength) -- ... end ---- @param a0 Pointer_integer ---- @return integer -function cur_obj_check_frame_prior_current_frame(a0) - -- ... -end - --- @param m MarioState --- @return integer function mario_is_in_air_action(m) diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md index 8e4f8c230..572b46f94 100644 --- a/docs/lua/functions-3.md +++ b/docs/lua/functions-3.md @@ -2858,7 +2858,7 @@ Sets the current DJUI HUD font ## [djui_hud_get_color](#djui_hud_get_color) ### Description -Gets the current DJUI HUD color +Gets the current DJUI HUD global color ### Lua Example `local djuiColorValue = djui_hud_get_color()` @@ -2879,7 +2879,7 @@ Gets the current DJUI HUD color ## [djui_hud_set_color](#djui_hud_set_color) ### Description -Sets the current DJUI HUD color +Sets the current DJUI HUD global color ### Lua Example `djui_hud_set_color(r, g, b, a)` @@ -2905,7 +2905,7 @@ Sets the current DJUI HUD color ## [djui_hud_reset_color](#djui_hud_reset_color) ### Description -Resets the current DJUI HUD color +Resets the current DJUI HUD global color ### Lua Example `djui_hud_reset_color()` @@ -2923,6 +2923,74 @@ Resets the current DJUI HUD color
+## [djui_hud_get_text_color](#djui_hud_get_text_color) + +### Description +Gets the current DJUI HUD text default color. This color is overridden by color codes + +### Lua Example +`local djuiColorValue = djui_hud_get_text_color()` + +### Parameters +- None + +### Returns +- [DjuiColor](structs.md#DjuiColor) + +### C Prototype +`struct DjuiColor* djui_hud_get_text_color(void);` + +[:arrow_up_small:](#) + +
+ +## [djui_hud_set_text_color](#djui_hud_set_text_color) + +### Description +Sets the current DJUI HUD text default color. This color is overridden by color codes + +### Lua Example +`djui_hud_set_text_color(r, g, b, a)` + +### Parameters +| Field | Type | +| ----- | ---- | +| r | `integer` | +| g | `integer` | +| b | `integer` | +| a | `integer` | + +### Returns +- None + +### C Prototype +`void djui_hud_set_text_color(u8 r, u8 g, u8 b, u8 a);` + +[:arrow_up_small:](#) + +
+ +## [djui_hud_reset_text_color](#djui_hud_reset_text_color) + +### Description +Resets the current DJUI HUD text default color. This color is overridden by color codes + +### Lua Example +`djui_hud_reset_text_color()` + +### Parameters +- None + +### Returns +- None + +### C Prototype +`void djui_hud_reset_text_color(void);` + +[:arrow_up_small:](#) + +
+ ## [djui_hud_get_rotation](#djui_hud_get_rotation) ### Description diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md index a639b7db9..d45ae38a8 100644 --- a/docs/lua/functions-6.md +++ b/docs/lua/functions-6.md @@ -1615,26 +1615,6 @@ Multiplies a vector by the transpose of a matrix of the form: `| ? ? ? 0 |` `| ?
-## [cur_obj_check_frame_prior_current_frame](#cur_obj_check_frame_prior_current_frame) - -### Lua Example -`local integerValue = cur_obj_check_frame_prior_current_frame(a0)` - -### Parameters -| Field | Type | -| ----- | ---- | -| a0 | `Pointer` <`integer`> | - -### Returns -- `integer` - -### C Prototype -`s32 cur_obj_check_frame_prior_current_frame(s16 *a0);` - -[:arrow_up_small:](#) - -
- ## [mario_is_in_air_action](#mario_is_in_air_action) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index b463ac63e..cd60e96f9 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -760,6 +760,9 @@ - [djui_hud_get_color](functions-3.md#djui_hud_get_color) - [djui_hud_set_color](functions-3.md#djui_hud_set_color) - [djui_hud_reset_color](functions-3.md#djui_hud_reset_color) + - [djui_hud_get_text_color](functions-3.md#djui_hud_get_text_color) + - [djui_hud_set_text_color](functions-3.md#djui_hud_set_text_color) + - [djui_hud_reset_text_color](functions-3.md#djui_hud_reset_text_color) - [djui_hud_get_rotation](functions-3.md#djui_hud_get_rotation) - [djui_hud_set_rotation](functions-3.md#djui_hud_set_rotation) - [djui_hud_set_rotation_interpolated](functions-3.md#djui_hud_set_rotation_interpolated) @@ -1609,7 +1612,6 @@ - [cur_obj_check_if_at_animation_end](functions-6.md#cur_obj_check_if_at_animation_end) - [cur_obj_check_anim_frame](functions-6.md#cur_obj_check_anim_frame) - [cur_obj_check_anim_frame_in_range](functions-6.md#cur_obj_check_anim_frame_in_range) - - [cur_obj_check_frame_prior_current_frame](functions-6.md#cur_obj_check_frame_prior_current_frame) - [mario_is_in_air_action](functions-6.md#mario_is_in_air_action) - [mario_is_dive_sliding](functions-6.md#mario_is_dive_sliding) - [cur_obj_set_y_vel_and_animation](functions-6.md#cur_obj_set_y_vel_and_animation) diff --git a/src/game/area.c b/src/game/area.c index 36448abd5..c22fa22eb 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -26,6 +26,7 @@ #include "pc/network/network.h" #include "pc/lua/smlua_hooks.h" #include "pc/djui/djui.h" +#include "pc/djui/djui_hud_utils.h" #include "pc/djui/djui_panel_pause.h" #include "pc/nametags.h" #include "engine/lighting_engine.h" @@ -254,6 +255,7 @@ void clear_areas(void) { le_clear(); geo_clear_interp_data(); + djui_hud_clear_interp_data(); } void clear_area_graph_nodes(void) { @@ -313,6 +315,7 @@ void unload_area(void) { le_clear(); geo_clear_interp_data(); + djui_hud_clear_interp_data(); } void load_mario_area(void) { diff --git a/src/game/level_update.c b/src/game/level_update.c index ff6ae25b1..76348da45 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -43,6 +43,7 @@ #include "pc/configfile.h" #include "pc/network/network.h" #include "pc/djui/djui.h" +#include "pc/djui/djui_hud_utils.h" // used for getting gMainMenuSounds #include "pc/djui/djui_panel_menu_options.h" #include "pc/lua/smlua_hooks.h" @@ -1764,6 +1765,7 @@ s32 update_level(void) { s32 init_level(void) { sync_objects_clear(); geo_clear_interp_data(); + djui_hud_clear_interp_data(); reset_dialog_render_state(); s32 val4 = 0; diff --git a/src/game/memory.c b/src/game/memory.c index feca24fd1..ee123c0ff 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -185,10 +185,42 @@ void growing_pool_free_pool(struct GrowingPool *pool) { // growing array // /////////////////// +static void growing_array_free_elements(struct GrowingArray *array) { + if (array) { + if (array->buffer) { + for (u32 i = 0; i != array->capacity; ++i) { + if (array->buffer[i]) { + array->free(array->buffer[i]); + } + } + memset(array->buffer, 0, sizeof(void *) * array->capacity); + } + array->count = 0; + } +} + struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free) { - growing_array_free(&array); - array = calloc(1, sizeof(struct GrowingArray)); - array->buffer = calloc(capacity, sizeof(void *)); + growing_array_free_elements(array); + + // reuse buffer if array was already allocated + if (array) { + if (!array->buffer || array->capacity != capacity) { + void **buffer = realloc(array->buffer, sizeof(void *) * capacity); + + // if realloc fails, destroy the array and create a new one + if (!buffer) { + growing_array_free(&array); + return growing_array_init(NULL, capacity, alloc, free); + } + + memset(buffer, 0, sizeof(void *) * capacity); + array->buffer = buffer; + } + } else { + array = malloc(sizeof(struct GrowingArray)); + array->buffer = calloc(capacity, sizeof(void *)); + } + array->capacity = capacity; array->count = 0; array->alloc = alloc; @@ -248,11 +280,7 @@ void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count) void growing_array_free(struct GrowingArray **array) { if (*array) { - for (u32 i = 0; i != (*array)->capacity; ++i) { - if ((*array)->buffer[i]) { - (*array)->free((*array)->buffer[i]); - } - } + growing_array_free_elements(*array); free((*array)->buffer); free(*array); *array = NULL; diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index f0bf4d162..ff35fe280 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -1333,21 +1333,6 @@ s32 cur_obj_check_anim_frame_in_range(s32 startFrame, s32 rangeLength) { } } -s32 cur_obj_check_frame_prior_current_frame(s16 *a0) { - if (!o) { return 0; } - s16 sp6 = o->header.gfx.animInfo.animFrame; - - while (*a0 != -1) { - if (*a0 == sp6) { - return TRUE; - } - - a0++; - } - - return FALSE; -} - s32 mario_is_in_air_action(struct MarioState* m) { if (!m) { return 0; } if (m->action & ACT_FLAG_AIR) { diff --git a/src/game/object_helpers.h b/src/game/object_helpers.h index fc65f764a..d004ecbeb 100644 --- a/src/game/object_helpers.h +++ b/src/game/object_helpers.h @@ -158,7 +158,6 @@ s32 cur_obj_check_if_near_animation_end(void); s32 cur_obj_check_if_at_animation_end(void); s32 cur_obj_check_anim_frame(s32 frame); s32 cur_obj_check_anim_frame_in_range(s32 startFrame, s32 rangeLength); -s32 cur_obj_check_frame_prior_current_frame(s16 *a0); s32 mario_is_in_air_action(struct MarioState* m); s32 mario_is_dive_sliding(struct MarioState* m); void cur_obj_set_y_vel_and_animation(f32 sp18, s32 sp1C); diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index 1752ae7b4..98fd6174c 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -25,6 +25,7 @@ #include "engine/math_util.h" #include "pc/network/network.h" #include "pc/lua/smlua.h" +#include "pc/djui/djui_hud_utils.h" /** * Flags controlling what debug info is displayed. @@ -605,6 +606,7 @@ void clear_objects(void) { clear_dynamic_surfaces(); geo_clear_interp_data(); + djui_hud_clear_interp_data(); } /** diff --git a/src/pc/crash_handler.c b/src/pc/crash_handler.c index 470f4e2e6..a493bbf39 100644 --- a/src/pc/crash_handler.c +++ b/src/pc/crash_handler.c @@ -217,12 +217,12 @@ static void crash_handler_produce_one_frame_callback(void) { if (font->textBeginDisplayList != NULL) { gSPDisplayList(gDisplayListHead++, font->textBeginDisplayList); } + gDPSetPrimColor(gDisplayListHead++, 0, 0, 255, 255, 255, 255); for (CrashHandlerText* text = sCrashHandlerText; text->s[0] != 0; ++text) { s32 x = GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(text->x * aspectScale); s32 y = SCREEN_HEIGHT - 8 - text->y * aspectScale; gDPPipeSync(gDisplayListHead++); - gDPSetEnvColor(gDisplayListHead++, text->r, text->g, text->b, 0xFF); create_dl_translation_matrix(DJUI_MTX_PUSH, x, y, 0); // translate scale diff --git a/src/pc/djui/djui.c b/src/pc/djui/djui.c index 3bd9fc8b1..43218a151 100644 --- a/src/pc/djui/djui.c +++ b/src/pc/djui/djui.c @@ -171,6 +171,7 @@ void djui_reset_hud_params(void) { djui_hud_set_rotation(0, ROTATION_PIVOT_X_LEFT, ROTATION_PIVOT_Y_TOP); djui_hud_set_text_alignment(TEXT_HALIGN_LEFT, TEXT_VALIGN_TOP); djui_hud_reset_color(); + djui_hud_reset_text_color(); djui_hud_set_filter(FILTER_NEAREST); djui_hud_reset_viewport(); djui_hud_reset_scissor(); diff --git a/src/pc/djui/djui_gfx.c b/src/pc/djui/djui_gfx.c index 4319782c3..eccfa5c95 100644 --- a/src/pc/djui/djui_gfx.c +++ b/src/pc/djui/djui_gfx.c @@ -166,7 +166,8 @@ void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt, void djui_gfx_render_texture_font_begin() { gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BOTH); - gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_FADEA); + gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_MODULATERGBA_PRIM2); + gDPSetCycleType(gDisplayListHead++, G_CYC_2CYCLE); gDPSetRenderMode(gDisplayListHead++, G_RM_XLU_SURF, G_RM_XLU_SURF2); gDPSetTextureFilter(gDisplayListHead++, djui_hud_get_filter() ? G_TF_BILERP : G_TF_POINT); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); @@ -193,12 +194,14 @@ void djui_gfx_render_texture_font(const Texture* texture, u32 w, u32 h, u8 fmt, void djui_gfx_render_texture_font_end() { gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); + gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE); gSPSetGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BACK); } void djui_gfx_render_texture_tile_font_begin() { gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BOTH); - gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_FADEA); + gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_MODULATERGBA_PRIM2); + gDPSetCycleType(gDisplayListHead++, G_CYC_2CYCLE); gDPSetRenderMode(gDisplayListHead++, G_RM_XLU_SURF, G_RM_XLU_SURF2); gDPSetTextureFilter(gDisplayListHead++, G_TF_POINT); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); @@ -243,6 +246,7 @@ void djui_gfx_render_texture_tile_font(const Texture* texture, u32 w, u32 h, u8 void djui_gfx_render_texture_tile_font_end() { gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); + gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE); gSPSetGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BACK); } diff --git a/src/pc/djui/djui_hud_utils.c b/src/pc/djui/djui_hud_utils.c index d36938e79..2e5d675d2 100644 --- a/src/pc/djui/djui_hud_utils.c +++ b/src/pc/djui/djui_hud_utils.c @@ -35,6 +35,7 @@ struct HudUtilsState { enum HudUtilsFilter filter; enum DjuiFontType font; struct DjuiColor color; + struct DjuiColor textColor; struct { InterpFieldF32 degrees; InterpFieldF32 pivotX; @@ -51,6 +52,7 @@ static struct HudUtilsState sHudUtilsState = { .filter = FILTER_NEAREST, .font = FONT_NORMAL, .color = { 255, 255, 255, 255 }, + .textColor = { 255, 255, 255, 255 }, .rotation = { .degrees = INTERP_INIT(0), .pivotX = INTERP_INIT(ROTATION_PIVOT_X_LEFT), @@ -63,6 +65,7 @@ static struct HudUtilsState sHudUtilsState = { }; static struct DjuiColor sRefColor = { 255, 255, 255, 255 }; +static struct DjuiColor sRefTextColor = { 255, 255, 255, 255 }; f32 gDjuiHudUtilsZ = 0; bool gDjuiHudLockMouse = false; @@ -144,8 +147,6 @@ static void djui_hud_translate_positions(f32 *outX, f32 *outY, f32 *outW, f32 *o // interp // //////////// -#define MAX_INTERP_HUD 512 - enum InterpHudType { INTERP_HUD_TRANSLATION, INTERP_HUD_ROTATION, @@ -170,9 +171,16 @@ struct InterpHud { struct GrowingArray *gfx; }; -static struct InterpHud sInterpHuds[MAX_INTERP_HUD] = { 0 }; -static u16 sInterpHudCount = 0; -static u8 sColorAltered = FALSE; +static struct GrowingArray *sInterpHuds = NULL; +static u32 sInterpHudCount = 0; + +static void interp_hud_free(void *ptr) { + struct InterpHud *interp = ptr; + if (interp) { + growing_array_free(&interp->gfx); + free(interp); + } +} void patch_djui_hud_before(void) { sInterpHudCount = 0; @@ -183,8 +191,8 @@ void patch_djui_hud(f32 delta) { Gfx* savedHeadPos = gDisplayListHead; struct HudUtilsState savedState = sHudUtilsState; - for (u16 i = 0; i < sInterpHudCount; i++) { - struct InterpHud* interp = &sInterpHuds[i]; + for (u32 i = 0; i < sInterpHudCount; i++) { + struct InterpHud *interp = sInterpHuds->buffer[i]; f32 x = delta_interpolate_f32(interp->posX.prev, interp->posX.curr, delta); f32 y = delta_interpolate_f32(interp->posY.prev, interp->posY.curr, delta); @@ -260,22 +268,28 @@ void patch_djui_hud(f32 delta) { gDjuiHudUtilsZ = savedZ; } -struct InterpHud *djui_hud_create_interp() { - if (sInterpHudCount >= MAX_INTERP_HUD) { return NULL; } +static struct InterpHud *djui_hud_create_interp() { + struct InterpHud *interp = ( + sInterpHudCount < sInterpHuds->count ? + sInterpHuds->buffer[sInterpHudCount] : + growing_array_alloc(sInterpHuds, sizeof(struct InterpHud)) + ); - struct InterpHud *interp = &sInterpHuds[sInterpHudCount++]; - interp->z = gDjuiHudUtilsZ; - interp->state = sHudUtilsState; - if (!interp->gfx) { - interp->gfx = growing_array_init(NULL, 8, malloc, free); - } else { - interp->gfx->count = 0; + if (interp) { + interp->z = gDjuiHudUtilsZ; + interp->state = sHudUtilsState; + if (!interp->gfx) { + interp->gfx = growing_array_init(NULL, 8, malloc, free); + } else { + interp->gfx->count = 0; + } + sInterpHudCount++; } return interp; } -InterpHudGfx *djui_hud_create_interp_gfx(struct InterpHud *interp, enum InterpHudType type) { +static InterpHudGfx *djui_hud_create_interp_gfx(struct InterpHud *interp, enum InterpHudType type) { if (!interp) { return NULL; } InterpHudGfx *gfx = growing_array_alloc(interp->gfx, sizeof(InterpHudGfx)); @@ -284,6 +298,11 @@ InterpHudGfx *djui_hud_create_interp_gfx(struct InterpHud *interp, enum InterpHu return gfx; } +void djui_hud_clear_interp_data() { + sInterpHuds = growing_array_init(sInterpHuds, 16, malloc, interp_hud_free); + sInterpHudCount = 0; +} + //////////// // others // //////////// @@ -328,19 +347,37 @@ void djui_hud_set_color(u8 r, u8 g, u8 b, u8 a) { sHudUtilsState.color.g = g; sHudUtilsState.color.b = b; sHudUtilsState.color.a = a; - sColorAltered = TRUE; gDPSetEnvColor(gDisplayListHead++, r, g, b, a); } void djui_hud_reset_color(void) { - if (sColorAltered) { - sHudUtilsState.color.r = 255; - sHudUtilsState.color.g = 255; - sHudUtilsState.color.b = 255; - sHudUtilsState.color.a = 255; - sColorAltered = FALSE; - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); - } + sHudUtilsState.color.r = 255; + sHudUtilsState.color.g = 255; + sHudUtilsState.color.b = 255; + sHudUtilsState.color.a = 255; + gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); +} + +struct DjuiColor* djui_hud_get_text_color(void) { + sRefTextColor.r = sHudUtilsState.textColor.r; + sRefTextColor.g = sHudUtilsState.textColor.g; + sRefTextColor.b = sHudUtilsState.textColor.b; + sRefTextColor.a = sHudUtilsState.textColor.a; + return &sRefTextColor; +} + +void djui_hud_set_text_color(u8 r, u8 g, u8 b, u8 a) { + sHudUtilsState.textColor.r = r; + sHudUtilsState.textColor.g = g; + sHudUtilsState.textColor.b = b; + sHudUtilsState.textColor.a = a; +} + +void djui_hud_reset_text_color(void) { + sHudUtilsState.textColor.r = 255; + sHudUtilsState.textColor.g = 255; + sHudUtilsState.textColor.b = 255; + sHudUtilsState.textColor.a = 255; } void djui_hud_get_rotation(RET s16 *rotation, RET f32 *pivotX, RET f32 *pivotY) { @@ -580,13 +617,26 @@ static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32 f32 lineWidth = 0; f32 textHeight = font->lineHeight; + // apply text color + gDPSetPrimColor(gDisplayListHead++, 0, 0, + sHudUtilsState.textColor.r, + sHudUtilsState.textColor.g, + sHudUtilsState.textColor.b, + sHudUtilsState.textColor.a + ); + font->render_begin(); while (*c != '\0') { // check color code struct DjuiColor parsedColor; - if (djui_text_parse_color(c, end, false, &sHudUtilsState.color, &c, &parsedColor)) { - gDPSetEnvColor(gDisplayListHead++, parsedColor.r, parsedColor.g, parsedColor.b, parsedColor.a); + if (djui_text_parse_color(c, end, false, &sHudUtilsState.textColor, &c, &parsedColor)) { + gDPSetPrimColor(gDisplayListHead++, 0, 0, + parsedColor.r, + parsedColor.g, + parsedColor.b, + parsedColor.a + ); continue; } diff --git a/src/pc/djui/djui_hud_utils.h b/src/pc/djui/djui_hud_utils.h index 353ee3511..569b18a9b 100644 --- a/src/pc/djui/djui_hud_utils.h +++ b/src/pc/djui/djui_hud_utils.h @@ -62,6 +62,8 @@ extern struct GlobalTextures gGlobalTextures; extern f32 gDjuiHudUtilsZ; extern bool gDjuiHudLockMouse; +void djui_hud_clear_interp_data(); + /* |description|Gets the current DJUI HUD resolution|descriptionEnd| */ u8 djui_hud_get_resolution(void); /* |description|Sets the current DJUI HUD resolution|descriptionEnd| */ @@ -74,12 +76,18 @@ void djui_hud_set_filter(enum HudUtilsFilter filterType); s8 djui_hud_get_font(void); /* |description|Sets the current DJUI HUD font|descriptionEnd| */ void djui_hud_set_font(s8 fontType); -/* |description|Gets the current DJUI HUD color|descriptionEnd| */ +/* |description|Gets the current DJUI HUD global color|descriptionEnd| */ struct DjuiColor* djui_hud_get_color(void); -/* |description|Sets the current DJUI HUD color|descriptionEnd| */ +/* |description|Sets the current DJUI HUD global color|descriptionEnd| */ void djui_hud_set_color(u8 r, u8 g, u8 b, u8 a); -/* |description|Resets the current DJUI HUD color|descriptionEnd| */ +/* |description|Resets the current DJUI HUD global color|descriptionEnd| */ void djui_hud_reset_color(void); +/* |description|Gets the current DJUI HUD text default color. This color is overridden by color codes|descriptionEnd| */ +struct DjuiColor* djui_hud_get_text_color(void); +/* |description|Sets the current DJUI HUD text default color. This color is overridden by color codes|descriptionEnd| */ +void djui_hud_set_text_color(u8 r, u8 g, u8 b, u8 a); +/* |description|Resets the current DJUI HUD text default color. This color is overridden by color codes|descriptionEnd| */ +void djui_hud_reset_text_color(void); /* |description|Gets the current DJUI HUD rotation|descriptionEnd| */ void djui_hud_get_rotation(RET s16 *rotation, RET f32 *pivotX, RET f32 *pivotY); /* |description|Sets the current DJUI HUD rotation|descriptionEnd| */ diff --git a/src/pc/djui/djui_inputbox.c b/src/pc/djui/djui_inputbox.c index c0a911130..da7fa59b0 100644 --- a/src/pc/djui/djui_inputbox.c +++ b/src/pc/djui/djui_inputbox.c @@ -577,6 +577,7 @@ static bool djui_inputbox_render(struct DjuiBase* base) { } // set color + gDPSetPrimColor(gDisplayListHead++, 0, 0, 255, 255, 255, 255); gDPSetEnvColor(gDisplayListHead++, inputbox->textColor.r, inputbox->textColor.g, inputbox->textColor.b, inputbox->textColor.a); // make selection well formed diff --git a/src/pc/djui/djui_text.c b/src/pc/djui/djui_text.c index 26fd4ea9c..eb5643ac8 100644 --- a/src/pc/djui/djui_text.c +++ b/src/pc/djui/djui_text.c @@ -382,8 +382,10 @@ static void djui_text_render_line(struct DjuiText* text, char* c1, char* c2, f32 for (char* c = c1; c < c2;) { struct DjuiColor parsedColor; if (djui_text_parse_color(c, c2, true, &sDjuiTextDefaultColor, &c, &parsedColor)) { - gDPSetEnvColor(gDisplayListHead++, parsedColor.r, parsedColor.g, parsedColor.b, parsedColor.a); - sDjuiTextCurrentColor = parsedColor; + sDjuiTextCurrentColor.r = parsedColor.r; + sDjuiTextCurrentColor.g = parsedColor.g; + sDjuiTextCurrentColor.b = parsedColor.b; + gDPSetEnvColor(gDisplayListHead++, sDjuiTextCurrentColor.r, sDjuiTextCurrentColor.g, sDjuiTextCurrentColor.b, sDjuiTextCurrentColor.a); continue; } @@ -450,6 +452,7 @@ static bool djui_text_render(struct DjuiBase* base) { create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSize, translatedFontSize, 1.0f); // set color + gDPSetPrimColor(gDisplayListHead++, 0, 0, 255, 255, 255, 255); gDPSetEnvColor(gDisplayListHead++, base->color.r, base->color.g, base->color.b, base->color.a); sDjuiTextCurrentColor = base->color; diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 54bb0672b..47dcd1e4c 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -12318,6 +12318,59 @@ int smlua_func_djui_hud_reset_color(UNUSED lua_State* L) { return 1; } +int smlua_func_djui_hud_get_text_color(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_get_text_color", 0, top); + return 0; + } + + + smlua_push_object(L, LOT_DJUICOLOR, djui_hud_get_text_color(), NULL); + + return 1; +} + +int smlua_func_djui_hud_set_text_color(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_set_text_color", 4, top); + return 0; + } + + u8 r = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_text_color"); return 0; } + u8 g = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_text_color"); return 0; } + u8 b = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_set_text_color"); return 0; } + u8 a = smlua_to_integer(L, 4); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_set_text_color"); return 0; } + + djui_hud_set_text_color(r, g, b, a); + + return 1; +} + +int smlua_func_djui_hud_reset_text_color(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_reset_text_color", 0, top); + return 0; + } + + + djui_hud_reset_text_color(); + + return 1; +} + int smlua_func_djui_hud_get_rotation(lua_State* L) { if (L == NULL) { return 0; } @@ -26858,24 +26911,6 @@ int smlua_func_cur_obj_check_anim_frame_in_range(lua_State* L) { return 1; } -int smlua_func_cur_obj_check_frame_prior_current_frame(lua_State* L) { - if (L == NULL) { return 0; } - - int top = lua_gettop(L); - if (top != 1) { - LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "cur_obj_check_frame_prior_current_frame", 1, top); - return 0; - } - - s16 * a0 = (s16 *)smlua_to_cpointer(L, 1, LVT_S16_P); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "cur_obj_check_frame_prior_current_frame"); return 0; } - - extern s32 cur_obj_check_frame_prior_current_frame(s16 *a0); - lua_pushinteger(L, cur_obj_check_frame_prior_current_frame(a0)); - - return 1; -} - int smlua_func_mario_is_in_air_action(lua_State* L) { if (L == NULL) { return 0; } @@ -37494,6 +37529,9 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "djui_hud_get_color", smlua_func_djui_hud_get_color); smlua_bind_function(L, "djui_hud_set_color", smlua_func_djui_hud_set_color); smlua_bind_function(L, "djui_hud_reset_color", smlua_func_djui_hud_reset_color); + smlua_bind_function(L, "djui_hud_get_text_color", smlua_func_djui_hud_get_text_color); + smlua_bind_function(L, "djui_hud_set_text_color", smlua_func_djui_hud_set_text_color); + smlua_bind_function(L, "djui_hud_reset_text_color", smlua_func_djui_hud_reset_text_color); smlua_bind_function(L, "djui_hud_get_rotation", smlua_func_djui_hud_get_rotation); smlua_bind_function(L, "djui_hud_set_rotation", smlua_func_djui_hud_set_rotation); smlua_bind_function(L, "djui_hud_set_rotation_interpolated", smlua_func_djui_hud_set_rotation_interpolated); @@ -38277,7 +38315,6 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "cur_obj_check_if_at_animation_end", smlua_func_cur_obj_check_if_at_animation_end); smlua_bind_function(L, "cur_obj_check_anim_frame", smlua_func_cur_obj_check_anim_frame); smlua_bind_function(L, "cur_obj_check_anim_frame_in_range", smlua_func_cur_obj_check_anim_frame_in_range); - smlua_bind_function(L, "cur_obj_check_frame_prior_current_frame", smlua_func_cur_obj_check_frame_prior_current_frame); smlua_bind_function(L, "mario_is_in_air_action", smlua_func_mario_is_in_air_action); smlua_bind_function(L, "mario_is_dive_sliding", smlua_func_mario_is_dive_sliding); smlua_bind_function(L, "cur_obj_set_y_vel_and_animation", smlua_func_cur_obj_set_y_vel_and_animation); diff --git a/src/pc/nametags.c b/src/pc/nametags.c index 37fe27bf8..c39a1a249 100644 --- a/src/pc/nametags.c +++ b/src/pc/nametags.c @@ -18,34 +18,26 @@ struct StateExtras { }; static struct StateExtras sStateExtras[MAX_PLAYERS]; -void name_without_hex(char* input) { - s32 i, j; - bool inSlash = false; - for (i = j = 0; input[i] != '\0'; i++) { - if (input[i] == '\\') { - inSlash = !inSlash; - } else if (!inSlash) { - input[j++] = input[i]; // it just works - } - } - - input[j] = '\0'; -} - void djui_hud_print_outlined_text_interpolated(const char* text, f32 prevX, f32 prevY, f32 prevScale, f32 x, f32 y, f32 scale, u8 r, u8 g, u8 b, u8 a, f32 outlineDarkness) { f32 offset = 1 * (scale * 2); f32 prevOffset = 1 * (prevScale * 2); + djui_hud_set_text_color(r, g, b, 255); + // render outline - djui_hud_set_color(r * outlineDarkness, g * outlineDarkness, b * outlineDarkness, a); + 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); + // render text - djui_hud_set_color(r, g, b, a); + djui_hud_set_color(255, 255, 255, a); djui_hud_print_text_interpolated(text, prevX, prevY, prevScale, x, y, scale); + + // reset colors djui_hud_set_color(255, 255, 255, 255); + djui_hud_set_text_color(255, 255, 255, 255); } void nametags_render(void) { @@ -59,7 +51,21 @@ void nametags_render(void) { djui_hud_set_resolution(RESOLUTION_N64); djui_hud_set_font(FONT_SPECIAL); - for (u8 i = gNametagsSettings.showSelfTag ? 0 : 1; i < MAX_PLAYERS; i++) { + struct NametagInfo { + Vec3f pos; + f32 scale; + char name[MAX_CONFIG_STRING]; + }; + struct NametagInfo nametags[MAX_PLAYERS] = {0}; + s32 sortedNametagIndices[MAX_PLAYERS] = {0}; + s32 numNametags = 0; + + extern bool gDjuiHudToWorldCalcViewport; + gDjuiHudToWorldCalcViewport = false; + + // sort nametags by their distance to the camera + // insertion sort is quick enough for such small array + for (s32 i = gNametagsSettings.showSelfTag ? 0 : 1; i < MAX_PLAYERS; i++) { struct MarioState* m = &gMarioStates[i]; if (!is_player_active(m)) { continue; } struct NetworkPlayer* np = &gNetworkPlayers[i]; @@ -84,8 +90,6 @@ void nametags_render(void) { vec3f_copy(pos, m->marioBodyState->headPos); pos[1] += 100; - extern bool gDjuiHudToWorldCalcViewport; - gDjuiHudToWorldCalcViewport = false; if ((i != 0 || (i == 0 && m->action != ACT_FIRST_PERSON)) && djui_hud_world_pos_to_screen_pos(pos, out)) { @@ -96,61 +100,89 @@ void nametags_render(void) { snprintf(name, MAX_CONFIG_STRING, "%s", hookedString); } else { snprintf(name, MAX_CONFIG_STRING, "%s", np->name); - name_without_hex(name); } if (!djui_hud_world_pos_to_screen_pos(pos, out)) { continue; } - u8* color = network_get_player_text_color(m->playerIndex); f32 scale = -300 / out[2] * djui_hud_get_fov_coeff(); - f32 measure = djui_hud_measure_text(name) * scale * 0.5f; - out[1] -= 16 * scale; - u8 alpha = (i == 0 ? 255 : MIN(np->fadeOpacity << 3, 255)) * clamp(FADE_SCALE - scale, 0.f, 1.f); - - struct StateExtras* e = &sStateExtras[i]; - if (!e->inited) { - vec3f_copy(e->prevPos, out); - e->prevScale = scale; - e->inited = true; + s32 j = 0; + for (; j < numNametags; ++j) { + const struct NametagInfo *nametag = &nametags[sortedNametagIndices[j]]; + if (scale < nametag->scale) { + memmove(sortedNametagIndices + j + 1, sortedNametagIndices + j, sizeof(s32) * (numNametags - j)); + break; + } } + sortedNametagIndices[j] = i; - // Apply viewport for credits - extern Vp *gViewportOverride; - extern Vp *gViewportClip; - extern Vp gViewportFullscreen; - Vp *viewport = gViewportOverride == NULL ? gViewportClip : gViewportOverride; - if (viewport) { - make_viewport_clip_rect(viewport); - gSPViewport(gDisplayListHead++, viewport); - } + struct NametagInfo *nametag = &nametags[i]; + vec3f_copy(nametag->pos, out); + nametag->scale = scale; + memcpy(nametag->name, name, sizeof(name)); - djui_hud_print_outlined_text_interpolated(name, - e->prevPos[0] - measure, e->prevPos[1], e->prevScale, - out[0] - measure, out[1], scale, - color[0], color[1], color[2], alpha, 0.25); - - if (i != 0 && gNametagsSettings.showHealth) { - djui_hud_set_color(255, 255, 255, alpha); - f32 healthScale = 90 * scale; - f32 prevHealthScale = 90 * e->prevScale; - hud_render_power_meter_interpolated(m->health, - e->prevPos[0] - (prevHealthScale * 0.5f), e->prevPos[1] - 72 * scale, prevHealthScale, prevHealthScale, - out[0] - ( healthScale * 0.5f), out[1] - 72 * scale, healthScale, healthScale - ); - } - - // Reset viewport - if (viewport) { - gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - BORDER_HEIGHT); - gSPViewport(gDisplayListHead++, &gViewportFullscreen); - } - - vec3f_copy(e->prevPos, out); - e->prevScale = scale; + numNametags++; } - gDjuiHudToWorldCalcViewport = true; + } + + gDjuiHudToWorldCalcViewport = true; + + // render nametags + for (s32 k = 0; k < numNametags; ++k) { + s32 playerIndex = sortedNametagIndices[k]; + struct NametagInfo *nametag = &nametags[playerIndex]; + 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); + + struct StateExtras* e = &sStateExtras[playerIndex]; + if (!e->inited) { + vec3f_copy(e->prevPos, nametag->pos); + e->prevScale = nametag->scale; + e->inited = true; + } + + // Apply viewport for credits + extern Vp *gViewportOverride; + extern Vp *gViewportClip; + extern Vp gViewportFullscreen; + Vp *viewport = gViewportOverride == NULL ? gViewportClip : gViewportOverride; + if (viewport) { + make_viewport_clip_rect(viewport); + gSPViewport(gDisplayListHead++, viewport); + } + + // 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, + 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; + 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 + ); + } + + // Reset viewport + if (viewport) { + gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - BORDER_HEIGHT); + gSPViewport(gDisplayListHead++, &gViewportFullscreen); + } + + vec3f_copy(e->prevPos, nametag->pos); + e->prevScale = nametag->scale; } }