diff --git a/autogen/exposed_lists.py b/autogen/exposed_lists.py index 98b5bf351..50e836d02 100644 --- a/autogen/exposed_lists.py +++ b/autogen/exposed_lists.py @@ -51,6 +51,7 @@ "include/PR/gbi.h", "include/PR/gbi_extension.h", "src/pc/gfx/gfx_pc.h", + "src/pc/djui/djui_gfx.h", "src/engine/surface_load.h", "src/pc/lua/utils/smlua_audio_utils.h", ] @@ -117,6 +118,7 @@ "src/pc/lua/smlua_hooks.h": [ "^LUA_BEHAVIOR_.*", "MAX_HOOKED_.*", "^HOOK_RETURN_.*", "^ACTION_HOOK_.*", "^MOD_MENU_ELEMENT_.*" ], "src/pc/djui/djui_panel_menu.h": [ "RAINBOW_TEXT_LEN" ], "src/pc/mods/mod_fs.h": [ "INT_TYPE_MAX", "FLOAT_TYPE_MAX", "FILE_SEEK_MAX" ], + "src/pc/djui/djui_gfx.h": [ "MTX_" ], "src/engine/surface_load.h": [ "NUM_CELLS" ], "src/pc/network/version.h": [ "VERSION_OFFSET" ], } diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 1050eaab8..f29d67b36 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -2753,6 +2753,33 @@ CONSOLE_MESSAGE_ERROR = 2 --- @type ConsoleMessageLevel --- | `CONSOLE_MESSAGE_WARNING` --- | `CONSOLE_MESSAGE_ERROR` +CS_KEEP = -1 --- @type CombinerSource +CS_0 = 0 --- @type CombinerSource +CS_1 = 1 --- @type CombinerSource +CS_TEXTURE = 2 --- @type CombinerSource +CS_COLOR = 3 --- @type CombinerSource +CS_TEXT = 4 --- @type CombinerSource +CS_COMBINED = 5 --- @type CombinerSource +CS_NOISE = 6 --- @type CombinerSource +CS_TEXTURE_ALPHA = 7 --- @type CombinerSource +CS_COLOR_ALPHA = 8 --- @type CombinerSource +CS_TEXT_ALPHA = 9 --- @type CombinerSource +CS_COMBINED_ALPHA = 10 --- @type CombinerSource + +--- @alias CombinerSource +--- | `CS_KEEP` +--- | `CS_0` +--- | `CS_1` +--- | `CS_TEXTURE` +--- | `CS_COLOR` +--- | `CS_TEXT` +--- | `CS_COMBINED` +--- | `CS_NOISE` +--- | `CS_TEXTURE_ALPHA` +--- | `CS_COLOR_ALPHA` +--- | `CS_TEXT_ALPHA` +--- | `CS_COMBINED_ALPHA` + --- @type number ROTATION_PIVOT_X_LEFT = 0.0 diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index c3309bfd2..f47f0b668 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -3980,6 +3980,19 @@ function djui_hud_set_color(r, g, b, a) -- ... end +--- @param prevR integer +--- @param prevG integer +--- @param prevB integer +--- @param prevA integer +--- @param r integer +--- @param g integer +--- @param b integer +--- @param a integer +--- Sets the current DJUI HUD global color interpolated +function djui_hud_set_color_interpolated(prevR, prevG, prevB, prevA, r, g, b, a) + -- ... +end + --- Resets the current DJUI HUD global color function djui_hud_reset_color() -- ... @@ -4005,6 +4018,30 @@ function djui_hud_reset_text_color() -- ... end +--- @param cycles integer +--- Sets the number of cycles used by the combiner +function djui_hud_set_combiner_cycles(cycles) + -- ... +end + +--- @param cycle integer +--- @param alpha boolean +--- @param a? CombinerSource +--- @param b? CombinerSource +--- @param c? CombinerSource +--- @param d? CombinerSource +--- Sets the current DJUI HUD combiner.
+--- Each part uses the following equation: `P = (A - B) * C + D`.
+--- Cycle 2 may be used to extend the equation, with the result of the previous cycle accessible through CS_COMBINED +function djui_hud_set_combiner(cycle, alpha, a, b, c, d) + -- ... +end + +--- Resets the current DJUI HUD combiner +function djui_hud_reset_combiner() + -- ... +end + --- @return integer rotation --- @return number pivotX --- @return number pivotY @@ -4014,8 +4051,8 @@ function djui_hud_get_rotation() end --- @param rotation integer ---- @param pivotX number ---- @param pivotY number +--- @param pivotX? number +--- @param pivotY? number --- Sets the current DJUI HUD rotation function djui_hud_set_rotation(rotation, pivotX, pivotY) -- ... @@ -4161,6 +4198,38 @@ function djui_hud_reset_scissor() -- ... end +--- @param x number +--- @param y number +--- @param scaleX number +--- @param scaleY number +--- Applies a transformation (translate, rotate, scale) to subsequent DJUI HUD elements until closed +function djui_hud_transform(x, y, scaleX, scaleY) + -- ... +end + +--- @param prevX number +--- @param prevY number +--- @param prevScaleX number +--- @param prevScaleY number +--- @param x number +--- @param y number +--- @param scaleX number +--- @param scaleY number +--- Applies an interpolated transformation (translate, rotate, scale) to subsequent DJUI HUD elements until closed +function djui_hud_transform_interpolated(prevX, prevY, prevScaleX, prevScaleY, x, y, scaleX, scaleY) + -- ... +end + +--- Closes the previous transformation +function djui_hud_close_transform() + -- ... +end + +--- Resets the transformation to a fullscreen state +function djui_hud_reset_transform() + -- ... +end + --- @param message string --- @return number width --- @return number height diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 9ca604dd7..c7ff9b094 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -17,6 +17,8 @@ - [enum DialogId](#enum-DialogId) - [djui_console.h](#djui_consoleh) - [enum ConsoleMessageLevel](#enum-ConsoleMessageLevel) +- [djui_gfx.h](#djui_gfxh) + - [enum CombinerSource](#enum-CombinerSource) - [djui_hud_utils.h](#djui_hud_utilsh) - [enum HudUtilsResolution](#enum-HudUtilsResolution) - [enum HudUtilsFilter](#enum-HudUtilsFilter) @@ -1193,6 +1195,28 @@
+## [djui_gfx.h](#djui_gfx.h) + +### [enum CombinerSource](#CombinerSource) +| Identifier | Value | +| :--------- | :---- | +| CS_KEEP | -1 | +| CS_0 | 0 | +| CS_1 | 1 | +| CS_TEXTURE | 2 | +| CS_COLOR | 3 | +| CS_TEXT | 4 | +| CS_COMBINED | 5 | +| CS_NOISE | 6 | +| CS_TEXTURE_ALPHA | 7 | +| CS_COLOR_ALPHA | 8 | +| CS_TEXT_ALPHA | 9 | +| CS_COMBINED_ALPHA | 10 | + +[:arrow_up_small:](#) + +
+ ## [djui_hud_utils.h](#djui_hud_utils.h) - ROTATION_PIVOT_X_LEFT - ROTATION_PIVOT_X_CENTER diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md index bfa5ffcf9..c239b73ef 100644 --- a/docs/lua/functions-3.md +++ b/docs/lua/functions-3.md @@ -3095,6 +3095,36 @@ Sets the current DJUI HUD global color
+## [djui_hud_set_color_interpolated](#djui_hud_set_color_interpolated) + +### Description +Sets the current DJUI HUD global color interpolated + +### Lua Example +`djui_hud_set_color_interpolated(prevR, prevG, prevB, prevA, r, g, b, a)` + +### Parameters +| Field | Type | +| ----- | ---- | +| prevR | `integer` | +| prevG | `integer` | +| prevB | `integer` | +| prevA | `integer` | +| r | `integer` | +| g | `integer` | +| b | `integer` | +| a | `integer` | + +### Returns +- None + +### C Prototype +`void djui_hud_set_color_interpolated(u8 prevR, u8 prevG, u8 prevB, u8 prevA, u8 r, u8 g, u8 b, u8 a);` + +[:arrow_up_small:](#) + +
+ ## [djui_hud_reset_color](#djui_hud_reset_color) ### Description @@ -3184,6 +3214,80 @@ Resets the current DJUI HUD text default color. This color is overridden by colo
+## [djui_hud_set_combiner_cycles](#djui_hud_set_combiner_cycles) + +### Description +Sets the number of cycles used by the combiner + +### Lua Example +`djui_hud_set_combiner_cycles(cycles)` + +### Parameters +| Field | Type | +| ----- | ---- | +| cycles | `integer` | + +### Returns +- None + +### C Prototype +`void djui_hud_set_combiner_cycles(u8 cycles);` + +[:arrow_up_small:](#) + +
+ +## [djui_hud_set_combiner](#djui_hud_set_combiner) + +### Description +Sets the current DJUI HUD combiner. +Each part uses the following equation: `P = (A - B) * C + D`. +Cycle 2 may be used to extend the equation, with the result of the previous cycle accessible through CS_COMBINED + +### Lua Example +`djui_hud_set_combiner(cycle, alpha, a, b, c, d)` + +### Parameters +| Field | Type | +| ----- | ---- | +| cycle | `integer` | +| alpha | `boolean` | +| a | [enum CombinerSource](constants.md#enum-CombinerSource) | +| b | [enum CombinerSource](constants.md#enum-CombinerSource) | +| c | [enum CombinerSource](constants.md#enum-CombinerSource) | +| d | [enum CombinerSource](constants.md#enum-CombinerSource) | + +### Returns +- None + +### C Prototype +`void djui_hud_set_combiner(u8 cycle, bool alpha, OPTIONAL enum CombinerSource a, OPTIONAL enum CombinerSource b, OPTIONAL enum CombinerSource c, OPTIONAL enum CombinerSource d);` + +[:arrow_up_small:](#) + +
+ +## [djui_hud_reset_combiner](#djui_hud_reset_combiner) + +### Description +Resets the current DJUI HUD combiner + +### Lua Example +`djui_hud_reset_combiner()` + +### Parameters +- None + +### Returns +- None + +### C Prototype +`void djui_hud_reset_combiner();` + +[:arrow_up_small:](#) + +
+ ## [djui_hud_get_rotation](#djui_hud_get_rotation) ### Description @@ -3226,7 +3330,7 @@ Sets the current DJUI HUD rotation - None ### C Prototype -`void djui_hud_set_rotation(s16 rotation, f32 pivotX, f32 pivotY);` +`void djui_hud_set_rotation(s16 rotation, OPTIONAL f32 pivotX, OPTIONAL f32 pivotY);` [:arrow_up_small:](#) @@ -3701,6 +3805,104 @@ Resets the scissor rectangle to a fullscreen state
+## [djui_hud_transform](#djui_hud_transform) + +### Description +Applies a transformation (translate, rotate, scale) to subsequent DJUI HUD elements until closed + +### Lua Example +`djui_hud_transform(x, y, scaleX, scaleY)` + +### Parameters +| Field | Type | +| ----- | ---- | +| x | `number` | +| y | `number` | +| scaleX | `number` | +| scaleY | `number` | + +### Returns +- None + +### C Prototype +`void djui_hud_transform(f32 x, f32 y, f32 scaleX, f32 scaleY);` + +[:arrow_up_small:](#) + +
+ +## [djui_hud_transform_interpolated](#djui_hud_transform_interpolated) + +### Description +Applies an interpolated transformation (translate, rotate, scale) to subsequent DJUI HUD elements until closed + +### Lua Example +`djui_hud_transform_interpolated(prevX, prevY, prevScaleX, prevScaleY, x, y, scaleX, scaleY)` + +### Parameters +| Field | Type | +| ----- | ---- | +| prevX | `number` | +| prevY | `number` | +| prevScaleX | `number` | +| prevScaleY | `number` | +| x | `number` | +| y | `number` | +| scaleX | `number` | +| scaleY | `number` | + +### Returns +- None + +### C Prototype +`void djui_hud_transform_interpolated(f32 prevX, f32 prevY, f32 prevScaleX, f32 prevScaleY, f32 x, f32 y, f32 scaleX, f32 scaleY);` + +[:arrow_up_small:](#) + +
+ +## [djui_hud_close_transform](#djui_hud_close_transform) + +### Description +Closes the previous transformation + +### Lua Example +`djui_hud_close_transform()` + +### Parameters +- None + +### Returns +- None + +### C Prototype +`void djui_hud_close_transform(void);` + +[:arrow_up_small:](#) + +
+ +## [djui_hud_reset_transform](#djui_hud_reset_transform) + +### Description +Resets the transformation to a fullscreen state + +### Lua Example +`djui_hud_reset_transform()` + +### Parameters +- None + +### Returns +- None + +### C Prototype +`void djui_hud_reset_transform(void);` + +[:arrow_up_small:](#) + +
+ ## [djui_hud_measure_text](#djui_hud_measure_text) ### Description diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 35ac3c04e..bff4c6e0b 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -769,10 +769,14 @@ - [djui_hud_set_font](functions-3.md#djui_hud_set_font) - [djui_hud_get_color](functions-3.md#djui_hud_get_color) - [djui_hud_set_color](functions-3.md#djui_hud_set_color) + - [djui_hud_set_color_interpolated](functions-3.md#djui_hud_set_color_interpolated) - [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_set_combiner_cycles](functions-3.md#djui_hud_set_combiner_cycles) + - [djui_hud_set_combiner](functions-3.md#djui_hud_set_combiner) + - [djui_hud_reset_combiner](functions-3.md#djui_hud_reset_combiner) - [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) @@ -796,6 +800,10 @@ - [djui_hud_reset_viewport](functions-3.md#djui_hud_reset_viewport) - [djui_hud_set_scissor](functions-3.md#djui_hud_set_scissor) - [djui_hud_reset_scissor](functions-3.md#djui_hud_reset_scissor) + - [djui_hud_transform](functions-3.md#djui_hud_transform) + - [djui_hud_transform_interpolated](functions-3.md#djui_hud_transform_interpolated) + - [djui_hud_close_transform](functions-3.md#djui_hud_close_transform) + - [djui_hud_reset_transform](functions-3.md#djui_hud_reset_transform) - [djui_hud_measure_text](functions-3.md#djui_hud_measure_text) - [djui_hud_render_texture](functions-3.md#djui_hud_render_texture) - [djui_hud_render_texture_tile](functions-3.md#djui_hud_render_texture_tile) diff --git a/src/pc/crash_handler.c b/src/pc/crash_handler.c index 7f5f51903..2390e9d38 100644 --- a/src/pc/crash_handler.c +++ b/src/pc/crash_handler.c @@ -218,8 +218,8 @@ static void crash_handler_produce_one_frame_callback(void) { 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; + s32 x = text->x * aspectScale; + s32 y = 8 + text->y * aspectScale; gDPPipeSync(gDisplayListHead++); create_dl_translation_matrix(DJUI_MTX_PUSH, x, y, 0); diff --git a/src/pc/djui/djui.c b/src/pc/djui/djui.c index 400c50f93..392830f5f 100644 --- a/src/pc/djui/djui.c +++ b/src/pc/djui/djui.c @@ -184,16 +184,17 @@ void djui_reset_hud_params(void) { djui_hud_set_text_alignment(TEXT_HALIGN_LEFT, TEXT_VALIGN_TOP); djui_hud_reset_color(); djui_hud_reset_text_color(); + djui_hud_reset_combiner(); djui_hud_set_filter(FILTER_NEAREST); djui_hud_reset_viewport(); djui_hud_reset_scissor(); + djui_hud_reset_transform(); } void djui_render(void) { if (!sDjuiInited || gDjuiDisabled) { return; } sSavedDisplayListHead = gDisplayListHead; - gDjuiHudUtilsZ = 0; djui_reset_hud_params(); create_dl_ortho_matrix(); diff --git a/src/pc/djui/djui_base.c b/src/pc/djui/djui_base.c index e4d85a506..9c9fa5745 100644 --- a/src/pc/djui/djui_base.c +++ b/src/pc/djui/djui_base.c @@ -232,7 +232,7 @@ static f32 djui_base_render_border_piece(struct DjuiBase* base, f32 x1, f32 y1, // translate position f32 translatedX = x1; f32 translatedY = y1; - djui_gfx_position_translate(&translatedX, &translatedY); + djui_gfx_dimension_translate(&translatedX, &translatedY); create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0); // translate size @@ -242,6 +242,7 @@ static f32 djui_base_render_border_piece(struct DjuiBase* base, f32 x1, f32 y1, create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedWidth, translatedHeight, 1.0f); // render + djui_gfx_update_combine_mode(CS_COLOR); gDPSetEnvColor(gDisplayListHead++, base->borderColor.r, base->borderColor.g, base->borderColor.b, base->borderColor.a); gSPDisplayList(gDisplayListHead++, dl_djui_simple_rect); diff --git a/src/pc/djui/djui_gfx.c b/src/pc/djui/djui_gfx.c index aa5332970..48b9caef3 100644 --- a/src/pc/djui/djui_gfx.c +++ b/src/pc/djui/djui_gfx.c @@ -21,45 +21,131 @@ const Gfx dl_djui_display_list_end[] = { gsSPEndDisplayList(), }; +static Mat4 sDjuiCoordinateMtx = { + { 1, 0, 0, 0 }, + { 0, -1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 240, 0, 1 }, +}; + void djui_gfx_displaylist_begin(void) { gSPDisplayList(gDisplayListHead++, dl_djui_display_list_begin); + + // translate to DJUI coordinate system + sDjuiCoordinateMtx[3][0] = GFX_DIMENSIONS_FROM_LEFT_EDGE(0); + gSPMatrix(gDisplayListHead++, (Mtx*) &sDjuiCoordinateMtx, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH); } void djui_gfx_displaylist_end(void) { gSPDisplayList(gDisplayListHead++, dl_djui_display_list_end); + gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); +} + +struct CombinerState gCombinerState = { .cycles = 1 }; +bool gCombinerUpdated = false; +bool gCombinerOverride = false; +static Gfx sDjuiCombineMode = { 0 }; +static u32 sCombinerCycleType = G_CYC_1CYCLE; + +static u8 djui_gfx_translate_combiner_source(u8 cycle, bool alpha, enum CombinerSource source) { + if (!alpha) { + switch (source) { + default: return G_CCMUX_0; + case CS_1: return G_CCMUX_1; + case CS_TEXTURE: return cycle ? G_CCMUX_TEXEL1 : G_CCMUX_TEXEL0; + case CS_COLOR: return G_CCMUX_ENVIRONMENT; + case CS_TEXT: return G_CCMUX_PRIMITIVE; + case CS_COMBINED: return G_CCMUX_COMBINED; + case CS_NOISE: return G_CCMUX_NOISE; + case CS_TEXTURE_ALPHA: return cycle ? G_CCMUX_TEXEL1_ALPHA : G_CCMUX_TEXEL0_ALPHA; + case CS_COLOR_ALPHA: return G_CCMUX_ENV_ALPHA; + case CS_TEXT_ALPHA: return G_CCMUX_PRIMITIVE_ALPHA; + case CS_COMBINED_ALPHA: return G_CCMUX_COMBINED_ALPHA; + } + } else { + switch (source) { + default: return G_ACMUX_0; + case CS_1: return G_ACMUX_1; + case CS_TEXTURE: + case CS_TEXTURE_ALPHA: return cycle ? G_ACMUX_TEXEL1 : G_ACMUX_TEXEL0; + case CS_COLOR: + case CS_COLOR_ALPHA: return G_ACMUX_ENVIRONMENT; + case CS_TEXT: + case CS_TEXT_ALPHA: return G_ACMUX_PRIMITIVE; + case CS_COMBINED: + case CS_COMBINED_ALPHA: return G_ACMUX_COMBINED; + } + + } +} + +void djui_gfx_update_combine_mode(enum CombinerSource mode) { + u32 cycleType = G_CYC_1CYCLE; + + if (gCombinerOverride) { + cycleType = (gCombinerState.cycles - 1) << G_MDSFT_CYCLETYPE; + + if (gCombinerUpdated) { + u8 p[16]; + for (u8 i = 0; i < 8 * gCombinerState.cycles; i++) { + p[i] = djui_gfx_translate_combiner_source(i >> 3, i >> 2 & 1, + gCombinerState.cycle[i >> 3][i >> 2 & 1][i & 3]); + } + + gDPSetCombineLERPNoString(&sDjuiCombineMode, + p[ 0], p[ 1], p[ 2], p[ 3], + p[ 4], p[ 5], p[ 6], p[ 7], + p[ 8], p[ 9], p[10], p[11], + p[12], p[13], p[14], p[15] + ); + gCombinerUpdated = false; + } + + *(gDisplayListHead++) = sDjuiCombineMode; + } else switch (mode) { + case CS_COLOR: gDPSetCombineMode(gDisplayListHead++, G_CC_FADE, G_CC_PASS2); break; + case CS_TEXTURE: gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_PASS2); break; + case CS_TEXT: gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_MODULATERGBA_PRIM2); cycleType = G_CYC_2CYCLE; break; + default: break; + } + + if (sCombinerCycleType != cycleType) { + gDPSetCycleType(gDisplayListHead++, cycleType); + sCombinerCycleType = cycleType; + } } static const Vtx vertex_djui_menu_rect[] = { - {{{ 0, -1, 0 }, 0, { 0, 0 }, { 0x96, 0x96, 0x96, 0xff }}}, - {{{ 1, -1, 0 }, 0, { 0, 0 }, { 0x96, 0x96, 0x96, 0xff }}}, - {{{ 1, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, 1, 0 }, 0, { 0, 0 }, { 0x96, 0x96, 0x96, 0xff }}}, + {{{ 1, 1, 0 }, 0, { 0, 0 }, { 0x96, 0x96, 0x96, 0xff }}}, + {{{ 1, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, }; static const Vtx vertex_djui_simple_rect[] = { - {{{ 0, -1, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 1, -1, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 1, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, 1, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 1, 1, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 1, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, }; const Gfx dl_djui_menu_rect[] = { gsDPPipeSync(), - gsSPClearGeometryMode(G_LIGHTING), - gsDPSetCombineMode(G_CC_FADE, G_CC_FADE), + gsSPClearGeometryMode(G_LIGHTING | G_CULL_BOTH), gsDPSetRenderMode(G_RM_XLU_SURF, G_RM_XLU_SURF2), gsSPVertexNonGlobal(vertex_djui_menu_rect, 4, 0), gsSP2Triangles(0, 1, 2, 0x0, 0, 2, 3, 0x0), + gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK), gsSPEndDisplayList(), }; const Gfx dl_djui_simple_rect[] = { gsDPPipeSync(), - gsSPClearGeometryMode(G_LIGHTING), - gsDPSetCombineMode(G_CC_FADE, G_CC_FADE), + gsSPClearGeometryMode(G_LIGHTING | G_CULL_BOTH), gsDPSetRenderMode(G_RM_XLU_SURF, G_RM_XLU_SURF2), gsSPVertexNonGlobal(vertex_djui_simple_rect, 4, 0), gsSP2Triangles(0, 1, 2, 0x0, 0, 2, 3, 0x0), + gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK), gsSPEndDisplayList(), }; @@ -86,16 +172,15 @@ f32 djui_gfx_get_scale(void) { ///////////////////////////////////////////// static const Vtx vertex_djui_image[] = { - {{{ 0, -1, 0 }, 0, { 0, 2048 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 1, -1, 0 }, 0, { 2048, 2048 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 1, 0, 0 }, 0, { 2048, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, - {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, 1, 0 }, 0, { 0, 2048 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 1, 1, 0 }, 0, { 2048, 2048 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 1, 0, 0 }, 0, { 2048, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, + {{{ 0, 0, 0 }, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}}, }; const Gfx dl_djui_image[] = { gsDPPipeSync(), gsSPClearGeometryMode(G_LIGHTING | G_CULL_BOTH), - gsDPSetCombineMode(G_CC_FADEA, G_CC_FADEA), gsDPSetRenderMode(G_RM_XLU_SURF, G_RM_XLU_SURF2), gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON), gsDPLoadTextureBlock(NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0), @@ -104,7 +189,7 @@ const Gfx dl_djui_image[] = { // gsSPExecuteDjui(G_TEXCLIP_DJUI), gsSP2Triangles(0, 1, 2, 0x0, 0, 2, 3, 0x0), gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), - gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE), + gsDPSetCombineMode(G_CC_SHADE, G_CC_PASS2), gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK), gsSPEndDisplayList(), }; @@ -114,6 +199,7 @@ inline static u8 djui_gfx_power_of_two(u32 value) { } void djui_gfx_render_texture(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, bool filter) { + djui_gfx_update_combine_mode(CS_TEXTURE); gDPSetTextureFilter(gDisplayListHead++, filter ? G_TF_BILERP : G_TF_POINT); gDPSetTextureOverrideDjui(gDisplayListHead++, texture, djui_gfx_power_of_two(w), djui_gfx_power_of_two(h), fmt, siz); gSPDisplayList(gDisplayListHead++, dl_djui_image); @@ -138,13 +224,13 @@ void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt, f32 aspect = tileH ? ((f32)tileW / (f32)tileH) : 1; - vtx[0] = (Vtx) {{{ 0, -1, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + 1, ((tileY + tileH) * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[2] = (Vtx) {{{ 1 * aspect, 0, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + 1, ( tileY * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[1] = (Vtx) {{{ 1 * aspect, -1, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + 1, ((tileY + tileH) * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[3] = (Vtx) {{{ 0, 0, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + 1, ( tileY * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[0] = (Vtx) {{{ 0, 1, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + 1, ((tileY + tileH) * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[2] = (Vtx) {{{ 1 * aspect, 0, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + 1, ( tileY * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[1] = (Vtx) {{{ 1 * aspect, 1, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + 1, ((tileY + tileH) * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[3] = (Vtx) {{{ 0, 0, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + 1, ( tileY * 2048.0f) / (f32)h + 1 }, { 0xff, 0xff, 0xff, 0xff }}}; gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BOTH); - gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_FADEA); + djui_gfx_update_combine_mode(CS_TEXTURE); gDPSetRenderMode(gDisplayListHead++, G_RM_XLU_SURF, G_RM_XLU_SURF2); gDPSetTextureFilter(gDisplayListHead++, filter ? G_TF_BILERP : G_TF_POINT); @@ -160,14 +246,13 @@ void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt, gSP2TrianglesDjui(gDisplayListHead++, 0, 1, 2, 0x0, 0, 2, 3, 0x0); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); - gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); + gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_PASS2); gSPSetGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BACK); } void djui_gfx_render_texture_font_begin() { gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BOTH); - gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_MODULATERGBA_PRIM2); - gDPSetCycleType(gDisplayListHead++, G_CYC_2CYCLE); + djui_gfx_update_combine_mode(CS_TEXT); 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,15 +278,13 @@ 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); + gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_PASS2); 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_MODULATERGBA_PRIM2); - gDPSetCycleType(gDisplayListHead++, G_CYC_2CYCLE); + djui_gfx_update_combine_mode(CS_TEXT); 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); @@ -231,10 +314,10 @@ void djui_gfx_render_texture_tile_font(const Texture* texture, u32 w, u32 h, u8 // this should be tested carefully. it definitely fixes some stuff, but what does it break? f32 offsetX = (-1024.0f / (f32)w) + 1; f32 offsetY = (-1024.0f / (f32)h) + 1; - vtx[0] = (Vtx) {{{ 0, -1, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + offsetX, ((tileY + tileH) * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[2] = (Vtx) {{{ 1 * aspect, 0, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + offsetX, ( tileY * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[1] = (Vtx) {{{ 1 * aspect, -1, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + offsetX, ((tileY + tileH) * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; - vtx[3] = (Vtx) {{{ 0, 0, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + offsetX, ( tileY * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[0] = (Vtx) {{{ 0, 1, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + offsetX, ((tileY + tileH) * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[2] = (Vtx) {{{ 1 * aspect, 0, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + offsetX, ( tileY * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[1] = (Vtx) {{{ 1 * aspect, 1, 0 }, 0, { ((tileX + tileW) * 2048.0f) / (f32)w + offsetX, ((tileY + tileH) * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; + vtx[3] = (Vtx) {{{ 0, 0, 0 }, 0, { ( tileX * 2048.0f) / (f32)w + offsetX, ( tileY * 2048.0f) / (f32)h + offsetY }, { 0xff, 0xff, 0xff, 0xff }}}; gDPSetTextureOverrideDjui(gDisplayListHead++, texture, djui_gfx_power_of_two(w), djui_gfx_power_of_two(h), fmt, siz); *(gDisplayListHead++) = (Gfx) gsSPExecuteDjui(G_TEXOVERRIDE_DJUI); @@ -245,33 +328,33 @@ 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); + gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_PASS2); gSPSetGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BACK); } ///////////////////////////////////////////// -void djui_gfx_position_translate(f32* x, f32* y) { +void djui_gfx_dimension_translate(f32* x, f32* y) { u32 windowWidth, windowHeight; gfx_get_dimensions(&windowWidth, &windowHeight); - *x = GFX_DIMENSIONS_FROM_LEFT_EDGE(0) + *x * ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); - *y = SCREEN_HEIGHT - *y * ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); + + *x *= ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); + *y *= ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); } void djui_gfx_scale_translate(f32* width, f32* height) { u32 windowWidth, windowHeight; gfx_get_dimensions(&windowWidth, &windowHeight); - *width = *width * ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); - *height = *height * ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); + *width *= ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); + *height *= ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); } void djui_gfx_size_translate(f32* size) { u32 windowWidth, windowHeight; gfx_get_dimensions(&windowWidth, &windowHeight); - *size = *size * ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); + *size *= ((f32)SCREEN_HEIGHT / (f32)windowHeight) * djui_gfx_get_scale(); } bool djui_gfx_add_clipping_specific(struct DjuiBase* base, f32 dX, f32 dY, f32 dW, f32 dH) { diff --git a/src/pc/djui/djui_gfx.h b/src/pc/djui/djui_gfx.h index 2df6786e9..2db320c9b 100644 --- a/src/pc/djui/djui_gfx.h +++ b/src/pc/djui/djui_gfx.h @@ -13,6 +13,37 @@ extern const Gfx dl_djui_img_end[]; void djui_gfx_displaylist_begin(void); void djui_gfx_displaylist_end(void); +enum CombinerSource { + CS_KEEP = -1, + CS_0, + CS_1, + CS_TEXTURE, // TEXEL0 + CS_COLOR, // ENVIRONMENT + CS_TEXT, // PRIMITIVE + CS_COMBINED, // COMBINED + CS_NOISE, // NOISE + CS_TEXTURE_ALPHA, // TEXEL0_ALPHA + CS_COLOR_ALPHA, // ENV_ALPHA + CS_TEXT_ALPHA, // PRIMITIVE_ALPHA + CS_COMBINED_ALPHA, // COMBINED_ALPHA +}; + +struct CombinerPart { + enum CombinerSource a, b, c, d; +}; + +typedef enum CombinerSource CombinerCycle[2][4]; + +struct CombinerState { + CombinerCycle cycle[2]; + u8 cycles; +}; + +extern struct CombinerState gCombinerState; +extern bool gCombinerUpdated; +extern bool gCombinerOverride; +void djui_gfx_update_combine_mode(enum CombinerSource mode); + /* |description|Gets the current visual scaling factor of DJUI|descriptionEnd| */ f32 djui_gfx_get_scale(void); @@ -29,7 +60,7 @@ void djui_gfx_render_texture_tile_font_end(); void gfx_get_dimensions(u32* width, u32* height); -void djui_gfx_position_translate(f32* x, f32* y); +void djui_gfx_dimension_translate(f32* x, f32* y); void djui_gfx_scale_translate(f32* width, f32* height); void djui_gfx_size_translate(f32* size); diff --git a/src/pc/djui/djui_hud_utils.c b/src/pc/djui/djui_hud_utils.c index b29bf3b3a..a0d582e38 100644 --- a/src/pc/djui/djui_hud_utils.c +++ b/src/pc/djui/djui_hud_utils.c @@ -25,11 +25,20 @@ #include "engine/math_util.h" #define INTERP_INIT(v) {v, v} +#define INTERP_SET(field, p, c) field.prev = p; field.curr = c; +#define INTERP_RESET(field, c) field.prev = field.curr = c; +#define INTERP_MUL(field, m) field.prev *= m.prev; field.curr *= m.curr; +#define IS_INTERP_VAL(field, v) (field.prev == v && field.curr == v) +#define IS_INTERP_SAME(field) (field.prev == field.curr) typedef struct { f32 prev, curr; } InterpFieldF32; +typedef struct { + s16 prev, curr; +} InterpFieldS16; + struct HudUtilsState { enum HudUtilsResolution resolution; enum HudUtilsFilter filter; @@ -37,7 +46,7 @@ struct HudUtilsState { struct DjuiColor color; struct DjuiColor textColor; struct { - InterpFieldF32 degrees; + InterpFieldS16 units; InterpFieldF32 pivotX; InterpFieldF32 pivotY; } rotation; @@ -54,7 +63,7 @@ static struct HudUtilsState sHudUtilsState = { .color = { 255, 255, 255, 255 }, .textColor = { 255, 255, 255, 255 }, .rotation = { - .degrees = INTERP_INIT(0), + .units = INTERP_INIT(0), .pivotX = INTERP_INIT(ROTATION_PIVOT_X_LEFT), .pivotY = INTERP_INIT(ROTATION_PIVOT_Y_TOP), }, @@ -67,7 +76,6 @@ 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; extern ALIGNED8 const u8 texture_hud_char_camera[]; @@ -110,12 +118,9 @@ static inline bool djui_hud_text_font_is_legacy() { return sHudUtilsState.font < 0; } -static void djui_hud_position_translate(f32* x, f32* y) { +static void djui_hud_dimension_translate(f32* x, f32* y) { if (sHudUtilsState.resolution == RESOLUTION_DJUI) { - djui_gfx_position_translate(x, y); - } else { - *x = GFX_DIMENSIONS_FROM_LEFT_EDGE(0) + *x; - *y = SCREEN_HEIGHT - *y; + djui_gfx_dimension_translate(x, y); } } @@ -128,9 +133,7 @@ static void djui_hud_size_translate(f32* size) { // Translates position and scale to N64 resolution static void djui_hud_translate_positions(f32 *outX, f32 *outY, f32 *outW, f32 *outH) { // translate position - djui_hud_position_translate(outX, outY); - *outX -= GFX_DIMENSIONS_FROM_LEFT_EDGE(0); - *outY -= SCREEN_HEIGHT; + djui_hud_dimension_translate(outX, outY); // translate scale if (sHudUtilsState.resolution == RESOLUTION_DJUI) { @@ -154,6 +157,7 @@ enum InterpHudType { INTERP_HUD_HALIGN, INTERP_HUD_VALIGN, INTERP_HUD_NEW_LINE, + INTERP_HUD_COLOR, }; typedef struct { @@ -163,14 +167,41 @@ typedef struct { } InterpHudGfx; struct InterpHud { - f32 z; - InterpFieldF32 posX, posY; - InterpFieldF32 scaleX, scaleY; + bool noMtx; + union { + struct { + InterpFieldF32 posX, posY; + InterpFieldF32 scaleX, scaleY; + }; + struct { + InterpFieldF32 r, g, b, a; + }; + }; f32 width, height; struct HudUtilsState state; struct GrowingArray *gfx; }; +static bool sDjuiHudMtxPushed = false; +static inline void djui_hud_setup_matrix() { + sDjuiHudMtxPushed = false; +} + +static s8 djui_hud_pass_matrix() { + if (sDjuiHudMtxPushed) { + return DJUI_MTX_NOPUSH; + } else { + sDjuiHudMtxPushed = true; + return DJUI_MTX_PUSH; + } +} + +static inline void djui_hud_pop_matrix(struct InterpHud *interp) { + if (sDjuiHudMtxPushed) { + gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); + } else if (interp) { gSPNoOp(gDisplayListHead++); } +} + static struct GrowingArray *sInterpHuds = NULL; static u32 sInterpHudCount = 0; @@ -187,7 +218,6 @@ void patch_djui_hud_before(void) { } void patch_djui_hud(f32 delta) { - f32 savedZ = gDjuiHudUtilsZ; Gfx* savedHeadPos = gDisplayListHead; struct HudUtilsState savedState = sHudUtilsState; @@ -199,7 +229,7 @@ void patch_djui_hud(f32 delta) { f32 scaleW = delta_interpolate_f32(interp->scaleX.prev, interp->scaleX.curr, delta); f32 scaleH = delta_interpolate_f32(interp->scaleY.prev, interp->scaleY.curr, delta); sHudUtilsState = interp->state; - gDjuiHudUtilsZ = interp->z; + djui_hud_setup_matrix(); for (u32 j = 0; j != interp->gfx->count; ++j) { const InterpHudGfx *gfx = interp->gfx->buffer[j]; @@ -207,38 +237,30 @@ void patch_djui_hud(f32 delta) { switch (gfx->type) { case INTERP_HUD_TRANSLATION: { - f32 translatedX = x; - f32 translatedY = y; - djui_hud_position_translate(&translatedX, &translatedY); - create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ); + djui_hud_dimension_translate(&x, &y); + create_dl_translation_matrix(djui_hud_pass_matrix(), x, y, 0); } break; case INTERP_HUD_ROTATION: { - if (sHudUtilsState.rotation.degrees.prev != 0 || sHudUtilsState.rotation.degrees.curr != 0) { - f32 translatedW = scaleW; - f32 translatedH = scaleH; - djui_hud_size_translate(&translatedW); - djui_hud_size_translate(&translatedH); - s16 rotPrev = degrees_to_sm64(sHudUtilsState.rotation.degrees.prev); - s16 rotCurr = degrees_to_sm64(sHudUtilsState.rotation.degrees.curr); - s32 normalizedDiff = (((s32) rotCurr - (s32) rotPrev + 0x8000) & 0xFFFF) - 0x8000; // Fix modular overflow/underflow - s32 rotation = delta_interpolate_s32(rotCurr - normalizedDiff, rotCurr, delta); - f32 pivotX = delta_interpolate_f32(sHudUtilsState.rotation.pivotX.prev, sHudUtilsState.rotation.pivotX.curr, delta); - f32 pivotY = delta_interpolate_f32(sHudUtilsState.rotation.pivotY.prev, sHudUtilsState.rotation.pivotY.curr, delta); - f32 pivotTranslationX = interp->width * translatedW * pivotX; - f32 pivotTranslationY = interp->height * translatedH * pivotY; - create_dl_translation_matrix(DJUI_MTX_NOPUSH, +pivotTranslationX, -pivotTranslationY, 0); - create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sm64_to_degrees(rotation), 0, 0, 1); - create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0); - } + f32 translatedW = scaleW, translatedH = scaleH; + djui_hud_dimension_translate(&translatedW, &translatedH); + s16 rotPrev = sHudUtilsState.rotation.units.prev; + s16 rotCurr = sHudUtilsState.rotation.units.curr; + s32 normalizedDiff = (((s32) rotCurr - (s32) rotPrev + 0x8000) & 0xFFFF) - 0x8000; // Fix modular overflow/underflow + s32 rotation = delta_interpolate_s32(rotCurr - normalizedDiff, rotCurr, delta); + f32 pivotX = delta_interpolate_f32(sHudUtilsState.rotation.pivotX.prev, sHudUtilsState.rotation.pivotX.curr, delta); + f32 pivotY = delta_interpolate_f32(sHudUtilsState.rotation.pivotY.prev, sHudUtilsState.rotation.pivotY.curr, delta); + f32 pivotTranslationX = interp->width * translatedW * pivotX; + f32 pivotTranslationY = interp->height * translatedH * pivotY; + create_dl_translation_matrix(djui_hud_pass_matrix(), +pivotTranslationX, +pivotTranslationY, 0); + create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sm64_to_degrees(rotation), 0, 0, -1); + create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, -pivotTranslationY, 0); } break; case INTERP_HUD_SCALE: { - f32 translatedW = scaleW; - f32 translatedH = scaleH; - djui_hud_size_translate(&translatedW); - djui_hud_size_translate(&translatedH); - create_dl_scale_matrix(DJUI_MTX_NOPUSH, interp->width * translatedW, interp->height * translatedH, 1.0f); + f32 translatedW = scaleW, translatedH = scaleH; + djui_hud_dimension_translate(&translatedW, &translatedH); + create_dl_scale_matrix(djui_hud_pass_matrix(), interp->width * translatedW, interp->height * translatedH, 1.0f); } break; case INTERP_HUD_HALIGN: { @@ -250,22 +272,27 @@ void patch_djui_hud(f32 delta) { case INTERP_HUD_VALIGN: { f32 textVAlign = delta_interpolate_f32(sHudUtilsState.textAlignment.v.prev, sHudUtilsState.textAlignment.v.curr, delta); f32 textHeight = gfx->params[0]; - create_dl_translation_matrix(DJUI_MTX_NOPUSH, 0, textHeight * textVAlign, 0); + create_dl_translation_matrix(DJUI_MTX_NOPUSH, 0, -textHeight * textVAlign, 0); } break; case INTERP_HUD_NEW_LINE: { const struct DjuiFont *font = djui_hud_get_text_font(); f32 textHAlign = delta_interpolate_f32(sHudUtilsState.textAlignment.h.prev, sHudUtilsState.textAlignment.h.curr, delta); f32 lineWidth = gfx->params[0]; - create_dl_translation_matrix(DJUI_MTX_NOPUSH, -lineWidth * (1.f - textHAlign), -font->lineHeight, 0); + create_dl_translation_matrix(DJUI_MTX_NOPUSH, -lineWidth * (1.f - textHAlign), font->lineHeight, 0); + } break; + + case INTERP_HUD_COLOR: { + gDPSetEnvColor(gDisplayListHead++, x, y, scaleW, scaleH); } break; } } + + if (!interp->noMtx) { djui_hud_pop_matrix(interp); } } sHudUtilsState = savedState; gDisplayListHead = savedHeadPos; - gDjuiHudUtilsZ = savedZ; } static struct InterpHud *djui_hud_create_interp() { @@ -276,7 +303,6 @@ static struct InterpHud *djui_hud_create_interp() { ); if (interp) { - interp->z = gDjuiHudUtilsZ; interp->state = sHudUtilsState; if (!interp->gfx) { interp->gfx = growing_array_init(NULL, 8, malloc, free); @@ -303,6 +329,51 @@ void djui_hud_clear_interp_data() { sInterpHudCount = 0; } +static inline void djui_hud_do_translation(struct InterpHud *interp, f32 x, f32 y) { + bool doInterp = interp && !(IS_INTERP_SAME(interp->posX) && IS_INTERP_SAME(interp->posY)); + if (doInterp || !(x == 0 && y == 0)) { + if (doInterp) { djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION); } + + djui_hud_dimension_translate(&x, &y); + create_dl_translation_matrix(djui_hud_pass_matrix(), x, y, 0); + } +} + +static inline void djui_hud_do_rotation(struct InterpHud *interp, f32 width, f32 height) { + if (IS_INTERP_VAL(sHudUtilsState.rotation.units, 0)) { return; } + + bool doInterp = interp && !( + IS_INTERP_SAME(sHudUtilsState.rotation.units) + && IS_INTERP_SAME(sHudUtilsState.rotation.pivotX) + && IS_INTERP_SAME(sHudUtilsState.rotation.pivotY) + ); + + djui_hud_dimension_translate(&width, &height); + + if (doInterp) { djui_hud_create_interp_gfx(interp, INTERP_HUD_ROTATION); } + + f32 pivotTranslationX = width * sHudUtilsState.rotation.pivotX.curr; + f32 pivotTranslationY = height * sHudUtilsState.rotation.pivotY.curr; + + create_dl_translation_matrix(djui_hud_pass_matrix(), +pivotTranslationX, +pivotTranslationY, 0); + create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sm64_to_degrees(sHudUtilsState.rotation.units.curr), 0, 0, -1); + create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, -pivotTranslationY, 0); +} + +static inline void djui_hud_do_scale(struct InterpHud *interp, f32 scaleX, f32 scaleY) { + bool doInterp = interp && !( + IS_INTERP_SAME(interp->scaleX) + && IS_INTERP_SAME(interp->scaleY) + ); + + if (doInterp || !(scaleX == 1 && scaleY == 1)) { + if (doInterp) { djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE); } + + djui_hud_dimension_translate(&scaleX, &scaleY); + create_dl_scale_matrix(djui_hud_pass_matrix(), scaleX, scaleY, 1.0f); + } +} + //////////// // others // //////////// @@ -350,6 +421,21 @@ void djui_hud_set_color(u8 r, u8 g, u8 b, u8 a) { gDPSetEnvColor(gDisplayListHead++, r, g, b, a); } +void djui_hud_set_color_interpolated(u8 prevR, u8 prevG, u8 prevB, u8 prevA, u8 r, u8 g, u8 b, u8 a) { + struct InterpHud *interp = djui_hud_create_interp(); + if (interp) { + INTERP_SET(interp->r, prevR, r); + INTERP_SET(interp->g, prevG, g); + INTERP_SET(interp->b, prevB, b); + INTERP_SET(interp->a, prevA, a); + interp->noMtx = true; + + djui_hud_create_interp_gfx(interp, INTERP_HUD_COLOR); + } + + djui_hud_set_color(r, g, b, a); +} + void djui_hud_reset_color(void) { sHudUtilsState.color.r = 255; sHudUtilsState.color.g = 255; @@ -380,25 +466,45 @@ void djui_hud_reset_text_color(void) { sHudUtilsState.textColor.a = 255; } +void djui_hud_set_combiner_cycles(u8 cycles) { + gCombinerState.cycles = cycles != 2 ? 1 : 2; +} + +void djui_hud_set_combiner(u8 cycle, bool alpha, + OPTIONAL enum CombinerSource a, OPTIONAL enum CombinerSource b, OPTIONAL enum CombinerSource c, OPTIONAL enum CombinerSource d) { + if (--cycle > 1) { return; } + + struct CombinerPart *part = (struct CombinerPart*) gCombinerState.cycle[cycle][alpha]; + if (a > CS_KEEP) { part->a = a; } + if (b > CS_KEEP) { part->b = b; } + if (c > CS_KEEP) { part->c = c; } + if (d > CS_KEEP) { part->d = d; } + + gCombinerUpdated = true; + gCombinerOverride = true; +} + +void djui_hud_reset_combiner() { + gCombinerState.cycles = 1; + gCombinerOverride = false; +} + void djui_hud_get_rotation(RET s16 *rotation, RET f32 *pivotX, RET f32 *pivotY) { - *rotation = degrees_to_sm64(sHudUtilsState.rotation.degrees.curr); + *rotation = sHudUtilsState.rotation.units.curr; *pivotX = sHudUtilsState.rotation.pivotX.curr; *pivotY = sHudUtilsState.rotation.pivotY.curr; } -void djui_hud_set_rotation(s16 rotation, f32 pivotX, f32 pivotY) { - sHudUtilsState.rotation.degrees.prev = sHudUtilsState.rotation.degrees.curr = sm64_to_degrees(rotation); - sHudUtilsState.rotation.pivotX.prev = sHudUtilsState.rotation.pivotX.curr = pivotX; - sHudUtilsState.rotation.pivotY.prev = sHudUtilsState.rotation.pivotY.curr = pivotY; +void djui_hud_set_rotation(s16 rotation, OPTIONAL f32 pivotX, OPTIONAL f32 pivotY) { + INTERP_RESET(sHudUtilsState.rotation.units, rotation); + INTERP_RESET(sHudUtilsState.rotation.pivotX, pivotX); + INTERP_RESET(sHudUtilsState.rotation.pivotY, pivotY); } void djui_hud_set_rotation_interpolated(s16 prevRotation, f32 prevPivotX, f32 prevPivotY, s16 rotation, f32 pivotX, f32 pivotY) { - sHudUtilsState.rotation.degrees.prev = sm64_to_degrees(prevRotation); - sHudUtilsState.rotation.degrees.curr = sm64_to_degrees(rotation); - sHudUtilsState.rotation.pivotX.prev = prevPivotX; - sHudUtilsState.rotation.pivotX.curr = pivotX; - sHudUtilsState.rotation.pivotY.prev = prevPivotY; - sHudUtilsState.rotation.pivotY.curr = pivotY; + INTERP_SET(sHudUtilsState.rotation.units, prevRotation, rotation); + INTERP_SET(sHudUtilsState.rotation.pivotX, prevPivotX, pivotX); + INTERP_SET(sHudUtilsState.rotation.pivotY, prevPivotY, pivotY); } void djui_hud_get_text_alignment(RET f32 *textHAlign, RET f32 *textVAlign) { @@ -407,33 +513,33 @@ void djui_hud_get_text_alignment(RET f32 *textHAlign, RET f32 *textVAlign) { } void djui_hud_set_text_alignment(f32 textHAlign, f32 textVAlign) { - sHudUtilsState.textAlignment.h.prev = sHudUtilsState.textAlignment.h.curr = textHAlign; - sHudUtilsState.textAlignment.v.prev = sHudUtilsState.textAlignment.v.curr = textVAlign; + INTERP_RESET(sHudUtilsState.textAlignment.h, textHAlign); + INTERP_RESET(sHudUtilsState.textAlignment.v, textVAlign); } void djui_hud_set_text_alignment_interpolated(f32 prevTextHAlign, f32 prevTextVAlign, f32 textHAlign, f32 textVAlign) { - sHudUtilsState.textAlignment.h.prev = prevTextHAlign; - sHudUtilsState.textAlignment.h.curr = textHAlign; - sHudUtilsState.textAlignment.v.prev = prevTextVAlign; - sHudUtilsState.textAlignment.v.curr = textVAlign; + INTERP_SET(sHudUtilsState.textAlignment.h, prevTextHAlign, textHAlign); + INTERP_SET(sHudUtilsState.textAlignment.v, prevTextVAlign, textVAlign); } u32 djui_hud_get_screen_width(void) { - u32 windowWidth, windowHeight; - gfx_get_dimensions(&windowWidth, &windowHeight); - - return (sHudUtilsState.resolution == RESOLUTION_N64) - ? GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT - : (windowWidth / djui_gfx_get_scale()); + if (sHudUtilsState.resolution == RESOLUTION_N64) { + return SCREEN_HEIGHT * GFX_DIMENSIONS_ASPECT_RATIO; + } else { + u32 windowWidth, windowHeight; + gfx_get_dimensions(&windowWidth, &windowHeight); + return windowWidth / djui_gfx_get_scale(); + } } u32 djui_hud_get_screen_height(void) { - u32 windowWidth, windowHeight; - gfx_get_dimensions(&windowWidth, &windowHeight); - - return (sHudUtilsState.resolution == RESOLUTION_N64) - ? SCREEN_HEIGHT - : (windowHeight / djui_gfx_get_scale()); + if (sHudUtilsState.resolution == RESOLUTION_N64) { + return SCREEN_HEIGHT; + } else { + u32 windowWidth, windowHeight; + gfx_get_dimensions(&windowWidth, &windowHeight); + return windowHeight / djui_gfx_get_scale(); + } } f32 djui_hud_get_mouse_x(void) { @@ -484,8 +590,7 @@ f32 djui_hud_get_mouse_scroll_y(void) { void djui_hud_set_viewport(f32 x, f32 y, f32 width, f32 height) { // translate position and scale - f32 translatedX = x, translatedY = y, translatedW = width, translatedH = height; - djui_hud_translate_positions(&translatedX, &translatedY, &translatedW, &translatedH); + djui_hud_translate_positions(&x, &y, &width, &height); // convert to viewport structure static Vp vp = {{ @@ -493,10 +598,10 @@ void djui_hud_set_viewport(f32 x, f32 y, f32 width, f32 height) { { 640, 480, 511, 0 }, }}; Vp_t *viewport = &vp.vp; - viewport->vscale[0] = translatedW * 2.0f; - viewport->vscale[1] = translatedH * 2.0f; - viewport->vtrans[0] = (translatedW + translatedX) * 2.0f; - viewport->vtrans[1] = (translatedH + translatedY) * 2.0f; + viewport->vscale[0] = width * 2.0f; + viewport->vscale[1] = height * 2.0f; + viewport->vtrans[0] = (width + x) * 2.0f; + viewport->vtrans[1] = (height + y) * 2.0f; gSPViewport(gDisplayListHead++, &vp); } @@ -508,17 +613,76 @@ void djui_hud_reset_viewport(void) { void djui_hud_set_scissor(f32 x, f32 y, f32 width, f32 height) { // translate position and scale - f32 translatedX = x, translatedY = y, translatedW = width, translatedH = height; - djui_hud_translate_positions(&translatedX, &translatedY, &translatedW, &translatedH); + djui_hud_translate_positions(&x, &y, &width, &height); // apply the scissor - gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, translatedX, translatedY, translatedW, translatedH); + gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, x, y, width, height); } void djui_hud_reset_scissor(void) { gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - BORDER_HEIGHT); } +static u8 sTransformDepth = 0; + +static void djui_hud_transform_internal(f32 x, f32 y, f32 scaleX, f32 scaleY, struct InterpHud *interp) { + if (sTransformDepth == MAX_MATRIX_STACK_SIZE - 3) { return; } + djui_hud_setup_matrix(); + + // translate + djui_hud_do_translation(interp, x, y); + + // rotate + enum HudUtilsResolution origResolution = sHudUtilsState.resolution; + sHudUtilsState.resolution = RESOLUTION_N64; + djui_hud_do_rotation(interp, + SCREEN_HEIGHT * GFX_DIMENSIONS_ASPECT_RATIO * scaleX, + SCREEN_HEIGHT * scaleY); + sHudUtilsState.resolution = origResolution; + + // scale + djui_hud_do_scale(interp, scaleX, scaleY); + + if (sDjuiHudMtxPushed) { sTransformDepth++; } +} + +void djui_hud_transform(f32 x, f32 y, f32 scaleX, f32 scaleY) { + djui_hud_transform_internal(x, y, scaleX, scaleY, NULL); +} + +void djui_hud_transform_interpolated(f32 prevX, f32 prevY, f32 prevScaleX, f32 prevScaleY, f32 x, f32 y, f32 scaleX, f32 scaleY) { + struct InterpHud *interp = djui_hud_create_interp(); + if (interp) { + interp->noMtx = true; + INTERP_SET(interp->posX, prevX, x); + INTERP_SET(interp->posY, prevY, y); + INTERP_SET(interp->scaleX, prevScaleX, scaleX); + INTERP_SET(interp->scaleY, prevScaleY, scaleY); + INTERP_MUL(interp->state.rotation.pivotX, interp->scaleX); + INTERP_MUL(interp->state.rotation.pivotY, interp->scaleY); + interp->state.resolution = RESOLUTION_N64; + interp->width = SCREEN_HEIGHT * GFX_DIMENSIONS_ASPECT_RATIO; + interp->height = SCREEN_HEIGHT; + } + + djui_hud_transform_internal(prevX, prevY, prevScaleX, prevScaleY, interp); +} + +void djui_hud_close_transform(void) { + if (sTransformDepth) { + gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); + sTransformDepth--; + } +} + +void djui_hud_reset_transform(void) { + if (sTransformDepth > 0) { printf("\n%i: %i", gGlobalTimer, sTransformDepth); } + while (sTransformDepth) { + gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); + sTransformDepth--; + } +} + 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(); @@ -575,7 +739,6 @@ static Mtx *allocate_dl_translation_matrix() { 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 fontScaleX = font->defaultFontScale * scaleX; @@ -586,30 +749,23 @@ static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32 gSPDisplayList(gDisplayListHead++, font->textBeginDisplayList); } - // translate position - djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION); - 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); + djui_hud_setup_matrix(); + + // translate + x += (font->xOffset * scaleX); y += (font->yOffset * scaleY); + djui_hud_do_translation(interp, x, y); // rotate - 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 * 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); + f32 width, height; + djui_hud_measure_text(message, &width, &height); + if (interp) { + interp->width = width; + interp->height = height; } + djui_hud_do_rotation(interp, width * scaleX, height * scaleY); // compute font size - djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE); - create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSizeX, translatedFontSizeY, 1.0f); + djui_hud_do_scale(interp, fontScaleX, fontScaleY); // allocate the translation matrix for the vertical alignment InterpHudGfx *valignGfx = djui_hud_create_interp_gfx(interp, INTERP_HUD_VALIGN); @@ -707,8 +863,7 @@ static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32 guTranslate(valignMatrix, 0, textHeight * sHudUtilsState.textAlignment.v.curr, 0); if (valignGfx) { valignGfx->params[0] = textHeight; } - // pop - gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); + djui_hud_pop_matrix(interp); } void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scaleX, f32 scaleY) { @@ -734,17 +889,10 @@ void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, struct InterpHud *interp = djui_hud_create_interp(); if (interp) { - const struct DjuiFont* font = djui_hud_get_text_font(); - interp->posX.prev = prevX; - interp->posY.prev = prevY; - interp->posX.curr = x; - interp->posY.curr = y; - interp->scaleX.prev = prevScaleX; - interp->scaleY.prev = prevScaleY; - interp->scaleX.curr = scaleX; - interp->scaleY.curr = scaleY; - interp->width = font->defaultFontScale; - interp->height = font->defaultFontScale; + INTERP_SET(interp->posX, prevX, x); + INTERP_SET(interp->posY, prevY, y); + INTERP_SET(interp->scaleX, prevScaleX, scaleX); + INTERP_SET(interp->scaleY, prevScaleY, scaleY); } djui_hud_print_text_internal(message, x, y, scaleX, scaleY, interp); @@ -762,78 +910,46 @@ static void djui_hud_render_texture_raw(const Texture* texture, u32 width, u32 h if (!texture) { return; } - gDjuiHudUtilsZ += 0.001f; + djui_hud_setup_matrix(); - // translate position - djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION); - f32 translatedX = x; - f32 translatedY = y; - djui_hud_position_translate(&translatedX, &translatedY); - create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ); + // translate + djui_hud_do_translation(interp, x, y); // rotate - f32 translatedW = scaleW; - f32 translatedH = scaleH; - djui_hud_size_translate(&translatedW); - djui_hud_size_translate(&translatedH); - if (sHudUtilsState.rotation.degrees.prev != 0 || sHudUtilsState.rotation.degrees.curr != 0) { - djui_hud_create_interp_gfx(interp, INTERP_HUD_ROTATION); - f32 pivotTranslationX = width * translatedW * sHudUtilsState.rotation.pivotX.curr; - f32 pivotTranslationY = height * translatedH * 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); - } + djui_hud_do_rotation(interp, width * scaleW, height * scaleH); - // translate scale - djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE); - create_dl_scale_matrix(DJUI_MTX_NOPUSH, width * translatedW, height * translatedH, 1.0f); + // scale + djui_hud_do_scale(interp, width * scaleW, height * scaleH); // render djui_gfx_render_texture(texture, width, height, fmt, siz, sHudUtilsState.filter); // pop - gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); + djui_hud_pop_matrix(interp); } static void djui_hud_render_texture_tile_raw(const Texture* texture, u32 width, u32 height, u8 fmt, u8 siz, f32 x, f32 y, f32 scaleW, f32 scaleH, u32 tileX, u32 tileY, u32 tileW, u32 tileH, struct InterpHud *interp) { if (!texture) { return; } - gDjuiHudUtilsZ += 0.001f; + djui_hud_setup_matrix(); if (width != 0) { scaleW *= (f32) tileW / (f32) width; } if (height != 0) { scaleH *= (f32) tileH / (f32) height; } - // translate position - djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION); - f32 translatedX = x; - f32 translatedY = y; - djui_hud_position_translate(&translatedX, &translatedY); - create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ); + // translate + djui_hud_do_translation(interp, x, y); // rotate - f32 translatedW = scaleW; - f32 translatedH = scaleH; - djui_hud_size_translate(&translatedW); - djui_hud_size_translate(&translatedH); - if (sHudUtilsState.rotation.degrees.prev != 0 || sHudUtilsState.rotation.degrees.curr != 0) { - djui_hud_create_interp_gfx(interp, INTERP_HUD_ROTATION); - f32 aspect = tileH ? ((f32) tileW / (f32) tileH) : 1.f; - f32 pivotTranslationX = width * translatedW * aspect * sHudUtilsState.rotation.pivotX.curr; - f32 pivotTranslationY = height * translatedH * 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); - } + f32 aspect = tileH ? ((f32) tileW / (f32) tileH) : 1.f; + djui_hud_do_rotation(interp, width * scaleW * aspect, height * scaleH); - // translate scale - djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE); - create_dl_scale_matrix(DJUI_MTX_NOPUSH, width * translatedW, height * translatedH, 1.0f); + // scale + djui_hud_do_scale(interp, width * scaleW, height * scaleH); // render djui_gfx_render_texture_tile(texture, width, height, fmt, siz, tileX, tileY, tileW, tileH, sHudUtilsState.filter); // pop - gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); + djui_hud_pop_matrix(interp); } void djui_hud_render_texture(struct TextureInfo* texInfo, f32 x, f32 y, f32 scaleW, f32 scaleH) { @@ -851,14 +967,10 @@ void djui_hud_render_texture_interpolated(struct TextureInfo* texInfo, f32 prevX struct InterpHud *interp = djui_hud_create_interp(); if (interp) { - interp->posX.prev = prevX; - interp->posY.prev = prevY; - interp->posX.curr = x; - interp->posY.curr = y; - interp->scaleX.prev = prevScaleW; - interp->scaleY.prev = prevScaleH; - interp->scaleX.curr = scaleW; - interp->scaleY.curr = scaleH; + INTERP_SET(interp->posX, prevX, x); + INTERP_SET(interp->posY, prevY, y); + INTERP_SET(interp->scaleX, prevScaleW, scaleW); + INTERP_SET(interp->scaleY, prevScaleH, scaleH); interp->width = texInfo->width; interp->height = texInfo->height; } @@ -881,14 +993,10 @@ void djui_hud_render_texture_tile_interpolated(struct TextureInfo* texInfo, f32 struct InterpHud *interp = djui_hud_create_interp(); if (interp) { - interp->posX.prev = prevX; - interp->posY.prev = prevY; - interp->posX.curr = x; - interp->posY.curr = y; - interp->scaleX.prev = prevScaleW; - interp->scaleY.prev = prevScaleH; - interp->scaleX.curr = scaleW; - interp->scaleY.curr = scaleH; + INTERP_SET(interp->posX, prevX, x); + INTERP_SET(interp->posY, prevY, y); + INTERP_SET(interp->scaleX, prevScaleW, scaleW); + INTERP_SET(interp->scaleY, prevScaleH, scaleH); interp->width = texInfo->width; interp->height = texInfo->height; } @@ -897,38 +1005,23 @@ void djui_hud_render_texture_tile_interpolated(struct TextureInfo* texInfo, f32 } static void djui_hud_render_rect_internal(f32 x, f32 y, f32 width, f32 height, struct InterpHud *interp) { - gDjuiHudUtilsZ += 0.001f; + djui_hud_setup_matrix(); - // translate position - djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION); - f32 translatedX = x; - f32 translatedY = y; - djui_hud_position_translate(&translatedX, &translatedY); - create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ); + // translate + djui_hud_do_translation(interp, x, y); // rotate - f32 translatedW = width; - f32 translatedH = height; - djui_hud_size_translate(&translatedW); - djui_hud_size_translate(&translatedH); - if (sHudUtilsState.rotation.degrees.prev != 0 || sHudUtilsState.rotation.degrees.curr != 0) { - djui_hud_create_interp_gfx(interp, INTERP_HUD_ROTATION); - f32 pivotTranslationX = translatedW * sHudUtilsState.rotation.pivotX.curr; - f32 pivotTranslationY = translatedH * 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); - } + djui_hud_do_rotation(interp, width, height); - // translate scale - djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE); - create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedW, translatedH, 1.0f); + // scale + djui_hud_do_scale(interp, width, height); // render + djui_gfx_update_combine_mode(CS_COLOR); gSPDisplayList(gDisplayListHead++, dl_djui_simple_rect); // pop - gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); + djui_hud_pop_matrix(interp); } void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) { @@ -938,14 +1031,10 @@ void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) { void djui_hud_render_rect_interpolated(f32 prevX, f32 prevY, f32 prevWidth, f32 prevHeight, f32 x, f32 y, f32 width, f32 height) { struct InterpHud *interp = djui_hud_create_interp(); if (interp) { - interp->posX.prev = prevX; - interp->posY.prev = prevY; - interp->posX.curr = x; - interp->posY.curr = y; - interp->scaleX.prev = prevWidth; - interp->scaleY.prev = prevHeight; - interp->scaleX.curr = width; - interp->scaleY.curr = height; + INTERP_SET(interp->posX, prevX, x); + INTERP_SET(interp->posY, prevY, y); + INTERP_SET(interp->scaleX, prevWidth, width); + INTERP_SET(interp->scaleY, prevHeight, height); interp->width = 1; interp->height = 1; } @@ -995,7 +1084,7 @@ bool djui_hud_world_pos_to_screen_pos(Vec3f pos, VEC_OUT Vec3f out) { f32 screenWidth, screenHeight; if (sHudUtilsState.resolution == RESOLUTION_N64) { - screenWidth = GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT; + screenWidth = SCREEN_HEIGHT * GFX_DIMENSIONS_ASPECT_RATIO; screenHeight = SCREEN_HEIGHT; } else { u32 windowWidth, windowHeight; diff --git a/src/pc/djui/djui_hud_utils.h b/src/pc/djui/djui_hud_utils.h index 56ea5a698..ba1a0dd3a 100644 --- a/src/pc/djui/djui_hud_utils.h +++ b/src/pc/djui/djui_hud_utils.h @@ -1,6 +1,8 @@ #ifndef DJUI_HUD_UTILS_H #define DJUI_HUD_UTILS_H +#include "pc/lua/smlua.h" + // Common pivot values for rotation #define ROTATION_PIVOT_X_LEFT 0.0 #define ROTATION_PIVOT_X_CENTER 0.5 @@ -59,7 +61,6 @@ struct GlobalTextures { }; extern struct GlobalTextures gGlobalTextures; -extern f32 gDjuiHudUtilsZ; extern bool gDjuiHudLockMouse; void djui_hud_clear_interp_data(); @@ -80,6 +81,8 @@ void djui_hud_set_font(s8 fontType); struct DjuiColor* djui_hud_get_color(void); /* |description|Sets the current DJUI HUD global color|descriptionEnd| */ void djui_hud_set_color(u8 r, u8 g, u8 b, u8 a); +/* |description|Sets the current DJUI HUD global color interpolated|descriptionEnd| */ +void djui_hud_set_color_interpolated(u8 prevR, u8 prevG, u8 prevB, u8 prevA, u8 r, u8 g, u8 b, u8 a); /* |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| */ @@ -88,10 +91,20 @@ struct DjuiColor* djui_hud_get_text_color(void); 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|Sets the number of cycles used by the combiner|descriptionEnd| */ +void djui_hud_set_combiner_cycles(u8 cycles); +/* |description| +Sets the current DJUI HUD combiner. +Each part uses the following equation: `P = (A - B) * C + D`. +Cycle 2 may be used to extend the equation, with the result of the previous cycle accessible through CS_COMBINED +|descriptionEnd| */ +void djui_hud_set_combiner(u8 cycle, bool alpha, OPTIONAL enum CombinerSource a, OPTIONAL enum CombinerSource b, OPTIONAL enum CombinerSource c, OPTIONAL enum CombinerSource d); +/* |description|Resets the current DJUI HUD combiner|descriptionEnd| */ +void djui_hud_reset_combiner(); /* |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| */ -void djui_hud_set_rotation(s16 rotation, f32 pivotX, f32 pivotY); +void djui_hud_set_rotation(s16 rotation, OPTIONAL f32 pivotX, OPTIONAL f32 pivotY); /* |description|Sets the current DJUI HUD rotation interpolated|descriptionEnd| */ void djui_hud_set_rotation_interpolated(s16 prevRotation, f32 prevPivotX, f32 prevPivotY, s16 rotation, f32 pivotX, f32 pivotY); /* |description|Gets the current DJUI HUD text alignment|descriptionEnd| */ @@ -136,6 +149,14 @@ void djui_hud_reset_viewport(void); 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|Applies a transformation (translate, rotate, scale) to subsequent DJUI HUD elements until closed|descriptionEnd| */ +void djui_hud_transform(f32 x, f32 y, f32 scaleX, f32 scaleY); +/* |description|Applies an interpolated transformation (translate, rotate, scale) to subsequent DJUI HUD elements until closed|descriptionEnd| */ +void djui_hud_transform_interpolated(f32 prevX, f32 prevY, f32 prevScaleX, f32 prevScaleY, f32 x, f32 y, f32 scaleX, f32 scaleY); +/* |description|Closes the previous transformation|descriptionEnd| */ +void djui_hud_close_transform(void); +/* |description|Resets the transformation to a fullscreen state|descriptionEnd| */ +void djui_hud_reset_transform(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); diff --git a/src/pc/djui/djui_image.c b/src/pc/djui/djui_image.c index d082b06cd..10b17c1c7 100644 --- a/src/pc/djui/djui_image.c +++ b/src/pc/djui/djui_image.c @@ -13,7 +13,7 @@ static bool djui_image_render(struct DjuiBase* base) { // translate position f32 translatedX = comp->x; f32 translatedY = comp->y; - djui_gfx_position_translate(&translatedX, &translatedY); + djui_gfx_dimension_translate(&translatedX, &translatedY); create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0); // translate size diff --git a/src/pc/djui/djui_inputbox.c b/src/pc/djui/djui_inputbox.c index d5c4bde44..c97fb738c 100644 --- a/src/pc/djui/djui_inputbox.c +++ b/src/pc/djui/djui_inputbox.c @@ -493,6 +493,8 @@ static void djui_inputbox_render_selection(struct DjuiInputbox* inputbox) { } } + djui_gfx_update_combine_mode(CS_COLOR); + // render only cursor when there is no selection width if (selection[0] == selection[1]) { if (sCursorBlink < DJUI_INPUTBOX_MID_BLINK && djui_interactable_is_input_focus(&inputbox->base)) { @@ -573,7 +575,7 @@ static bool djui_inputbox_render(struct DjuiBase* base) { // translate position f32 translatedX = comp->x + inputbox->viewX; f32 translatedY = comp->y + inputbox->yOffset; - djui_gfx_position_translate(&translatedX, &translatedY); + djui_gfx_dimension_translate(&translatedX, &translatedY); create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0); // compute font size diff --git a/src/pc/djui/djui_rect.c b/src/pc/djui/djui_rect.c index 97383c65a..a5630bb10 100644 --- a/src/pc/djui/djui_rect.c +++ b/src/pc/djui/djui_rect.c @@ -10,7 +10,7 @@ bool djui_rect_render(struct DjuiBase* base) { // translate position f32 translatedX = clip->x; f32 translatedY = clip->y; - djui_gfx_position_translate(&translatedX, &translatedY); + djui_gfx_dimension_translate(&translatedX, &translatedY); create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0); // translate size @@ -20,6 +20,7 @@ bool djui_rect_render(struct DjuiBase* base) { create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedWidth, translatedHeight, 1.0f); // render + djui_gfx_update_combine_mode(CS_COLOR); gDPSetEnvColor(gDisplayListHead++, base->color.r, base->color.g, base->color.b, base->color.a); gSPDisplayList(gDisplayListHead++, base->gradient ? dl_djui_menu_rect : dl_djui_simple_rect); diff --git a/src/pc/djui/djui_text.c b/src/pc/djui/djui_text.c index a67f1d4fd..577e3cdbb 100644 --- a/src/pc/djui/djui_text.c +++ b/src/pc/djui/djui_text.c @@ -252,7 +252,7 @@ static void djui_text_render_single_char(struct DjuiText* text, char* c) { return; } - create_dl_translation_matrix(DJUI_MTX_NOPUSH, sTextRenderX - sTextRenderLastX, (sTextRenderY - sTextRenderLastY) * -1.0f, 0); + create_dl_translation_matrix(DJUI_MTX_NOPUSH, sTextRenderX - sTextRenderLastX, sTextRenderY - sTextRenderLastY, 0); text->font->render_char(c); sTextRenderLastX = sTextRenderX; @@ -474,7 +474,7 @@ static bool djui_text_render(struct DjuiBase* base) { // translate position f32 translatedX = comp->x; f32 translatedY = comp->y; - djui_gfx_position_translate(&translatedX, &translatedY); + djui_gfx_dimension_translate(&translatedX, &translatedY); create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0); // compute size diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index ec2922c1b..750b30737 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1461,6 +1461,18 @@ const char gSmluaConstants[] = "" "CONSOLE_MESSAGE_INFO=0\n" "CONSOLE_MESSAGE_WARNING=1\n" "CONSOLE_MESSAGE_ERROR=2\n" +"CS_KEEP=-1\n" +"CS_0=0\n" +"CS_1=1\n" +"CS_TEXTURE=2\n" +"CS_COLOR=3\n" +"CS_TEXT=4\n" +"CS_COMBINED=5\n" +"CS_NOISE=6\n" +"CS_TEXTURE_ALPHA=7\n" +"CS_COLOR_ALPHA=8\n" +"CS_TEXT_ALPHA=9\n" +"CS_COMBINED_ALPHA=10\n" "ROTATION_PIVOT_X_LEFT=0.0\n" "ROTATION_PIVOT_X_CENTER=0.5\n" "ROTATION_PIVOT_X_RIGHT=1.0\n" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 2b05d1a9c..55001f963 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -12369,6 +12369,37 @@ int smlua_func_djui_hud_set_color(lua_State* L) { return 1; } +int smlua_func_djui_hud_set_color_interpolated(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 8) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_set_color_interpolated", 8, top); + return 0; + } + + u8 prevR = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_color_interpolated"); return 0; } + u8 prevG = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_color_interpolated"); return 0; } + u8 prevB = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_set_color_interpolated"); return 0; } + u8 prevA = smlua_to_integer(L, 4); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_set_color_interpolated"); return 0; } + u8 r = smlua_to_integer(L, 5); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "djui_hud_set_color_interpolated"); return 0; } + u8 g = smlua_to_integer(L, 6); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 6, "djui_hud_set_color_interpolated"); return 0; } + u8 b = smlua_to_integer(L, 7); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 7, "djui_hud_set_color_interpolated"); return 0; } + u8 a = smlua_to_integer(L, 8); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 8, "djui_hud_set_color_interpolated"); return 0; } + + djui_hud_set_color_interpolated(prevR, prevG, prevB, prevA, r, g, b, a); + + return 1; +} + int smlua_func_djui_hud_reset_color(lua_State* L) { if (L == NULL) { return 0; } @@ -12437,6 +12468,77 @@ int smlua_func_djui_hud_reset_text_color(lua_State* L) { return 1; } +int smlua_func_djui_hud_set_combiner_cycles(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", "djui_hud_set_combiner_cycles", 1, top); + return 0; + } + + u8 cycles = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_combiner_cycles"); return 0; } + + djui_hud_set_combiner_cycles(cycles); + + return 1; +} + +int smlua_func_djui_hud_set_combiner(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top < 2 || top > 6) { + LOG_LUA_LINE("Improper param count for '%s': Expected between %u and %u, Received %u", "djui_hud_set_combiner", 2, 6, top); + return 0; + } + + u8 cycle = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_combiner"); return 0; } + bool alpha = smlua_to_boolean(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_combiner"); return 0; } + enum CombinerSource a = (enum CombinerSource) 0; + if (top >= 3) { + a = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_set_combiner"); return 0; } + } + enum CombinerSource b = (enum CombinerSource) 0; + if (top >= 4) { + b = smlua_to_integer(L, 4); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_set_combiner"); return 0; } + } + enum CombinerSource c = (enum CombinerSource) 0; + if (top >= 5) { + c = smlua_to_integer(L, 5); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "djui_hud_set_combiner"); return 0; } + } + enum CombinerSource d = (enum CombinerSource) 0; + if (top >= 6) { + d = smlua_to_integer(L, 6); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 6, "djui_hud_set_combiner"); return 0; } + } + + djui_hud_set_combiner(cycle, alpha, a, b, c, d); + + return 1; +} + +int smlua_func_djui_hud_reset_combiner(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_combiner", 0, top); + return 0; + } + + + djui_hud_reset_combiner(); + + return 1; +} + int smlua_func_djui_hud_get_rotation(lua_State* L) { if (L == NULL) { return 0; } @@ -12464,17 +12566,23 @@ int smlua_func_djui_hud_set_rotation(lua_State* L) { if (L == NULL) { return 0; } int top = lua_gettop(L); - if (top != 3) { - LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_set_rotation", 3, top); + if (top < 1 || top > 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected between %u and %u, Received %u", "djui_hud_set_rotation", 1, 3, top); return 0; } s16 rotation = smlua_to_integer(L, 1); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_rotation"); return 0; } - f32 pivotX = smlua_to_number(L, 2); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_rotation"); return 0; } - f32 pivotY = smlua_to_number(L, 3); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_set_rotation"); return 0; } + f32 pivotX = (f32) 0; + if (top >= 2) { + pivotX = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_rotation"); return 0; } + } + f32 pivotY = (f32) 0; + if (top >= 3) { + pivotY = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_set_rotation"); return 0; } + } djui_hud_set_rotation(rotation, pivotX, pivotY); @@ -12844,6 +12952,90 @@ int smlua_func_djui_hud_reset_scissor(lua_State* L) { return 1; } +int smlua_func_djui_hud_transform(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_transform", 4, top); + return 0; + } + + f32 x = smlua_to_number(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_transform"); return 0; } + f32 y = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_transform"); return 0; } + f32 scaleX = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_transform"); return 0; } + f32 scaleY = smlua_to_number(L, 4); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_transform"); return 0; } + + djui_hud_transform(x, y, scaleX, scaleY); + + return 1; +} + +int smlua_func_djui_hud_transform_interpolated(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 8) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_transform_interpolated", 8, top); + return 0; + } + + f32 prevX = smlua_to_number(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_transform_interpolated"); return 0; } + f32 prevY = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_transform_interpolated"); return 0; } + f32 prevScaleX = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_transform_interpolated"); return 0; } + f32 prevScaleY = smlua_to_number(L, 4); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_transform_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_transform_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_transform_interpolated"); return 0; } + f32 scaleX = smlua_to_number(L, 7); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 7, "djui_hud_transform_interpolated"); return 0; } + f32 scaleY = smlua_to_number(L, 8); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 8, "djui_hud_transform_interpolated"); return 0; } + + djui_hud_transform_interpolated(prevX, prevY, prevScaleX, prevScaleY, x, y, scaleX, scaleY); + + return 1; +} + +int smlua_func_djui_hud_close_transform(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_close_transform", 0, top); + return 0; + } + + + djui_hud_close_transform(); + + return 1; +} + +int smlua_func_djui_hud_reset_transform(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_transform", 0, top); + return 0; + } + + + djui_hud_reset_transform(); + + return 1; +} + int smlua_func_djui_hud_measure_text(lua_State* L) { if (L == NULL) { return 0; } @@ -38003,10 +38195,14 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "djui_hud_set_font", smlua_func_djui_hud_set_font); 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_set_color_interpolated", smlua_func_djui_hud_set_color_interpolated); 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_set_combiner_cycles", smlua_func_djui_hud_set_combiner_cycles); + smlua_bind_function(L, "djui_hud_set_combiner", smlua_func_djui_hud_set_combiner); + smlua_bind_function(L, "djui_hud_reset_combiner", smlua_func_djui_hud_reset_combiner); 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); @@ -38030,6 +38226,10 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "djui_hud_reset_viewport", smlua_func_djui_hud_reset_viewport); 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_transform", smlua_func_djui_hud_transform); + smlua_bind_function(L, "djui_hud_transform_interpolated", smlua_func_djui_hud_transform_interpolated); + smlua_bind_function(L, "djui_hud_close_transform", smlua_func_djui_hud_close_transform); + smlua_bind_function(L, "djui_hud_reset_transform", smlua_func_djui_hud_reset_transform); smlua_bind_function(L, "djui_hud_measure_text", smlua_func_djui_hud_measure_text); 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);