mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-22 10:01:46 +00:00
DJUI Text improvements and bug fixes (#1131)
- Drastically improve and optimize display list usage for text - Add text alignment with and without interpolation, and color codes, new lines and tabs are now handled properly - Restored alpha color code (`#RGBA` or `#RRGGBBAA`) for `djui_print_text` functions (regular DJUI text allows alpha color codes, but ignores the alpha component) - Add constants for common text alignment and rotation pivot values - Fix interpolation issues with all `djui_hud` elements - A few autogen fixes (missing `number` type for constants, missing return values for some functions) - Fix recolorable hud font offsets on `e`, `i` and `o` letters
This commit is contained in:
parent
dd838ad979
commit
3b53952767
41 changed files with 1133 additions and 534 deletions
|
|
@ -535,6 +535,8 @@ def def_constant(fname, processed_constant, skip_constant):
|
|||
continue
|
||||
if '"' in c[1]:
|
||||
s += '\n--- @type string\n'
|
||||
elif "." in c[1]:
|
||||
s += '\n--- @type number\n'
|
||||
else:
|
||||
s += '\n--- @type integer\n'
|
||||
s += '%s = %s\n' % (c[0], c[1])
|
||||
|
|
|
|||
|
|
@ -1342,7 +1342,7 @@ def doc_function(fname, function):
|
|||
s += '- None\n'
|
||||
|
||||
s += '\n### Returns\n'
|
||||
if rtype != None:
|
||||
if len(rvalues) > 0:
|
||||
for _, ptype, plink in rvalues:
|
||||
if plink:
|
||||
s += '- [%s](%s)\n' % (ptype, plink)
|
||||
|
|
|
|||
|
|
@ -2760,6 +2760,42 @@ CONSOLE_MESSAGE_ERROR = 2 --- @type ConsoleMessageLevel
|
|||
--- | `CONSOLE_MESSAGE_WARNING`
|
||||
--- | `CONSOLE_MESSAGE_ERROR`
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_X_LEFT = 0.0
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_X_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_X_RIGHT = 1.0
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_Y_TOP = 0.0
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_Y_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
ROTATION_PIVOT_Y_BOTTOM = 1.0
|
||||
|
||||
--- @type number
|
||||
TEXT_HALIGN_LEFT = 0.0
|
||||
|
||||
--- @type number
|
||||
TEXT_HALIGN_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
TEXT_HALIGN_RIGHT = 1.0
|
||||
|
||||
--- @type number
|
||||
TEXT_VALIGN_TOP = 0.0
|
||||
|
||||
--- @type number
|
||||
TEXT_VALIGN_CENTER = 0.5
|
||||
|
||||
--- @type number
|
||||
TEXT_VALIGN_BOTTOM = 1.0
|
||||
|
||||
RESOLUTION_DJUI = 0 --- @type HudUtilsResolution
|
||||
RESOLUTION_N64 = 1 --- @type HudUtilsResolution
|
||||
RESOLUTION_COUNT = 2 --- @type HudUtilsResolution
|
||||
|
|
@ -2778,16 +2814,18 @@ FILTER_COUNT = 2 --- @type HudUtilsFilter
|
|||
--- | `FILTER_LINEAR`
|
||||
--- | `FILTER_COUNT`
|
||||
|
||||
FONT_NORMAL = 0 --- @type DjuiFontType
|
||||
FONT_MENU = 1 --- @type DjuiFontType
|
||||
FONT_HUD = 2 --- @type DjuiFontType
|
||||
FONT_ALIASED = 3 --- @type DjuiFontType
|
||||
FONT_CUSTOM_HUD = 4 --- @type DjuiFontType
|
||||
FONT_RECOLOR_HUD = 5 --- @type DjuiFontType
|
||||
FONT_SPECIAL = 6 --- @type DjuiFontType
|
||||
FONT_COUNT = 7 --- @type DjuiFontType
|
||||
FONT_LEGACY = -1 --- @type DjuiFontType
|
||||
FONT_NORMAL = 0 --- @type DjuiFontType
|
||||
FONT_MENU = 1 --- @type DjuiFontType
|
||||
FONT_HUD = 2 --- @type DjuiFontType
|
||||
FONT_ALIASED = 3 --- @type DjuiFontType
|
||||
FONT_CUSTOM_HUD = 4 --- @type DjuiFontType
|
||||
FONT_RECOLOR_HUD = 5 --- @type DjuiFontType
|
||||
FONT_SPECIAL = 6 --- @type DjuiFontType
|
||||
FONT_COUNT = 7 --- @type DjuiFontType
|
||||
|
||||
--- @alias DjuiFontType
|
||||
--- | `FONT_LEGACY`
|
||||
--- | `FONT_NORMAL`
|
||||
--- | `FONT_MENU`
|
||||
--- | `FONT_HUD`
|
||||
|
|
|
|||
|
|
@ -3856,7 +3856,9 @@ function djui_hud_reset_color()
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @return HudUtilsRotation
|
||||
--- @return integer rotation
|
||||
--- @return number pivotX
|
||||
--- @return number pivotY
|
||||
--- Gets the current DJUI HUD rotation
|
||||
function djui_hud_get_rotation()
|
||||
-- ...
|
||||
|
|
@ -3881,6 +3883,29 @@ function djui_hud_set_rotation_interpolated(prevRotation, prevPivotX, prevPivotY
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @return number textHAlign
|
||||
--- @return number textVAlign
|
||||
--- Gets the current DJUI HUD text alignment
|
||||
function djui_hud_get_text_alignment()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param textHAlign number
|
||||
--- @param textVAlign number
|
||||
--- Sets the current DJUI HUD text alignment
|
||||
function djui_hud_set_text_alignment(textHAlign, textVAlign)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param prevTextHAlign number
|
||||
--- @param prevTextVAlign number
|
||||
--- @param textHAlign number
|
||||
--- @param textVAlign number
|
||||
--- Sets the current DJUI HUD text alignment interpolated
|
||||
function djui_hud_set_text_alignment_interpolated(prevTextHAlign, prevTextVAlign, textHAlign, textVAlign)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return integer
|
||||
--- Gets the screen width in the current DJUI HUD resolution
|
||||
function djui_hud_get_screen_width()
|
||||
|
|
|
|||
|
|
@ -955,14 +955,6 @@
|
|||
--- @field public translation Vec3s
|
||||
--- @field public rotation Vec3s
|
||||
|
||||
--- @class HudUtilsRotation
|
||||
--- @field public rotation number
|
||||
--- @field public rotationDiff number
|
||||
--- @field public prevPivotX number
|
||||
--- @field public prevPivotY number
|
||||
--- @field public pivotX number
|
||||
--- @field public pivotY number
|
||||
|
||||
--- @class InstantWarp
|
||||
--- @field public id integer
|
||||
--- @field public area integer
|
||||
|
|
|
|||
|
|
@ -1149,6 +1149,18 @@
|
|||
<br />
|
||||
|
||||
## [djui_hud_utils.h](#djui_hud_utils.h)
|
||||
- ROTATION_PIVOT_X_LEFT
|
||||
- ROTATION_PIVOT_X_CENTER
|
||||
- ROTATION_PIVOT_X_RIGHT
|
||||
- ROTATION_PIVOT_Y_TOP
|
||||
- ROTATION_PIVOT_Y_CENTER
|
||||
- ROTATION_PIVOT_Y_BOTTOM
|
||||
- TEXT_HALIGN_LEFT
|
||||
- TEXT_HALIGN_CENTER
|
||||
- TEXT_HALIGN_RIGHT
|
||||
- TEXT_VALIGN_TOP
|
||||
- TEXT_VALIGN_CENTER
|
||||
- TEXT_VALIGN_BOTTOM
|
||||
|
||||
### [enum HudUtilsResolution](#HudUtilsResolution)
|
||||
| Identifier | Value |
|
||||
|
|
@ -1167,6 +1179,7 @@
|
|||
### [enum DjuiFontType](#DjuiFontType)
|
||||
| Identifier | Value |
|
||||
| :--------- | :---- |
|
||||
| FONT_LEGACY | -1 |
|
||||
| FONT_NORMAL | 0 |
|
||||
| FONT_MENU | 1 |
|
||||
| FONT_HUD | 2 |
|
||||
|
|
|
|||
|
|
@ -1312,7 +1312,8 @@ Calculates and returns the pitch and yaw angles from one 3D position (`from`) to
|
|||
| to | [Vec3f](structs.md#Vec3f) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void calculate_angles(Vec3f from, Vec3f to, RET s16 *pitch, RET s16 *yaw);`
|
||||
|
|
@ -1585,7 +1586,7 @@ Applies a roll-based shake effect to the camera. Simulates rotational disturbanc
|
|||
| roll | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void shake_camera_roll(INOUT s16 *roll);`
|
||||
|
|
@ -2825,7 +2826,7 @@ Gets the current DJUI HUD font
|
|||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`u8 djui_hud_get_font(void);`
|
||||
`s8 djui_hud_get_font(void);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
@ -2928,16 +2929,18 @@ Resets the current DJUI HUD color
|
|||
Gets the current DJUI HUD rotation
|
||||
|
||||
### Lua Example
|
||||
`local hudUtilsRotationValue = djui_hud_get_rotation()`
|
||||
`local rotation, pivotX, pivotY = djui_hud_get_rotation()`
|
||||
|
||||
### Parameters
|
||||
- None
|
||||
|
||||
### Returns
|
||||
- [HudUtilsRotation](structs.md#HudUtilsRotation)
|
||||
- `integer`
|
||||
- `number`
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`struct HudUtilsRotation* djui_hud_get_rotation(void);`
|
||||
`void djui_hud_get_rotation(RET s16 *rotation, RET f32 *pivotX, RET f32 *pivotY);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
@ -2990,7 +2993,79 @@ Sets the current DJUI HUD rotation interpolated
|
|||
- None
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_set_rotation_interpolated(s32 prevRotation, f32 prevPivotX, f32 prevPivotY, s32 rotation, f32 pivotX, f32 pivotY);`
|
||||
`void djui_hud_set_rotation_interpolated(s16 prevRotation, f32 prevPivotX, f32 prevPivotY, s16 rotation, f32 pivotX, f32 pivotY);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [djui_hud_get_text_alignment](#djui_hud_get_text_alignment)
|
||||
|
||||
### Description
|
||||
Gets the current DJUI HUD text alignment
|
||||
|
||||
### Lua Example
|
||||
`local textHAlign, textVAlign = djui_hud_get_text_alignment()`
|
||||
|
||||
### Parameters
|
||||
- None
|
||||
|
||||
### Returns
|
||||
- `number`
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_get_text_alignment(RET f32 *textHAlign, RET f32 *textVAlign);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [djui_hud_set_text_alignment](#djui_hud_set_text_alignment)
|
||||
|
||||
### Description
|
||||
Sets the current DJUI HUD text alignment
|
||||
|
||||
### Lua Example
|
||||
`djui_hud_set_text_alignment(textHAlign, textVAlign)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| textHAlign | `number` |
|
||||
| textVAlign | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_set_text_alignment(f32 textHAlign, f32 textVAlign);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [djui_hud_set_text_alignment_interpolated](#djui_hud_set_text_alignment_interpolated)
|
||||
|
||||
### Description
|
||||
Sets the current DJUI HUD text alignment interpolated
|
||||
|
||||
### Lua Example
|
||||
`djui_hud_set_text_alignment_interpolated(prevTextHAlign, prevTextVAlign, textHAlign, textVAlign)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| prevTextHAlign | `number` |
|
||||
| prevTextVAlign | `number` |
|
||||
| textHAlign | `number` |
|
||||
| textVAlign | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void djui_hud_set_text_alignment_interpolated(f32 prevTextHAlign, f32 prevTextVAlign, f32 textHAlign, f32 textVAlign);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
|
|||
|
|
@ -5134,7 +5134,9 @@ Calculates the distance between two points in 3D space (`from` and `to`), as wel
|
|||
| to | [Vec3f](structs.md#Vec3f) |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `number`
|
||||
- `integer`
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, RET f32 *dist, RET s16 *pitch, RET s16 *yaw);`
|
||||
|
|
|
|||
|
|
@ -2945,7 +2945,7 @@ Determines an object's forward speed multiplier.
|
|||
| floor_nY | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`void calc_obj_friction(RET f32 *objFriction, f32 floor_nY);`
|
||||
|
|
@ -4419,7 +4419,7 @@ Begin by increasing the current object's scale by `scaleVel`, and slowly decreas
|
|||
| blinkLength | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void obj_update_blinking(INOUT s32 *blinkTimer, s16 baseCycleLength, s16 cycleLengthRange, s16 blinkLength);`
|
||||
|
|
@ -4743,7 +4743,8 @@ Treats far home as Mario. Returns the distance and angle to the nearest player
|
|||
| threshold | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `integer`
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`void treat_far_home_as_mario(f32 threshold, RET s32* distanceToPlayer, RET s32* angleToPlayer);`
|
||||
|
|
|
|||
|
|
@ -1963,7 +1963,7 @@ Marks an object to be unloaded at the end of the frame
|
|||
| dragStrength | `number` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
- `number`
|
||||
|
||||
### C Prototype
|
||||
`void apply_drag_to_value(INOUT f32 *value, f32 dragStrength);`
|
||||
|
|
|
|||
|
|
@ -763,6 +763,9 @@
|
|||
- [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)
|
||||
- [djui_hud_get_text_alignment](functions-3.md#djui_hud_get_text_alignment)
|
||||
- [djui_hud_set_text_alignment](functions-3.md#djui_hud_set_text_alignment)
|
||||
- [djui_hud_set_text_alignment_interpolated](functions-3.md#djui_hud_set_text_alignment_interpolated)
|
||||
- [djui_hud_get_screen_width](functions-3.md#djui_hud_get_screen_width)
|
||||
- [djui_hud_get_screen_height](functions-3.md#djui_hud_get_screen_height)
|
||||
- [djui_hud_get_mouse_x](functions-3.md#djui_hud_get_mouse_x)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
- [GraphNodeSwitchCase](#GraphNodeSwitchCase)
|
||||
- [GraphNodeTranslation](#GraphNodeTranslation)
|
||||
- [GraphNodeTranslationRotation](#GraphNodeTranslationRotation)
|
||||
- [HudUtilsRotation](#HudUtilsRotation)
|
||||
- [InstantWarp](#InstantWarp)
|
||||
- [LakituState](#LakituState)
|
||||
- [LevelValues](#LevelValues)
|
||||
|
|
@ -1427,21 +1426,6 @@
|
|||
|
||||
<br />
|
||||
|
||||
## [HudUtilsRotation](#HudUtilsRotation)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| rotation | `number` | |
|
||||
| rotationDiff | `number` | |
|
||||
| prevPivotX | `number` | |
|
||||
| prevPivotY | `number` | |
|
||||
| pivotX | `number` | |
|
||||
| pivotY | `number` | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [InstantWarp](#InstantWarp)
|
||||
|
||||
| Field | Type | Access |
|
||||
|
|
|
|||
|
|
@ -235,6 +235,8 @@ static void crash_handler_produce_one_frame_callback(void) {
|
|||
// render the line
|
||||
f32 addX = 0;
|
||||
char* c = text->s;
|
||||
|
||||
font->render_begin();
|
||||
while (*c != '\0') {
|
||||
f32 charWidth = 0.4f;
|
||||
|
||||
|
|
@ -253,6 +255,7 @@ static void crash_handler_produce_one_frame_callback(void) {
|
|||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, charWidth, 0, 0);
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
font->render_end();
|
||||
|
||||
// pop
|
||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
|
|
|
|||
|
|
@ -122,11 +122,9 @@ void discord_activity_update(void) {
|
|||
|
||||
// HACK: give the detail population more space than the Discord details can fit so it gets truncated without cutting off the largest strings
|
||||
char details[512] = { 0 };
|
||||
discord_populate_details(details, 512);
|
||||
char* detailsNoColor = str_remove_color_codes(details);
|
||||
|
||||
snprintf(sCurActivity.details, 128, "%s", detailsNoColor);
|
||||
free(detailsNoColor);
|
||||
discord_populate_details(details, ARRAY_COUNT(details));
|
||||
djui_text_remove_colors(details);
|
||||
snprintf(sCurActivity.details, 128, "%s", details);
|
||||
|
||||
if (!app.activities) {
|
||||
LOG_INFO("no activities");
|
||||
|
|
|
|||
|
|
@ -168,7 +168,8 @@ void djui_lua_error_clear(void) {
|
|||
void djui_reset_hud_params(void) {
|
||||
djui_hud_set_resolution(RESOLUTION_DJUI);
|
||||
djui_hud_set_font(FONT_NORMAL);
|
||||
djui_hud_set_rotation(0, 0, 0);
|
||||
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_set_filter(FILTER_NEAREST);
|
||||
djui_hud_reset_viewport();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
// font 0 (built-in normal font) //
|
||||
///////////////////////////////////
|
||||
|
||||
static void djui_font_normal_render_char(char* c) {
|
||||
static void djui_font_normal_render_char(const char* c) {
|
||||
// replace undisplayable characters
|
||||
if (*c == ' ') { return; }
|
||||
|
||||
|
|
@ -18,16 +18,16 @@ static void djui_font_normal_render_char(char* c) {
|
|||
u32 tx = index % 64;
|
||||
u32 ty = index / 64;
|
||||
extern ALIGNED8 const Texture texture_font_jp[];
|
||||
djui_gfx_render_texture_tile(texture_font_jp, 512, 1024, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_jp, 512, 1024, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16);
|
||||
} else {
|
||||
u32 tx = index % 32;
|
||||
u32 ty = index / 32;
|
||||
extern ALIGNED8 const Texture texture_font_normal[];
|
||||
djui_gfx_render_texture_tile(texture_font_normal, 256, 128, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_normal, 256, 128, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16);
|
||||
}
|
||||
}
|
||||
|
||||
static f32 djui_font_normal_char_width(char* c) {
|
||||
static f32 djui_font_normal_char_width(const char* c) {
|
||||
if (*c == ' ') { return configExCoopTheme ? 6 / 32.0f : 0.30f; }
|
||||
extern const f32 font_normal_widths[];
|
||||
return djui_unicode_get_sprite_width(c, font_normal_widths, 32.0f);
|
||||
|
|
@ -41,7 +41,9 @@ static const struct DjuiFont sDjuiFontNormal = {
|
|||
.yOffset = 0.0f,
|
||||
.defaultFontScale = 32.0f,
|
||||
.textBeginDisplayList = NULL,
|
||||
.render_begin = djui_gfx_render_texture_tile_font_begin,
|
||||
.render_char = djui_font_normal_render_char,
|
||||
.render_end = djui_gfx_render_texture_tile_font_end,
|
||||
.char_width = djui_font_normal_char_width,
|
||||
};
|
||||
|
||||
|
|
@ -49,7 +51,7 @@ static const struct DjuiFont sDjuiFontNormal = {
|
|||
// font 1 (custom title font) //
|
||||
////////////////////////////////
|
||||
|
||||
static void djui_font_title_render_char(char* c) {
|
||||
static void djui_font_title_render_char(const char* c) {
|
||||
// replace undisplayable characters
|
||||
if (*c == ' ') { return; }
|
||||
|
||||
|
|
@ -64,10 +66,10 @@ static void djui_font_title_render_char(char* c) {
|
|||
u32 ty = index / 16;
|
||||
|
||||
extern ALIGNED8 const Texture texture_font_title[];
|
||||
djui_gfx_render_texture_tile(texture_font_title, 1024, 512, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 64, ty * 64, 64, 64, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_title, 1024, 512, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 64, ty * 64, 64, 64);
|
||||
}
|
||||
|
||||
static f32 djui_font_title_char_width(char* text) {
|
||||
static f32 djui_font_title_char_width(const char* text) {
|
||||
char c = *text;
|
||||
if (c == ' ') { return 0.30f; }
|
||||
c = djui_unicode_get_base_char(text);
|
||||
|
|
@ -83,7 +85,9 @@ static const struct DjuiFont sDjuiFontTitle = {
|
|||
.yOffset = 0.0f,
|
||||
.defaultFontScale = 64.0f,
|
||||
.textBeginDisplayList = NULL,
|
||||
.render_begin = djui_gfx_render_texture_tile_font_begin,
|
||||
.render_char = djui_font_title_render_char,
|
||||
.render_end = djui_gfx_render_texture_tile_font_end,
|
||||
.char_width = djui_font_title_char_width,
|
||||
};
|
||||
|
||||
|
|
@ -124,27 +128,29 @@ static u8 djui_font_hud_index(char c) {
|
|||
return c;
|
||||
}
|
||||
|
||||
static void djui_font_hud_render_char(char* text) {
|
||||
static void djui_font_hud_render_char(const char* text) {
|
||||
char c = *text;
|
||||
if (c == ' ') { return; }
|
||||
c = djui_unicode_get_base_char(text);
|
||||
u8 index = djui_font_hud_index(c);
|
||||
djui_gfx_render_texture(main_hud_lut[index], 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b, djui_hud_get_filter());
|
||||
djui_gfx_render_texture_font(main_hud_lut[index], 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b);
|
||||
}
|
||||
|
||||
static f32 djui_font_hud_char_width(UNUSED char* text) {
|
||||
static f32 djui_font_hud_char_width(UNUSED const char* text) {
|
||||
return 0.75f;
|
||||
}
|
||||
|
||||
static const struct DjuiFont sDjuiFontHud = {
|
||||
.charWidth = 1.0f,
|
||||
.charHeight = 0.9f,
|
||||
.lineHeight = 0.7f,
|
||||
.lineHeight = 1.25f,
|
||||
.xOffset = 0.0f,
|
||||
.yOffset = 0.0f,
|
||||
.defaultFontScale = 16.0f,
|
||||
.textBeginDisplayList = NULL,
|
||||
.render_begin = djui_gfx_render_texture_font_begin,
|
||||
.render_char = djui_font_hud_render_char,
|
||||
.render_end = djui_gfx_render_texture_font_end,
|
||||
.char_width = djui_font_hud_char_width,
|
||||
};
|
||||
|
||||
|
|
@ -152,7 +158,7 @@ static const struct DjuiFont sDjuiFontHud = {
|
|||
// font 3 (DJ's aliased font) //
|
||||
////////////////////////////////
|
||||
|
||||
static void djui_font_aliased_render_char(char* c) {
|
||||
static void djui_font_aliased_render_char(const char* c) {
|
||||
// replace undisplayable characters
|
||||
if (*c == ' ') { return; }
|
||||
|
||||
|
|
@ -163,16 +169,16 @@ static void djui_font_aliased_render_char(char* c) {
|
|||
u32 tx = index % 64;
|
||||
u32 ty = index / 64;
|
||||
extern ALIGNED8 const Texture texture_font_jp_aliased[];
|
||||
djui_gfx_render_texture_tile(texture_font_jp_aliased, 1024, 2048, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 16, ty * 32, 16, 32, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_jp_aliased, 1024, 2048, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 16, ty * 32, 16, 32);
|
||||
} else {
|
||||
u32 tx = index % 32;
|
||||
u32 ty = index / 32;
|
||||
extern ALIGNED8 const Texture texture_font_aliased[];
|
||||
djui_gfx_render_texture_tile(texture_font_aliased, 512, 256, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 16, ty * 32, 16, 32, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_aliased, 512, 256, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 16, ty * 32, 16, 32);
|
||||
}
|
||||
}
|
||||
|
||||
static f32 djui_font_aliased_char_width(char* c) {
|
||||
static f32 djui_font_aliased_char_width(const char* c) {
|
||||
if (*c == ' ') { return 6 / 32.0f; }
|
||||
extern const f32 font_aliased_widths[];
|
||||
return djui_unicode_get_sprite_width(c, font_aliased_widths, 1.0f) / 32.0f;
|
||||
|
|
@ -186,7 +192,9 @@ static const struct DjuiFont sDjuiFontAliased = {
|
|||
.lineHeight = 0.8125f,
|
||||
.defaultFontScale = 32.0f,
|
||||
.textBeginDisplayList = NULL,
|
||||
.render_begin = djui_gfx_render_texture_tile_font_begin,
|
||||
.render_char = djui_font_aliased_render_char,
|
||||
.render_end = djui_gfx_render_texture_tile_font_end,
|
||||
.char_width = djui_font_aliased_char_width,
|
||||
};
|
||||
|
||||
|
|
@ -194,7 +202,7 @@ static const struct DjuiFont sDjuiFontAliased = {
|
|||
// font 4/5 (custom hud font/recolor) //
|
||||
////////////////////////////////////////
|
||||
|
||||
static void djui_font_custom_hud_render_char(char* c) {
|
||||
static void djui_font_custom_hud_render_char(const char* c) {
|
||||
// replace undisplayable characters
|
||||
if (*c == ' ') { return; }
|
||||
|
||||
|
|
@ -204,10 +212,10 @@ static void djui_font_custom_hud_render_char(char* c) {
|
|||
u32 ty = index / 16;
|
||||
|
||||
extern ALIGNED8 const Texture texture_font_hud[];
|
||||
djui_gfx_render_texture_tile(texture_font_hud, 512, 512, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 32, ty * 32, 32, 32, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_hud, 512, 512, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 32, ty * 32, 32, 32);
|
||||
}
|
||||
|
||||
static void djui_font_custom_hud_recolor_render_char(char* c) {
|
||||
static void djui_font_custom_hud_recolor_render_char(const char* c) {
|
||||
// replace undisplayable characters
|
||||
if (*c == ' ') { return; }
|
||||
|
||||
|
|
@ -217,10 +225,10 @@ static void djui_font_custom_hud_recolor_render_char(char* c) {
|
|||
u32 ty = index / 16;
|
||||
|
||||
extern ALIGNED8 const Texture texture_font_hud_recolor[];
|
||||
djui_gfx_render_texture_tile(texture_font_hud_recolor, 512, 512, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 32, ty * 32, 32, 32, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_hud_recolor, 512, 512, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 32, ty * 32, 32, 32);
|
||||
}
|
||||
|
||||
static f32 djui_font_custom_hud_char_width(char* text) {
|
||||
static f32 djui_font_custom_hud_char_width(const char* text) {
|
||||
char c = *text;
|
||||
if (c == ' ') { return 0.3750f; }
|
||||
c = djui_unicode_get_base_char(text);
|
||||
|
|
@ -236,7 +244,9 @@ static const struct DjuiFont sDjuiFontCustomHud = {
|
|||
.yOffset = -10.25f,
|
||||
.defaultFontScale = 32.0f,
|
||||
.textBeginDisplayList = NULL,
|
||||
.render_begin = djui_gfx_render_texture_tile_font_begin,
|
||||
.render_char = djui_font_custom_hud_render_char,
|
||||
.render_end = djui_gfx_render_texture_tile_font_end,
|
||||
.char_width = djui_font_custom_hud_char_width,
|
||||
};
|
||||
|
||||
|
|
@ -248,7 +258,9 @@ static const struct DjuiFont sDjuiFontCustomHudRecolor = {
|
|||
.yOffset = -10.25f,
|
||||
.defaultFontScale = 32.0f,
|
||||
.textBeginDisplayList = NULL,
|
||||
.render_begin = djui_gfx_render_texture_tile_font_begin,
|
||||
.render_char = djui_font_custom_hud_recolor_render_char,
|
||||
.render_end = djui_gfx_render_texture_tile_font_end,
|
||||
.char_width = djui_font_custom_hud_char_width,
|
||||
};
|
||||
|
||||
|
|
@ -256,7 +268,7 @@ static const struct DjuiFont sDjuiFontCustomHudRecolor = {
|
|||
// font 6 (special font) //
|
||||
///////////////////////////
|
||||
|
||||
static void djui_font_special_render_char(char* c) {
|
||||
static void djui_font_special_render_char(const char* c) {
|
||||
// replace undisplayable characters
|
||||
if (*c == ' ') { return; }
|
||||
|
||||
|
|
@ -266,17 +278,17 @@ static void djui_font_special_render_char(char* c) {
|
|||
u32 tx = index % 64;
|
||||
u32 ty = index / 64;
|
||||
extern ALIGNED8 const Texture texture_font_jp[];
|
||||
djui_gfx_render_texture_tile(texture_font_jp, 512, 1024, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_jp, 512, 1024, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16);
|
||||
} else {
|
||||
u32 tx = index % 32;
|
||||
u32 ty = index / 32;
|
||||
extern ALIGNED8 const Texture texture_font_special[];
|
||||
djui_gfx_render_texture_tile(texture_font_special, 256, 128, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16, false, true);
|
||||
djui_gfx_render_texture_tile_font(texture_font_special, 256, 128, G_IM_FMT_RGBA, G_IM_SIZ_32b, tx * 8, ty * 16, 8, 16);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static f32 djui_font_special_char_width(char* c) {
|
||||
static f32 djui_font_special_char_width(const char* c) {
|
||||
if (*c == ' ') { return 0.5f; }
|
||||
extern const f32 font_special_widths[];
|
||||
return djui_unicode_get_sprite_width(c, font_special_widths, 32.0f);
|
||||
|
|
@ -290,7 +302,9 @@ static const struct DjuiFont sDjuiFontSpecial = {
|
|||
.yOffset = 0.0f,
|
||||
.defaultFontScale = 32.0f,
|
||||
.textBeginDisplayList = NULL,
|
||||
.render_begin = djui_gfx_render_texture_tile_font_begin,
|
||||
.render_char = djui_font_special_render_char,
|
||||
.render_end = djui_gfx_render_texture_tile_font_end,
|
||||
.char_width = djui_font_special_char_width,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ struct DjuiFont {
|
|||
f32 yOffset;
|
||||
f32 defaultFontScale;
|
||||
const Gfx* textBeginDisplayList;
|
||||
void (*render_char)(char*);
|
||||
f32 (*char_width)(char*);
|
||||
void (*render_begin)();
|
||||
void (*render_char)(const char*);
|
||||
void (*render_end)();
|
||||
f32 (*char_width)(const char*);
|
||||
};
|
||||
|
||||
extern const struct DjuiFont* gDjuiFonts[];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <ultra64.h>
|
||||
#include "sm64.h"
|
||||
#include "djui.h"
|
||||
#include "djui_hud_utils.h"
|
||||
#include "game/ingame_menu.h"
|
||||
#include "game/segment2.h"
|
||||
#include "pc/pc_main.h"
|
||||
|
|
@ -118,7 +119,93 @@ void djui_gfx_render_texture(const Texture* texture, u32 w, u32 h, u8 fmt, u8 si
|
|||
gSPDisplayList(gDisplayListHead++, dl_djui_image);
|
||||
}
|
||||
|
||||
void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, u32 tileX, u32 tileY, u32 tileW, u32 tileH, bool filter, bool font) {
|
||||
void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, u32 tileX, u32 tileY, u32 tileW, u32 tileH, bool filter) {
|
||||
if (!gDisplayListHead) {
|
||||
LOG_ERROR("Retrieved a null displaylist head");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!texture) {
|
||||
LOG_ERROR("Attempted to render null texture");
|
||||
return;
|
||||
}
|
||||
|
||||
Vtx *vtx = alloc_display_list(sizeof(Vtx) * 4);
|
||||
if (!vtx) {
|
||||
LOG_ERROR("Failed to allocate vertices");
|
||||
return;
|
||||
}
|
||||
|
||||
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 }}};
|
||||
|
||||
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BOTH);
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_FADEA);
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
|
||||
gDPSetTextureFilter(gDisplayListHead++, filter ? G_TF_BILERP : G_TF_POINT);
|
||||
|
||||
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
|
||||
|
||||
gDPSetTextureOverrideDjui(gDisplayListHead++, texture, djui_gfx_power_of_two(w), djui_gfx_power_of_two(h), fmt, siz);
|
||||
gDPLoadTextureBlockWithoutTexture(gDisplayListHead++, NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0);
|
||||
|
||||
*(gDisplayListHead++) = (Gfx) gsSPExecuteDjui(G_TEXOVERRIDE_DJUI);
|
||||
|
||||
gSPVertexNonGlobal(gDisplayListHead++, vtx, 4, 0);
|
||||
*(gDisplayListHead++) = (Gfx) gsSPExecuteDjui(G_TEXCLIP_DJUI);
|
||||
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);
|
||||
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_FADEA);
|
||||
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);
|
||||
gDPLoadTextureBlockWithoutTexture(gDisplayListHead++, NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void djui_gfx_render_texture_font(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz) {
|
||||
if (!gDisplayListHead) {
|
||||
LOG_ERROR("Retrieved a null displaylist head");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!texture) {
|
||||
LOG_ERROR("Attempted to render null texture");
|
||||
return;
|
||||
}
|
||||
|
||||
gDPSetTextureOverrideDjui(gDisplayListHead++, texture, djui_gfx_power_of_two(w), djui_gfx_power_of_two(h), fmt, siz);
|
||||
*(gDisplayListHead++) = (Gfx) gsSPExecuteDjui(G_TEXOVERRIDE_DJUI);
|
||||
gSPVertexNonGlobal(gDisplayListHead++, vertex_djui_image, 4, 0);
|
||||
gSP2Triangles(gDisplayListHead++, 0, 1, 2, 0x0, 0, 2, 3, 0x0);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
gDPLoadTextureBlockWithoutTexture(gDisplayListHead++, NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void djui_gfx_render_texture_tile_font(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, u32 tileX, u32 tileY, u32 tileW, u32 tileH) {
|
||||
if (!gDisplayListHead) {
|
||||
LOG_ERROR("Retrieved a null displaylist head");
|
||||
return;
|
||||
|
|
@ -139,29 +226,21 @@ void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt,
|
|||
|
||||
// I don't know why adding 1 to all of the UVs seems to fix rendering, but it does...
|
||||
// this should be tested carefully. it definitely fixes some stuff, but what does it break?
|
||||
f32 offsetX = (font ? -1024.0f / (f32)w : 0) + 1;
|
||||
f32 offsetY = (font ? -1024.0f / (f32)h : 0) + 1;
|
||||
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 }}};
|
||||
|
||||
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BOTH);
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_FADEA, G_CC_FADEA);
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
|
||||
gDPSetTextureFilter(gDisplayListHead++, filter ? G_TF_BILERP : G_TF_POINT);
|
||||
|
||||
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
|
||||
|
||||
gDPSetTextureOverrideDjui(gDisplayListHead++, texture, djui_gfx_power_of_two(w), djui_gfx_power_of_two(h), fmt, siz);
|
||||
gDPLoadTextureBlockWithoutTexture(gDisplayListHead++, NULL, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 64, 0, G_TX_CLAMP, G_TX_CLAMP, 0, 0, 0, 0);
|
||||
|
||||
*(gDisplayListHead++) = (Gfx) gsSPExecuteDjui(G_TEXOVERRIDE_DJUI);
|
||||
|
||||
gSPVertexNonGlobal(gDisplayListHead++, vtx, 4, 0);
|
||||
*(gDisplayListHead++) = (Gfx) gsSPExecuteDjui(G_TEXCLIP_DJUI);
|
||||
gSP2TrianglesDjui(gDisplayListHead++, 0, 1, 2, 0x0, 0, 2, 3, 0x0);
|
||||
}
|
||||
|
||||
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);
|
||||
gSPSetGeometryMode(gDisplayListHead++, G_LIGHTING | G_CULL_BACK);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,15 @@ void djui_gfx_displaylist_end(void);
|
|||
f32 djui_gfx_get_scale(void);
|
||||
|
||||
void djui_gfx_render_texture(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, bool filter);
|
||||
void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, u32 tileX, u32 tileY, u32 tileW, u32 tileH, bool filter, bool font);
|
||||
void djui_gfx_render_texture_tile(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, u32 tileX, u32 tileY, u32 tileW, u32 tileH, bool filter);
|
||||
|
||||
void djui_gfx_render_texture_font_begin();
|
||||
void djui_gfx_render_texture_font(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz);
|
||||
void djui_gfx_render_texture_font_end();
|
||||
|
||||
void djui_gfx_render_texture_tile_font_begin();
|
||||
void djui_gfx_render_texture_tile_font(const Texture* texture, u32 w, u32 h, u8 fmt, u8 siz, u32 tileX, u32 tileY, u32 tileW, u32 tileH);
|
||||
void djui_gfx_render_texture_tile_font_end();
|
||||
|
||||
void gfx_get_dimensions(u32* width, u32* height);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,45 @@
|
|||
|
||||
#include "engine/math_util.h"
|
||||
|
||||
static enum HudUtilsResolution sResolution = RESOLUTION_DJUI;
|
||||
static enum HudUtilsFilter sFilter = FILTER_NEAREST;
|
||||
static enum DjuiFontType sFont = FONT_NORMAL;
|
||||
static struct HudUtilsRotation sRotation = { 0, 0, 0, 0, 0, 0 };
|
||||
static struct DjuiColor sColor = { 255, 255, 255, 255 };
|
||||
#define INTERP_INIT(v) {v, v}
|
||||
|
||||
typedef struct {
|
||||
f32 prev, curr;
|
||||
} InterpFieldF32;
|
||||
|
||||
struct HudUtilsState {
|
||||
enum HudUtilsResolution resolution;
|
||||
enum HudUtilsFilter filter;
|
||||
enum DjuiFontType font;
|
||||
struct DjuiColor color;
|
||||
struct {
|
||||
InterpFieldF32 degrees;
|
||||
InterpFieldF32 pivotX;
|
||||
InterpFieldF32 pivotY;
|
||||
} rotation;
|
||||
struct {
|
||||
InterpFieldF32 h;
|
||||
InterpFieldF32 v;
|
||||
} textAlignment;
|
||||
};
|
||||
|
||||
static struct HudUtilsState sHudUtilsState = {
|
||||
.resolution = RESOLUTION_DJUI,
|
||||
.filter = FILTER_NEAREST,
|
||||
.font = FONT_NORMAL,
|
||||
.color = { 255, 255, 255, 255 },
|
||||
.rotation = {
|
||||
.degrees = INTERP_INIT(0),
|
||||
.pivotX = INTERP_INIT(ROTATION_PIVOT_X_LEFT),
|
||||
.pivotY = INTERP_INIT(ROTATION_PIVOT_Y_TOP),
|
||||
},
|
||||
.textAlignment = {
|
||||
.h = INTERP_INIT(TEXT_HALIGN_LEFT),
|
||||
.v = INTERP_INIT(TEXT_VALIGN_TOP),
|
||||
},
|
||||
};
|
||||
|
||||
static struct DjuiColor sRefColor = { 255, 255, 255, 255 };
|
||||
static bool sLegacy = false;
|
||||
|
||||
f32 gDjuiHudUtilsZ = 0;
|
||||
bool gDjuiHudLockMouse = false;
|
||||
|
|
@ -67,8 +99,16 @@ struct GlobalTextures gGlobalTextures = {
|
|||
.wario_head = { .texture = texture_hud_char_wario_head, "texture_hud_char_wario_head", .width = 16, .height = 16, .format = G_IM_FMT_RGBA, .size = G_IM_SIZ_16b }
|
||||
};
|
||||
|
||||
static inline const struct DjuiFont *djui_hud_get_text_font() {
|
||||
return gDjuiFonts[sHudUtilsState.font < 0 ? FONT_NORMAL : sHudUtilsState.font];
|
||||
}
|
||||
|
||||
static inline bool djui_hud_text_font_is_legacy() {
|
||||
return sHudUtilsState.font < 0;
|
||||
}
|
||||
|
||||
static void djui_hud_position_translate(f32* x, f32* y) {
|
||||
if (sResolution == RESOLUTION_DJUI) {
|
||||
if (sHudUtilsState.resolution == RESOLUTION_DJUI) {
|
||||
djui_gfx_position_translate(x, y);
|
||||
} else {
|
||||
*x = GFX_DIMENSIONS_FROM_LEFT_EDGE(0) + *x;
|
||||
|
|
@ -77,7 +117,7 @@ static void djui_hud_position_translate(f32* x, f32* y) {
|
|||
}
|
||||
|
||||
static void djui_hud_size_translate(f32* size) {
|
||||
if (sResolution == RESOLUTION_DJUI) {
|
||||
if (sHudUtilsState.resolution == RESOLUTION_DJUI) {
|
||||
djui_gfx_size_translate(size);
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +130,7 @@ static void djui_hud_translate_positions(f32 *outX, f32 *outY, f32 *outW, f32 *o
|
|||
*outY -= SCREEN_HEIGHT;
|
||||
|
||||
// translate scale
|
||||
if (sResolution == RESOLUTION_DJUI) {
|
||||
if (sHudUtilsState.resolution == RESOLUTION_DJUI) {
|
||||
u32 windowWidth, windowHeight;
|
||||
gfx_get_dimensions(&windowWidth, &windowHeight);
|
||||
f32 screenWidth = (f32) windowWidth / djui_gfx_get_scale();
|
||||
|
|
@ -105,22 +145,31 @@ static void djui_hud_translate_positions(f32 *outX, f32 *outY, f32 *outW, f32 *o
|
|||
////////////
|
||||
|
||||
#define MAX_INTERP_HUD 512
|
||||
struct InterpHud {
|
||||
Gfx* headPos;
|
||||
f32 z;
|
||||
f32 prevX;
|
||||
f32 prevY;
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 prevScaleW;
|
||||
f32 prevScaleH;
|
||||
f32 scaleW;
|
||||
f32 scaleH;
|
||||
f32 width;
|
||||
f32 height;
|
||||
enum HudUtilsResolution resolution;
|
||||
struct HudUtilsRotation rotation;
|
||||
|
||||
enum InterpHudType {
|
||||
INTERP_HUD_TRANSLATION,
|
||||
INTERP_HUD_ROTATION,
|
||||
INTERP_HUD_SCALE,
|
||||
INTERP_HUD_HALIGN,
|
||||
INTERP_HUD_VALIGN,
|
||||
INTERP_HUD_NEW_LINE,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
enum InterpHudType type;
|
||||
Gfx *pos;
|
||||
f32 params[1]; // we don't need more for now
|
||||
} InterpHudGfx;
|
||||
|
||||
struct InterpHud {
|
||||
f32 z;
|
||||
InterpFieldF32 posX, posY;
|
||||
InterpFieldF32 scaleX, scaleY;
|
||||
f32 width, height;
|
||||
struct HudUtilsState state;
|
||||
struct GrowingArray *gfx;
|
||||
};
|
||||
|
||||
static struct InterpHud sInterpHuds[MAX_INTERP_HUD] = { 0 };
|
||||
static u16 sInterpHudCount = 0;
|
||||
static u8 sColorAltered = FALSE;
|
||||
|
|
@ -132,140 +181,211 @@ void patch_djui_hud_before(void) {
|
|||
void patch_djui_hud(f32 delta) {
|
||||
f32 savedZ = gDjuiHudUtilsZ;
|
||||
Gfx* savedHeadPos = gDisplayListHead;
|
||||
enum HudUtilsResolution savedResolution = sResolution;
|
||||
struct HudUtilsRotation savedRotation = sRotation;
|
||||
struct HudUtilsState savedState = sHudUtilsState;
|
||||
|
||||
for (u16 i = 0; i < sInterpHudCount; i++) {
|
||||
struct InterpHud* interp = &sInterpHuds[i];
|
||||
f32 x = delta_interpolate_f32(interp->prevX, interp->x, delta);
|
||||
f32 y = delta_interpolate_f32(interp->prevY, interp->y, delta);
|
||||
f32 scaleW = delta_interpolate_f32(interp->prevScaleW, interp->scaleW, delta);
|
||||
f32 scaleH = delta_interpolate_f32(interp->prevScaleH, interp->scaleH, delta);
|
||||
sResolution = interp->resolution;
|
||||
sRotation = interp->rotation;
|
||||
|
||||
f32 x = delta_interpolate_f32(interp->posX.prev, interp->posX.curr, delta);
|
||||
f32 y = delta_interpolate_f32(interp->posY.prev, interp->posY.curr, 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;
|
||||
gDisplayListHead = interp->headPos;
|
||||
|
||||
// translate position
|
||||
f32 translatedX = x;
|
||||
f32 translatedY = y;
|
||||
djui_hud_position_translate(&translatedX, &translatedY);
|
||||
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
|
||||
for (u32 j = 0; j != interp->gfx->count; ++j) {
|
||||
const InterpHudGfx *gfx = interp->gfx->buffer[j];
|
||||
gDisplayListHead = gfx->pos;
|
||||
|
||||
// rotate
|
||||
f32 translatedW = scaleW;
|
||||
f32 translatedH = scaleH;
|
||||
djui_hud_size_translate(&translatedW);
|
||||
djui_hud_size_translate(&translatedH);
|
||||
if (sRotation.rotationDiff != 0 || sRotation.rotation != 0) {
|
||||
s32 rotation = delta_interpolate_s32(sRotation.rotation - sRotation.rotationDiff, sRotation.rotation, delta);
|
||||
f32 pivotX = delta_interpolate_f32(sRotation.prevPivotX, sRotation.pivotX, delta);
|
||||
f32 pivotY = delta_interpolate_f32(sRotation.prevPivotY, sRotation.pivotY, 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, rotation, 0, 0, 1);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
} 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);
|
||||
} break;
|
||||
|
||||
case INTERP_HUD_HALIGN: {
|
||||
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 * textHAlign, 0, 0);
|
||||
} break;
|
||||
|
||||
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);
|
||||
} 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);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// scale
|
||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, interp->width * translatedW, interp->height * translatedH, 1.0f);
|
||||
}
|
||||
sResolution = savedResolution;
|
||||
sRotation = savedRotation;
|
||||
|
||||
sHudUtilsState = savedState;
|
||||
gDisplayListHead = savedHeadPos;
|
||||
gDjuiHudUtilsZ = savedZ;
|
||||
}
|
||||
|
||||
struct InterpHud *djui_hud_create_interp() {
|
||||
if (sInterpHudCount >= MAX_INTERP_HUD) { return NULL; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return interp;
|
||||
}
|
||||
|
||||
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));
|
||||
gfx->type = type;
|
||||
gfx->pos = gDisplayListHead;
|
||||
return gfx;
|
||||
}
|
||||
|
||||
////////////
|
||||
// others //
|
||||
////////////
|
||||
|
||||
u8 djui_hud_get_resolution(void) {
|
||||
return sResolution;
|
||||
return sHudUtilsState.resolution;
|
||||
}
|
||||
|
||||
void djui_hud_set_resolution(enum HudUtilsResolution resolutionType) {
|
||||
if (resolutionType >= RESOLUTION_COUNT) { return; }
|
||||
sResolution = resolutionType;
|
||||
sHudUtilsState.resolution = resolutionType;
|
||||
}
|
||||
|
||||
u8 djui_hud_get_filter(void) {
|
||||
return sFilter;
|
||||
return sHudUtilsState.filter;
|
||||
}
|
||||
|
||||
void djui_hud_set_filter(enum HudUtilsFilter filterType) {
|
||||
if (filterType >= FILTER_COUNT) { return; }
|
||||
sFilter = filterType;
|
||||
sHudUtilsState.filter = filterType;
|
||||
}
|
||||
|
||||
u8 djui_hud_get_font(void) {
|
||||
return sFont;
|
||||
s8 djui_hud_get_font(void) {
|
||||
return sHudUtilsState.font;
|
||||
}
|
||||
|
||||
void djui_hud_set_font(s8 fontType) {
|
||||
if (fontType >= FONT_COUNT || fontType < -1) { return; }
|
||||
sLegacy = fontType == -1;
|
||||
if (sLegacy) { fontType = 0; }
|
||||
sFont = fontType;
|
||||
sHudUtilsState.font = fontType;
|
||||
}
|
||||
|
||||
struct DjuiColor* djui_hud_get_color(void) {
|
||||
sRefColor.r = sColor.r;
|
||||
sRefColor.g = sColor.g;
|
||||
sRefColor.b = sColor.b;
|
||||
sRefColor.a = sColor.a;
|
||||
sRefColor.r = sHudUtilsState.color.r;
|
||||
sRefColor.g = sHudUtilsState.color.g;
|
||||
sRefColor.b = sHudUtilsState.color.b;
|
||||
sRefColor.a = sHudUtilsState.color.a;
|
||||
return &sRefColor;
|
||||
}
|
||||
|
||||
void djui_hud_set_color(u8 r, u8 g, u8 b, u8 a) {
|
||||
sColor.r = r;
|
||||
sColor.g = g;
|
||||
sColor.b = b;
|
||||
sColor.a = a;
|
||||
sHudUtilsState.color.r = r;
|
||||
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) {
|
||||
sColor.r = 255;
|
||||
sColor.g = 255;
|
||||
sColor.b = 255;
|
||||
sColor.a = 255;
|
||||
sHudUtilsState.color.r = 255;
|
||||
sHudUtilsState.color.g = 255;
|
||||
sHudUtilsState.color.b = 255;
|
||||
sHudUtilsState.color.a = 255;
|
||||
sColorAltered = FALSE;
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
struct HudUtilsRotation* djui_hud_get_rotation(void) {
|
||||
return &sRotation;
|
||||
void djui_hud_get_rotation(RET s16 *rotation, RET f32 *pivotX, RET f32 *pivotY) {
|
||||
*rotation = degrees_to_sm64(sHudUtilsState.rotation.degrees.curr);
|
||||
*pivotX = sHudUtilsState.rotation.pivotX.curr;
|
||||
*pivotY = sHudUtilsState.rotation.pivotY.curr;
|
||||
}
|
||||
|
||||
void djui_hud_set_rotation(s16 rotation, f32 pivotX, f32 pivotY) {
|
||||
sRotation.rotationDiff = 0;
|
||||
sRotation.prevPivotX = pivotX;
|
||||
sRotation.prevPivotY = pivotY;
|
||||
sRotation.rotation = (rotation * 180.f) / 0x8000;
|
||||
sRotation.pivotX = pivotX;
|
||||
sRotation.pivotY = 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_interpolated(s32 prevRotation, f32 prevPivotX, f32 prevPivotY, s32 rotation, f32 pivotX, f32 pivotY) {
|
||||
f32 normalizedDiff = ((rotation - prevRotation + 0x8000) & 0xFFFF) - 0x8000; // Fix modular overflow/underflow
|
||||
sRotation.rotationDiff = (normalizedDiff * 180.f) / 0x8000;
|
||||
sRotation.prevPivotX = prevPivotX;
|
||||
sRotation.prevPivotY = prevPivotY;
|
||||
sRotation.rotation = (rotation * 180.f) / 0x8000;
|
||||
sRotation.pivotX = pivotX;
|
||||
sRotation.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;
|
||||
}
|
||||
|
||||
void djui_hud_get_text_alignment(RET f32 *textHAlign, RET f32 *textVAlign) {
|
||||
*textHAlign = sHudUtilsState.textAlignment.h.curr;
|
||||
*textVAlign = sHudUtilsState.textAlignment.v.curr;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
u32 djui_hud_get_screen_width(void) {
|
||||
u32 windowWidth, windowHeight;
|
||||
gfx_get_dimensions(&windowWidth, &windowHeight);
|
||||
|
||||
return (sResolution == RESOLUTION_N64)
|
||||
return (sHudUtilsState.resolution == RESOLUTION_N64)
|
||||
? GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT
|
||||
: (windowWidth / djui_gfx_get_scale());
|
||||
}
|
||||
|
|
@ -274,7 +394,7 @@ u32 djui_hud_get_screen_height(void) {
|
|||
u32 windowWidth, windowHeight;
|
||||
gfx_get_dimensions(&windowWidth, &windowHeight);
|
||||
|
||||
return (sResolution == RESOLUTION_N64)
|
||||
return (sHudUtilsState.resolution == RESOLUTION_N64)
|
||||
? SCREEN_HEIGHT
|
||||
: (windowHeight / djui_gfx_get_scale());
|
||||
}
|
||||
|
|
@ -364,23 +484,58 @@ void djui_hud_reset_scissor(void) {
|
|||
|
||||
f32 djui_hud_measure_text(const char* message) {
|
||||
if (message == NULL) { return 0; }
|
||||
const struct DjuiFont* font = gDjuiFonts[sFont];
|
||||
f32 width = 0;
|
||||
const char* c = message;
|
||||
while(*c != '\0') {
|
||||
width += font->char_width((char*)c) * (sLegacy ? 0.5f : 1.0f);
|
||||
c = djui_unicode_next_char((char*)c);
|
||||
const struct DjuiFont* font = djui_hud_get_text_font();
|
||||
f32 width = 0, maxWidth = 0;
|
||||
char *c = (char *) message;
|
||||
const char *end = message + strlen(message);
|
||||
while (*c != '\0') {
|
||||
|
||||
// check color code
|
||||
if (djui_text_parse_color(c, end, false, NULL, &c, NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// new line
|
||||
if (*c == '\n') {
|
||||
maxWidth = max(width, maxWidth);
|
||||
width = 0;
|
||||
}
|
||||
|
||||
// tab: align to the next (4 x space width)
|
||||
else if (*c == '\t') {
|
||||
f32 tabWidth = 4 * font->char_width(" ") * (djui_hud_text_font_is_legacy() ? 0.5f : 1.0f);
|
||||
width += tabWidth - fmodf(width, tabWidth);
|
||||
}
|
||||
|
||||
// unprintable chars
|
||||
else if (!djui_text_is_printable(c)) {
|
||||
// treat them as empty
|
||||
}
|
||||
|
||||
// regular chars
|
||||
else {
|
||||
width += font->char_width(c) * (djui_hud_text_font_is_legacy() ? 0.5f : 1.0f);
|
||||
}
|
||||
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
return width * font->defaultFontScale;
|
||||
return max(width, maxWidth) * font->defaultFontScale;
|
||||
}
|
||||
|
||||
void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scale) {
|
||||
static Mtx *allocate_dl_translation_matrix() {
|
||||
Mtx *matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
|
||||
if (matrix == NULL) { return NULL; }
|
||||
gSPMatrix(gDisplayListHead++, matrix, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
static void djui_hud_print_text_internal(const char* message, f32 x, f32 y, f32 scale, struct InterpHud *interp) {
|
||||
if (message == NULL) { return; }
|
||||
gDjuiHudUtilsZ += 0.001f;
|
||||
|
||||
if (sLegacy) { scale *= 0.5f; }
|
||||
if (djui_hud_text_font_is_legacy()) { scale *= 0.5f; }
|
||||
|
||||
const struct DjuiFont* font = gDjuiFonts[sFont];
|
||||
const struct DjuiFont* font = djui_hud_get_text_font();
|
||||
f32 fontScale = font->defaultFontScale * scale;
|
||||
|
||||
// setup display list
|
||||
|
|
@ -389,117 +544,147 @@ void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scale) {
|
|||
}
|
||||
|
||||
// translate position
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION);
|
||||
f32 translatedX = x + (font->xOffset * scale);
|
||||
f32 translatedY = y + (font->yOffset * scale);
|
||||
djui_hud_position_translate(&translatedX, &translatedY);
|
||||
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
|
||||
|
||||
// compute font size
|
||||
// rotate
|
||||
f32 translatedFontSize = fontScale;
|
||||
djui_hud_size_translate(&translatedFontSize);
|
||||
if (sHudUtilsState.rotation.degrees.prev != 0 || sHudUtilsState.rotation.degrees.curr != 0) {
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_ROTATION);
|
||||
f32 pivotTranslationX = font->defaultFontScale * translatedFontSize * sHudUtilsState.rotation.pivotX.curr;
|
||||
f32 pivotTranslationY = font->defaultFontScale * translatedFontSize * sHudUtilsState.rotation.pivotY.curr;
|
||||
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);
|
||||
}
|
||||
|
||||
// compute font size
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE);
|
||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSize, translatedFontSize, 1.0f);
|
||||
|
||||
// render the line
|
||||
f32 addX = 0;
|
||||
char* c = (char*)message;
|
||||
while (*c != '\0') {
|
||||
f32 charWidth = font->char_width(c);
|
||||
// allocate the translation matrix for the vertical alignment
|
||||
InterpHudGfx *valignGfx = djui_hud_create_interp_gfx(interp, INTERP_HUD_VALIGN);
|
||||
Mtx *valignMatrix = allocate_dl_translation_matrix();
|
||||
if (valignMatrix == NULL) { return; }
|
||||
|
||||
if (*c == '\n' && *c == ' ') {
|
||||
addX += charWidth;
|
||||
c++;
|
||||
// allocate the translation matrix for the horizontal alignment
|
||||
InterpHudGfx *halignGfx = djui_hud_create_interp_gfx(interp, INTERP_HUD_HALIGN);
|
||||
Mtx *halignMatrix = allocate_dl_translation_matrix();
|
||||
if (halignMatrix == NULL) { return; }
|
||||
|
||||
// render the line
|
||||
char* c = (char*)message;
|
||||
const char *end = message + strlen(message);
|
||||
f32 lineWidth = 0;
|
||||
f32 textHeight = font->lineHeight;
|
||||
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
// new line
|
||||
if (*c == '\n') {
|
||||
|
||||
// compute the horizontal alignment matrix for the current line
|
||||
guTranslate(halignMatrix, -lineWidth * sHudUtilsState.textAlignment.h.curr, 0, 0);
|
||||
if (halignGfx) { halignGfx->params[0] = lineWidth; }
|
||||
|
||||
// allocate a new translation matrix for the next line
|
||||
halignGfx = djui_hud_create_interp_gfx(interp, INTERP_HUD_HALIGN);
|
||||
halignMatrix = allocate_dl_translation_matrix();
|
||||
if (halignMatrix == NULL) { return; }
|
||||
|
||||
// cancel out the line translation and move to the next line
|
||||
// this is needed because otherwise the text would be rendered in a staircase way
|
||||
InterpHudGfx *newlineGfx = djui_hud_create_interp_gfx(interp, INTERP_HUD_NEW_LINE);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -lineWidth * (1.f - sHudUtilsState.textAlignment.h.curr), -font->lineHeight, 0);
|
||||
if (newlineGfx) { newlineGfx->params[0] = lineWidth; }
|
||||
lineWidth = 0;
|
||||
textHeight += font->lineHeight;
|
||||
c = djui_unicode_next_char(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
// tab: align to the next (4 x space width)
|
||||
else if (*c == '\t') {
|
||||
f32 tabWidth = 4 * font->char_width(" ");
|
||||
f32 newLineWidth = lineWidth + tabWidth - fmodf(lineWidth, tabWidth);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, newLineWidth - lineWidth, 0, 0);
|
||||
lineWidth = newLineWidth;
|
||||
c = djui_unicode_next_char(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
// unprintable chars
|
||||
if (!djui_text_is_printable(c)) {
|
||||
c = djui_unicode_next_char(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
// render
|
||||
f32 charWidth = font->char_width(c);
|
||||
font->render_char(c);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, charWidth + addX, 0, 0);
|
||||
addX = 0;
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, charWidth, 0, 0);
|
||||
lineWidth += charWidth;
|
||||
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
font->render_end();
|
||||
|
||||
// compute the horizontal alignment matrix for the last line
|
||||
guTranslate(halignMatrix, -lineWidth * sHudUtilsState.textAlignment.h.curr, 0, 0);
|
||||
if (halignGfx) { halignGfx->params[0] = lineWidth; }
|
||||
|
||||
// compute the vertical alignment matrix
|
||||
guTranslate(valignMatrix, 0, textHeight * sHudUtilsState.textAlignment.v.curr, 0);
|
||||
if (valignGfx) { valignGfx->params[0] = textHeight; }
|
||||
|
||||
// pop
|
||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scale) {
|
||||
djui_hud_print_text_internal(message, x, y, scale, NULL);
|
||||
}
|
||||
|
||||
void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScale, f32 x, f32 y, f32 scale) {
|
||||
if (message == NULL) { return; }
|
||||
f32 savedZ = gDjuiHudUtilsZ;
|
||||
gDjuiHudUtilsZ += 0.001f;
|
||||
|
||||
if (sLegacy) {
|
||||
prevScale *= 0.5f;
|
||||
scale *= 0.5f;
|
||||
if (djui_hud_text_font_is_legacy()) { prevScale *= 0.5f; }
|
||||
|
||||
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 = prevScale;
|
||||
interp->scaleY.prev = prevScale;
|
||||
interp->scaleX.curr = scale;
|
||||
interp->scaleY.curr = scale;
|
||||
interp->width = font->defaultFontScale;
|
||||
interp->height = font->defaultFontScale;
|
||||
}
|
||||
|
||||
const struct DjuiFont* font = gDjuiFonts[sFont];
|
||||
f32 fontScale = font->defaultFontScale * scale;
|
||||
|
||||
// setup display list
|
||||
if (font->textBeginDisplayList != NULL) {
|
||||
gSPDisplayList(gDisplayListHead++, font->textBeginDisplayList);
|
||||
}
|
||||
|
||||
Gfx* savedHeadPos = gDisplayListHead;
|
||||
|
||||
// translate position
|
||||
f32 translatedX = x + (font->xOffset * scale);
|
||||
f32 translatedY = y + (font->yOffset * scale);
|
||||
djui_hud_position_translate(&translatedX, &translatedY);
|
||||
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
|
||||
|
||||
// compute font size
|
||||
f32 translatedFontSize = fontScale;
|
||||
djui_hud_size_translate(&translatedFontSize);
|
||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSize, translatedFontSize, 1.0f);
|
||||
|
||||
// render the line
|
||||
f32 addX = 0;
|
||||
char* c = (char*)message;
|
||||
while (*c != '\0') {
|
||||
f32 charWidth = font->char_width(c);
|
||||
|
||||
if (*c == '\n' && *c == ' ') {
|
||||
addX += charWidth;
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// render
|
||||
font->render_char(c);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, charWidth + addX, 0, 0);
|
||||
addX = 0;
|
||||
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
|
||||
// pop
|
||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
|
||||
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
|
||||
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
|
||||
interp->headPos = savedHeadPos;
|
||||
interp->prevX = prevX;
|
||||
interp->prevY = prevY;
|
||||
interp->prevScaleW = prevScale;
|
||||
interp->prevScaleH = prevScale;
|
||||
interp->x = x;
|
||||
interp->y = y;
|
||||
interp->scaleW = scale;
|
||||
interp->scaleH = scale;
|
||||
interp->width = font->defaultFontScale;
|
||||
interp->height = font->defaultFontScale;
|
||||
interp->z = savedZ;
|
||||
interp->resolution = sResolution;
|
||||
interp->rotation = sRotation;
|
||||
djui_hud_print_text_internal(message, x, y, scale, interp);
|
||||
}
|
||||
|
||||
static inline bool is_power_of_two(u32 n) {
|
||||
return (n > 0) && ((n & (n - 1)) == 0);
|
||||
}
|
||||
|
||||
static void djui_hud_render_texture_raw(const Texture* texture, u32 width, u32 height, u8 fmt, u8 siz, f32 x, f32 y, f32 scaleW, f32 scaleH) {
|
||||
static void djui_hud_render_texture_raw(const Texture* texture, u32 width, u32 height, u8 fmt, u8 siz, f32 x, f32 y, f32 scaleW, f32 scaleH, struct InterpHud *interp) {
|
||||
if (!is_power_of_two(width) || !is_power_of_two(height)) {
|
||||
LOG_LUA_LINE("Tried to render DJUI HUD texture with NPOT width or height");
|
||||
return;
|
||||
|
|
@ -510,6 +695,7 @@ static void djui_hud_render_texture_raw(const Texture* texture, u32 width, u32 h
|
|||
gDjuiHudUtilsZ += 0.001f;
|
||||
|
||||
// translate position
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION);
|
||||
f32 translatedX = x;
|
||||
f32 translatedY = y;
|
||||
djui_hud_position_translate(&translatedX, &translatedY);
|
||||
|
|
@ -520,25 +706,27 @@ static void djui_hud_render_texture_raw(const Texture* texture, u32 width, u32 h
|
|||
f32 translatedH = scaleH;
|
||||
djui_hud_size_translate(&translatedW);
|
||||
djui_hud_size_translate(&translatedH);
|
||||
if (sRotation.rotation != 0) {
|
||||
f32 pivotTranslationX = width * translatedW * sRotation.pivotX;
|
||||
f32 pivotTranslationY = height * translatedH * sRotation.pivotY;
|
||||
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, sRotation.rotation, 0, 0, 1);
|
||||
create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sHudUtilsState.rotation.degrees.curr, 0, 0, 1);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
|
||||
}
|
||||
|
||||
// translate scale
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE);
|
||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, width * translatedW, height * translatedH, 1.0f);
|
||||
|
||||
// render
|
||||
djui_gfx_render_texture(texture, width, height, fmt, siz, sFilter);
|
||||
djui_gfx_render_texture(texture, width, height, fmt, siz, sHudUtilsState.filter);
|
||||
|
||||
// pop
|
||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
|
|
@ -546,6 +734,7 @@ static void djui_hud_render_texture_tile_raw(const Texture* texture, u32 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);
|
||||
|
|
@ -556,20 +745,22 @@ static void djui_hud_render_texture_tile_raw(const Texture* texture, u32 width,
|
|||
f32 translatedH = scaleH;
|
||||
djui_hud_size_translate(&translatedW);
|
||||
djui_hud_size_translate(&translatedH);
|
||||
if (sRotation.rotation != 0) {
|
||||
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 * sRotation.pivotX;
|
||||
f32 pivotTranslationY = height * translatedH * sRotation.pivotY;
|
||||
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, sRotation.rotation, 0, 0, 1);
|
||||
create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sHudUtilsState.rotation.degrees.curr, 0, 0, 1);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
|
||||
}
|
||||
|
||||
// translate scale
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE);
|
||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, width * translatedW, height * translatedH, 1.0f);
|
||||
|
||||
// render
|
||||
djui_gfx_render_texture_tile(texture, width, height, fmt, siz, tileX, tileY, tileW, tileH, sFilter, false);
|
||||
djui_gfx_render_texture_tile(texture, width, height, fmt, siz, tileX, tileY, tileW, tileH, sHudUtilsState.filter);
|
||||
|
||||
// pop
|
||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
|
|
@ -577,44 +768,35 @@ static void djui_hud_render_texture_tile_raw(const Texture* texture, u32 width,
|
|||
|
||||
void djui_hud_render_texture(struct TextureInfo* texInfo, f32 x, f32 y, f32 scaleW, f32 scaleH) {
|
||||
if (!texInfo) { return; }
|
||||
djui_hud_render_texture_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, x, y, scaleW, scaleH);
|
||||
djui_hud_render_texture_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, x, y, scaleW, scaleH, NULL);
|
||||
}
|
||||
|
||||
void djui_hud_render_texture_tile(struct TextureInfo* texInfo, f32 x, f32 y, f32 scaleW, f32 scaleH, u32 tileX, u32 tileY, u32 tileW, u32 tileH) {
|
||||
if (!texInfo) { return; }
|
||||
djui_hud_render_texture_tile_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, x, y, scaleW, scaleH, tileX, tileY, tileW, tileH);
|
||||
djui_hud_render_texture_tile_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, x, y, scaleW, scaleH, tileX, tileY, tileW, tileH, NULL);
|
||||
}
|
||||
|
||||
void djui_hud_render_texture_interpolated(struct TextureInfo* texInfo, f32 prevX, f32 prevY, f32 prevScaleW, f32 prevScaleH, f32 x, f32 y, f32 scaleW, f32 scaleH) {
|
||||
Gfx* savedHeadPos = gDisplayListHead;
|
||||
f32 savedZ = gDjuiHudUtilsZ;
|
||||
|
||||
if (!texInfo) { return; }
|
||||
|
||||
djui_hud_render_texture_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, prevX, prevY, prevScaleW, prevScaleH);
|
||||
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->width = texInfo->width;
|
||||
interp->height = texInfo->height;
|
||||
}
|
||||
|
||||
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
|
||||
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
|
||||
interp->headPos = savedHeadPos;
|
||||
interp->prevX = prevX;
|
||||
interp->prevY = prevY;
|
||||
interp->prevScaleW = prevScaleW;
|
||||
interp->prevScaleH = prevScaleH;
|
||||
interp->x = x;
|
||||
interp->y = y;
|
||||
interp->scaleW = scaleW;
|
||||
interp->scaleH = scaleH;
|
||||
interp->width = texInfo->width;
|
||||
interp->height = texInfo->height;
|
||||
interp->z = savedZ;
|
||||
interp->resolution = sResolution;
|
||||
interp->rotation = sRotation;
|
||||
djui_hud_render_texture_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, prevX, prevY, prevScaleW, prevScaleH, interp);
|
||||
}
|
||||
|
||||
void djui_hud_render_texture_tile_interpolated(struct TextureInfo* texInfo, f32 prevX, f32 prevY, f32 prevScaleW, f32 prevScaleH, f32 x, f32 y, f32 scaleW, f32 scaleH, u32 tileX, u32 tileY, u32 tileW, u32 tileH) {
|
||||
Gfx* savedHeadPos = gDisplayListHead;
|
||||
f32 savedZ = gDjuiHudUtilsZ;
|
||||
|
||||
if (!texInfo) { return; }
|
||||
|
||||
// apply scale correction for tiles
|
||||
|
|
@ -627,30 +809,28 @@ void djui_hud_render_texture_tile_interpolated(struct TextureInfo* texInfo, f32
|
|||
prevScaleH *= ((f32)tileH / (f32)texInfo->height);
|
||||
}
|
||||
|
||||
djui_hud_render_texture_tile_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, prevX, prevY, prevScaleW, prevScaleH, tileX, tileY, tileW, tileH);
|
||||
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->width = texInfo->width;
|
||||
interp->height = texInfo->height;
|
||||
}
|
||||
|
||||
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
|
||||
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
|
||||
interp->headPos = savedHeadPos;
|
||||
interp->prevX = prevX;
|
||||
interp->prevY = prevY;
|
||||
interp->prevScaleW = prevScaleW;
|
||||
interp->prevScaleH = prevScaleH;
|
||||
interp->x = x;
|
||||
interp->y = y;
|
||||
interp->scaleW = scaleW;
|
||||
interp->scaleH = scaleH;
|
||||
interp->width = texInfo->width;
|
||||
interp->height = texInfo->height;
|
||||
interp->z = savedZ;
|
||||
interp->resolution = sResolution;
|
||||
interp->rotation = sRotation;
|
||||
djui_hud_render_texture_tile_raw(texInfo->texture, texInfo->width, texInfo->height, texInfo->format, texInfo->size, prevX, prevY, prevScaleW, prevScaleH, tileX, tileY, tileW, tileH, interp);
|
||||
}
|
||||
|
||||
void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) {
|
||||
static void djui_hud_render_rect_internal(f32 x, f32 y, f32 width, f32 height, struct InterpHud *interp) {
|
||||
gDjuiHudUtilsZ += 0.001f;
|
||||
|
||||
// translate position
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_TRANSLATION);
|
||||
f32 translatedX = x;
|
||||
f32 translatedY = y;
|
||||
djui_hud_position_translate(&translatedX, &translatedY);
|
||||
|
|
@ -661,15 +841,17 @@ void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) {
|
|||
f32 translatedH = height;
|
||||
djui_hud_size_translate(&translatedW);
|
||||
djui_hud_size_translate(&translatedH);
|
||||
if (sRotation.rotation != 0) {
|
||||
f32 pivotTranslationX = translatedW * sRotation.pivotX;
|
||||
f32 pivotTranslationY = translatedH * sRotation.pivotY;
|
||||
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, sRotation.rotation, 0, 0, 1);
|
||||
create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sHudUtilsState.rotation.degrees.curr, 0, 0, 1);
|
||||
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
|
||||
}
|
||||
|
||||
// translate scale
|
||||
djui_hud_create_interp_gfx(interp, INTERP_HUD_SCALE);
|
||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedW, translatedH, 1.0f);
|
||||
|
||||
// render
|
||||
|
|
@ -679,28 +861,26 @@ void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) {
|
|||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) {
|
||||
djui_hud_render_rect_internal(x, y, width, height, NULL);
|
||||
}
|
||||
|
||||
void djui_hud_render_rect_interpolated(f32 prevX, f32 prevY, f32 prevWidth, f32 prevHeight, f32 x, f32 y, f32 width, f32 height) {
|
||||
Gfx* savedHeadPos = gDisplayListHead;
|
||||
f32 savedZ = gDjuiHudUtilsZ;
|
||||
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->width = 1;
|
||||
interp->height = 1;
|
||||
}
|
||||
|
||||
djui_hud_render_rect(prevX, prevY, prevWidth, prevHeight);
|
||||
|
||||
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
|
||||
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
|
||||
interp->headPos = savedHeadPos;
|
||||
interp->prevX = prevX;
|
||||
interp->prevY = prevY;
|
||||
interp->prevScaleW = prevWidth;
|
||||
interp->prevScaleH = prevHeight;
|
||||
interp->x = x;
|
||||
interp->y = y;
|
||||
interp->scaleW = width;
|
||||
interp->scaleH = height;
|
||||
interp->width = 1;
|
||||
interp->height = 1;
|
||||
interp->z = savedZ;
|
||||
interp->resolution = sResolution;
|
||||
interp->rotation = sRotation;
|
||||
djui_hud_render_rect_internal(prevX, prevY, prevWidth, prevHeight, interp);
|
||||
}
|
||||
|
||||
void djui_hud_render_line(f32 p1X, f32 p1Y, f32 p2X, f32 p2Y, f32 size) {
|
||||
|
|
@ -752,7 +932,7 @@ bool djui_hud_world_pos_to_screen_pos(Vec3f pos, VEC_OUT Vec3f out) {
|
|||
out[1] *= fovCoeff;
|
||||
|
||||
f32 screenWidth, screenHeight;
|
||||
if (sResolution == RESOLUTION_N64) {
|
||||
if (sHudUtilsState.resolution == RESOLUTION_N64) {
|
||||
screenWidth = GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT;
|
||||
screenHeight = SCREEN_HEIGHT;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,22 @@
|
|||
#ifndef DJUI_HUD_UTILS_H
|
||||
#define DJUI_HUD_UTILS_H
|
||||
|
||||
// Common pivot values for rotation
|
||||
#define ROTATION_PIVOT_X_LEFT 0.0
|
||||
#define ROTATION_PIVOT_X_CENTER 0.5
|
||||
#define ROTATION_PIVOT_X_RIGHT 1.0
|
||||
#define ROTATION_PIVOT_Y_TOP 0.0
|
||||
#define ROTATION_PIVOT_Y_CENTER 0.5
|
||||
#define ROTATION_PIVOT_Y_BOTTOM 1.0
|
||||
|
||||
// Common alignment values for text alignment
|
||||
#define TEXT_HALIGN_LEFT 0.0
|
||||
#define TEXT_HALIGN_CENTER 0.5
|
||||
#define TEXT_HALIGN_RIGHT 1.0
|
||||
#define TEXT_VALIGN_TOP 0.0
|
||||
#define TEXT_VALIGN_CENTER 0.5
|
||||
#define TEXT_VALIGN_BOTTOM 1.0
|
||||
|
||||
enum HudUtilsResolution {
|
||||
RESOLUTION_DJUI,
|
||||
RESOLUTION_N64,
|
||||
|
|
@ -14,7 +30,8 @@ enum HudUtilsFilter {
|
|||
};
|
||||
|
||||
enum DjuiFontType {
|
||||
FONT_NORMAL,
|
||||
FONT_LEGACY = -1,
|
||||
FONT_NORMAL = 0,
|
||||
FONT_MENU,
|
||||
FONT_HUD,
|
||||
FONT_ALIASED,
|
||||
|
|
@ -24,15 +41,6 @@ enum DjuiFontType {
|
|||
FONT_COUNT,
|
||||
};
|
||||
|
||||
struct HudUtilsRotation {
|
||||
f32 rotation;
|
||||
f32 rotationDiff;
|
||||
f32 prevPivotX;
|
||||
f32 prevPivotY;
|
||||
f32 pivotX;
|
||||
f32 pivotY;
|
||||
};
|
||||
|
||||
struct GlobalTextures {
|
||||
struct TextureInfo camera;
|
||||
struct TextureInfo lakitu;
|
||||
|
|
@ -63,7 +71,7 @@ u8 djui_hud_get_filter(void);
|
|||
/* |description|Sets the current DJUI HUD texture filter|descriptionEnd| */
|
||||
void djui_hud_set_filter(enum HudUtilsFilter filterType);
|
||||
/* |description|Gets the current DJUI HUD font|descriptionEnd| */
|
||||
u8 djui_hud_get_font(void);
|
||||
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| */
|
||||
|
|
@ -73,11 +81,17 @@ void djui_hud_set_color(u8 r, u8 g, u8 b, u8 a);
|
|||
/* |description|Resets the current DJUI HUD color|descriptionEnd| */
|
||||
void djui_hud_reset_color(void);
|
||||
/* |description|Gets the current DJUI HUD rotation|descriptionEnd| */
|
||||
struct HudUtilsRotation* djui_hud_get_rotation(void);
|
||||
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);
|
||||
/* |description|Sets the current DJUI HUD rotation interpolated|descriptionEnd| */
|
||||
void djui_hud_set_rotation_interpolated(s32 prevRotation, f32 prevPivotX, f32 prevPivotY, s32 rotation, f32 pivotX, f32 pivotY);
|
||||
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| */
|
||||
void djui_hud_get_text_alignment(RET f32 *textHAlign, RET f32 *textVAlign);
|
||||
/* |description|Sets the current DJUI HUD text alignment|descriptionEnd| */
|
||||
void djui_hud_set_text_alignment(f32 textHAlign, f32 textVAlign);
|
||||
/* |description|Sets the current DJUI HUD text alignment interpolated|descriptionEnd| */
|
||||
void djui_hud_set_text_alignment_interpolated(f32 prevTextHAlign, f32 prevTextVAlign, f32 textHAlign, f32 textVAlign);
|
||||
|
||||
/* |description|Gets the screen width in the current DJUI HUD resolution|descriptionEnd| */
|
||||
u32 djui_hud_get_screen_width(void);
|
||||
|
|
|
|||
|
|
@ -589,6 +589,8 @@ static bool djui_inputbox_render(struct DjuiBase* base) {
|
|||
f32 drawX = inputbox->viewX;
|
||||
f32 additionalShift = 0;
|
||||
bool wasInsideSelection = false;
|
||||
|
||||
font->render_begin();
|
||||
for (u16 i = 0; i < inputbox->bufferSize; i++) {
|
||||
|
||||
//render composition text
|
||||
|
|
@ -617,6 +619,7 @@ static bool djui_inputbox_render(struct DjuiBase* base) {
|
|||
djui_inputbox_render_char(inputbox, c, &drawX, &additionalShift);
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
font->render_end();
|
||||
|
||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ void djui_panel_mod_menu_mod_create(struct DjuiBase* caller) {
|
|||
}
|
||||
if (mod == NULL) { return; }
|
||||
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(to_uppercase(mod->name), false);
|
||||
char *modNameUppercase = to_uppercase(mod->name);
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(modNameUppercase, false);
|
||||
struct DjuiBase* body = djui_three_panel_get_body(panel);
|
||||
{
|
||||
struct DjuiPaginated* paginated = djui_paginated_create(body, 8);
|
||||
|
|
@ -130,6 +131,7 @@ void djui_panel_mod_menu_mod_create(struct DjuiBase* caller) {
|
|||
}
|
||||
|
||||
djui_panel_add(caller, panel, NULL);
|
||||
free(modNameUppercase);
|
||||
}
|
||||
|
||||
void djui_panel_mod_menu_create(struct DjuiBase* caller) {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,146 @@
|
|||
#include "djui_hud_utils.h"
|
||||
#include "game/segment2.h"
|
||||
|
||||
static u8 sSavedR = 0;
|
||||
static u8 sSavedG = 0;
|
||||
static u8 sSavedB = 0;
|
||||
static u8 sSavedA = 0;
|
||||
///////////
|
||||
// color //
|
||||
///////////
|
||||
|
||||
static const struct DjuiColor sDjuiTextDefaultColor = { 220, 220, 220, 255 };
|
||||
static struct DjuiColor sDjuiTextCurrentColor;
|
||||
|
||||
bool djui_text_parse_color(char *begin, const char *end, bool ignoreAlpha, const struct DjuiColor *baseColor, char **nextChar, struct DjuiColor *parsedColor) {
|
||||
char *c = begin;
|
||||
|
||||
// Not an escape
|
||||
if (*c != '\\') {
|
||||
return false;
|
||||
}
|
||||
c = djui_unicode_next_char(c);
|
||||
|
||||
// Not a color
|
||||
if (*c != '#') {
|
||||
return false;
|
||||
}
|
||||
c = djui_unicode_next_char(c);
|
||||
|
||||
// Parse color
|
||||
u32 color = 0;
|
||||
u8 length = 0;
|
||||
while (c < end) {
|
||||
if (*c == '\\') {
|
||||
break;
|
||||
}
|
||||
|
||||
u8 colorPiece = 0;
|
||||
if (*c >= '0' && *c <= '9') { colorPiece = *c - '0'; }
|
||||
else if (*c >= 'a' && *c <= 'f') { colorPiece = 10 + *c - 'a'; }
|
||||
else if (*c >= 'A' && *c <= 'F') { colorPiece = 10 + *c - 'A'; }
|
||||
else { // Not a valid color piece
|
||||
return false;
|
||||
}
|
||||
color = (color << 4) | colorPiece;
|
||||
length++;
|
||||
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
|
||||
// Unterminated color code
|
||||
if (c == end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (length) {
|
||||
|
||||
// reset to base color
|
||||
case 0: {
|
||||
if (baseColor && parsedColor) {
|
||||
*parsedColor = *baseColor;
|
||||
}
|
||||
} break;
|
||||
|
||||
// #rgb
|
||||
case 3: {
|
||||
if (parsedColor) {
|
||||
u32 r = (color >> 8) & 0xF;
|
||||
u32 g = (color >> 4) & 0xF;
|
||||
u32 b = (color >> 0) & 0xF;
|
||||
parsedColor->r = (r << 4) | r;
|
||||
parsedColor->g = (g << 4) | g;
|
||||
parsedColor->b = (b << 4) | b;
|
||||
parsedColor->a = 0xFF;
|
||||
}
|
||||
} break;
|
||||
|
||||
// #rgba
|
||||
case 4: {
|
||||
if (parsedColor) {
|
||||
u32 r = (color >> 12) & 0xF;
|
||||
u32 g = (color >> 8) & 0xF;
|
||||
u32 b = (color >> 4) & 0xF;
|
||||
u32 a = (color >> 0) & 0xF;
|
||||
parsedColor->r = (r << 4) | r;
|
||||
parsedColor->g = (g << 4) | g;
|
||||
parsedColor->b = (b << 4) | b;
|
||||
parsedColor->a = ignoreAlpha ? 0xFF : ((a << 4) | a);
|
||||
}
|
||||
} break;
|
||||
|
||||
// #rrggbb
|
||||
case 6: {
|
||||
if (parsedColor) {
|
||||
parsedColor->r = ((color >> 16) & 0xFF);
|
||||
parsedColor->g = ((color >> 8) & 0xFF);
|
||||
parsedColor->b = ((color >> 0) & 0xFF);
|
||||
parsedColor->a = 0xFF;
|
||||
}
|
||||
} break;
|
||||
|
||||
// #rrggbbaa
|
||||
case 8: {
|
||||
if (parsedColor) {
|
||||
parsedColor->r = ((color >> 24) & 0xFF);
|
||||
parsedColor->g = ((color >> 16) & 0xFF);
|
||||
parsedColor->b = ((color >> 8) & 0xFF);
|
||||
parsedColor->a = ignoreAlpha ? 0xFF : ((color >> 0) & 0xFF);
|
||||
}
|
||||
} break;
|
||||
|
||||
// Invalid color
|
||||
default: return false;
|
||||
}
|
||||
|
||||
if (nextChar) {
|
||||
*nextChar = djui_unicode_next_char(c);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void djui_text_remove_colors(char *str) {
|
||||
if (!str) { return; }
|
||||
char *colorStart = str;
|
||||
const char *strEnd = str + strlen(str);
|
||||
while ((colorStart = strstr(colorStart, "\\#"))) {
|
||||
char *colorEnd;
|
||||
if (djui_text_parse_color(colorStart, strEnd, false, NULL, &colorEnd, NULL) && colorEnd > colorStart) {
|
||||
memmove(colorStart, colorEnd, strlen(colorEnd) + 1);
|
||||
} else {
|
||||
colorStart++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *djui_text_get_uncolored_string(char *dest, size_t length, const char *str) {
|
||||
if (!dest) {
|
||||
dest = malloc(length * sizeof(char));
|
||||
if (!dest) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
strncpy(dest, str, length - 1);
|
||||
dest[length - 1] = 0;
|
||||
djui_text_remove_colors(dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
////////////////
|
||||
// properties //
|
||||
|
|
@ -59,6 +195,10 @@ static f32 sTextRenderY = 0;
|
|||
static f32 sTextRenderLastX = 0;
|
||||
static f32 sTextRenderLastY = 0;
|
||||
|
||||
bool djui_text_is_printable(const char *c) {
|
||||
return c != NULL && (!iscntrl(*c) || *c == 0x7F); // the star
|
||||
}
|
||||
|
||||
static void djui_text_translate(f32 x, f32 y) {
|
||||
sTextRenderX += x;
|
||||
sTextRenderY += y;
|
||||
|
|
@ -90,7 +230,7 @@ static void djui_text_render_char(struct DjuiText* text, char* c) {
|
|||
sTextRenderY += 1.0f / text->fontScale;
|
||||
gDPSetEnvColor(gDisplayListHead++, text->dropShadow.r, text->dropShadow.g, text->dropShadow.b, text->dropShadow.a);
|
||||
djui_text_render_single_char(text, c);
|
||||
gDPSetEnvColor(gDisplayListHead++, sSavedR, sSavedG, sSavedB, sSavedA);
|
||||
gDPSetEnvColor(gDisplayListHead++, sDjuiTextCurrentColor.r, sDjuiTextCurrentColor.g, sDjuiTextCurrentColor.b, sDjuiTextCurrentColor.a);
|
||||
sTextRenderX -= 1.0f / text->fontScale;
|
||||
sTextRenderY -= 1.0f / text->fontScale;
|
||||
}
|
||||
|
|
@ -99,16 +239,21 @@ static void djui_text_render_char(struct DjuiText* text, char* c) {
|
|||
|
||||
static f32 djui_text_measure_word_width(struct DjuiText* text, char* message) {
|
||||
f32 width = 0;
|
||||
bool skipping = false;
|
||||
char* c = message;
|
||||
const char *end = message + strlen(message);
|
||||
while (*c != '\0') {
|
||||
if (*c == ' ') { return width; }
|
||||
if (*c == '\n') { return width; }
|
||||
if (*c == '\0') { return width; }
|
||||
if (*c == '\\') { skipping = !skipping; }
|
||||
if (!skipping) {
|
||||
width += text->font->char_width(c);
|
||||
|
||||
// color code
|
||||
if (djui_text_parse_color(c, end, true, NULL, &c, NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// end of word due to unprintable chars or space
|
||||
if (!djui_text_is_printable(c) || *c == ' ') {
|
||||
return width;
|
||||
}
|
||||
|
||||
width += text->font->char_width(c);
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
return width;
|
||||
|
|
@ -122,17 +267,18 @@ static void djui_text_read_line(struct DjuiText* text, char** message, f32* line
|
|||
u16 lastSafeEllipsesIndex = *index;
|
||||
u16 lastSafeEllipsesLineWidth = *lineWidth + ellipsesWidth;*/
|
||||
|
||||
bool skipping = false;
|
||||
char* c = *message;
|
||||
const char *end = *message + strlen(*message);
|
||||
while (*c != '\0') {
|
||||
f32 charWidth = text->font->char_width(c);
|
||||
|
||||
// check for special escape sequences
|
||||
if (*c == '\\') { skipping = !skipping; }
|
||||
if (skipping || *c == '\\') {
|
||||
// check for color code
|
||||
if (*c == '\\') {
|
||||
lastC = c;
|
||||
c = djui_unicode_next_char(c);
|
||||
continue;
|
||||
if (djui_text_parse_color(c, end, true, NULL, &c, NULL)) {
|
||||
lastC = c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check for newline
|
||||
|
|
@ -212,59 +358,6 @@ f32 djui_text_find_width(struct DjuiText* text, u16 maxLines) {
|
|||
return largestWidth * text->fontScale;
|
||||
}
|
||||
|
||||
static char* djui_text_render_line_parse_escape(char* c1, char* c2) {
|
||||
bool parsingColor = (c1[1] == '#');
|
||||
char* c = parsingColor ? (c1 + 2) : (c1 + 1);
|
||||
|
||||
u32 color = 0;
|
||||
u8 colorPieces = 0;
|
||||
while (c < c2) {
|
||||
if (*c == '\\') { break; }
|
||||
if (parsingColor) {
|
||||
u8 colorPiece = 0;
|
||||
if (*c >= '0' && *c <= '9') { colorPiece = *c - '0'; }
|
||||
else if (*c >= 'a' && *c <= 'f') { colorPiece = 10 + *c - 'a'; }
|
||||
else if (*c >= 'A' && *c <= 'F') { colorPiece = 10 + *c - 'A'; }
|
||||
color = (color << 4) | colorPiece;
|
||||
colorPieces++;
|
||||
}
|
||||
c = djui_unicode_next_char(c);
|
||||
}
|
||||
|
||||
if (parsingColor) {
|
||||
if (colorPieces == 3) {
|
||||
u32 r = (color >> 8) & 0xF;
|
||||
u32 g = (color >> 4) & 0xF;
|
||||
u32 b = (color >> 0) & 0xF;
|
||||
sSavedR = (r << 4) | r;
|
||||
sSavedG = (g << 4) | g;
|
||||
sSavedB = (b << 4) | b;
|
||||
/*} else if (colorPieces == 4) {
|
||||
u32 r = (color >> 12) & 0xF;
|
||||
u32 g = (color >> 8) & 0xF;
|
||||
u32 b = (color >> 4) & 0xF;
|
||||
u32 a = (color >> 0) & 0xF;
|
||||
sSavedR = (r << 4) | r;
|
||||
sSavedG = (g << 4) | g;
|
||||
sSavedB = (b << 4) | b;
|
||||
sSavedA = (a << 4) | a;*/
|
||||
} else if (colorPieces == 6) {
|
||||
sSavedR = ((color >> 16) & 0xFF);
|
||||
sSavedG = ((color >> 8) & 0xFF);
|
||||
sSavedB = ((color >> 0) & 0xFF);
|
||||
}/*else if (colorPieces == 8) {
|
||||
sSavedR = ((color >> 24) & 0xFF);
|
||||
sSavedG = ((color >> 16) & 0xFF);
|
||||
sSavedB = ((color >> 8) & 0xFF);
|
||||
sSavedA = ((color >> 0) & 0xFF);
|
||||
}*/
|
||||
gDPSetEnvColor(gDisplayListHead++, sSavedR, sSavedG, sSavedB, sSavedA);
|
||||
}
|
||||
|
||||
c = djui_unicode_next_char(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void djui_text_render_line(struct DjuiText* text, char* c1, char* c2, f32 lineWidth, bool ellipses) {
|
||||
struct DjuiBase* base = &text->base;
|
||||
struct DjuiBaseRect* comp = &base->comp;
|
||||
|
|
@ -284,9 +377,13 @@ static void djui_text_render_line(struct DjuiText* text, char* c1, char* c2, f32
|
|||
}
|
||||
|
||||
// render the line
|
||||
text->font->render_begin();
|
||||
|
||||
for (char* c = c1; c < c2;) {
|
||||
if (*c == '\\') {
|
||||
c = djui_text_render_line_parse_escape(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;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -312,6 +409,8 @@ static void djui_text_render_line(struct DjuiText* text, char* c1, char* c2, f32
|
|||
}
|
||||
}
|
||||
|
||||
text->font->render_end();
|
||||
|
||||
// reset translation matrix
|
||||
djui_text_translate(-curWidth, text->font->lineHeight);
|
||||
}
|
||||
|
|
@ -352,10 +451,7 @@ static bool djui_text_render(struct DjuiBase* base) {
|
|||
|
||||
// set color
|
||||
gDPSetEnvColor(gDisplayListHead++, base->color.r, base->color.g, base->color.b, base->color.a);
|
||||
sSavedR = base->color.r;
|
||||
sSavedG = base->color.g;
|
||||
sSavedB = base->color.b;
|
||||
sSavedA = base->color.a;
|
||||
sDjuiTextCurrentColor = base->color;
|
||||
|
||||
// count lines
|
||||
u16 maxLines = comp->height / ((f32)text->font->lineHeight * text->fontScale);
|
||||
|
|
|
|||
|
|
@ -11,12 +11,17 @@ struct DjuiText {
|
|||
enum DjuiVAlign textVAlign;
|
||||
};
|
||||
|
||||
bool djui_text_parse_color(char *begin, const char *end, bool ignoreAlpha, const struct DjuiColor *baseColor, char **nextChar, struct DjuiColor *parsedColor);
|
||||
void djui_text_remove_colors(char *str);
|
||||
char *djui_text_get_uncolored_string(char *dest, size_t length, const char *str);
|
||||
|
||||
void djui_text_set_text(struct DjuiText* text, const char* message);
|
||||
void djui_text_set_font(struct DjuiText* text, const struct DjuiFont* font);
|
||||
void djui_text_set_font_scale(struct DjuiText* text, f32 fontScale);
|
||||
void djui_text_set_drop_shadow(struct DjuiText* text, f32 r, f32 g, f32 b, f32 a);
|
||||
void djui_text_set_alignment(struct DjuiText* text, enum DjuiHAlign hAlign, enum DjuiVAlign vAlign);
|
||||
|
||||
bool djui_text_is_printable(const char *c);
|
||||
int djui_text_count_lines(struct DjuiText* text, u16 maxLines);
|
||||
f32 djui_text_find_width(struct DjuiText* text, u16 maxLines);
|
||||
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ struct SmCodeGlyph sSmCodeDuplicateGlyphs[] = {
|
|||
|
||||
static void* sCharMap = NULL;
|
||||
|
||||
static s32 count_bytes_for_char(char* text) {
|
||||
static s32 count_bytes_for_char(const char* text) {
|
||||
s32 bytes = 0;
|
||||
u8 mask = (1 << 7);
|
||||
while (*text & mask) {
|
||||
|
|
@ -214,7 +214,7 @@ static s32 count_bytes_for_char(char* text) {
|
|||
return bytes ? bytes : 1;
|
||||
}
|
||||
|
||||
static u64 convert_unicode_char_to_u64(char* text) {
|
||||
static u64 convert_unicode_char_to_u64(const char* text) {
|
||||
s32 bytes = count_bytes_for_char(text);
|
||||
u64 value = (u8)*text;
|
||||
|
||||
|
|
@ -273,7 +273,7 @@ void djui_unicode_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
u32 djui_unicode_get_sprite_index(char* text) {
|
||||
u32 djui_unicode_get_sprite_index(const char* text) {
|
||||
// check for ASCI
|
||||
if ((u8)*text < 128) {
|
||||
// make sure it's in the valid range
|
||||
|
|
@ -298,7 +298,7 @@ u32 djui_unicode_get_sprite_index(char* text) {
|
|||
return (u8)'?' - SPRITE_INDEX_START_CHAR;
|
||||
}
|
||||
|
||||
f32 djui_unicode_get_sprite_width(char* text, const f32 font_widths[], f32 unicodeScale) {
|
||||
f32 djui_unicode_get_sprite_width(const char* text, const f32 font_widths[], f32 unicodeScale) {
|
||||
if (!text) { return 0; }
|
||||
|
||||
// check for ASCII
|
||||
|
|
@ -358,7 +358,7 @@ size_t djui_unicode_len(char* text) {
|
|||
return len;
|
||||
}
|
||||
|
||||
bool djui_unicode_valid_char(char* text) {
|
||||
bool djui_unicode_valid_char(const char* text) {
|
||||
if ((u8)*text < 128) {
|
||||
return ((u8)*text >= ' ');
|
||||
}
|
||||
|
|
@ -397,7 +397,7 @@ void djui_unicode_cleanup_end(char* text) {
|
|||
}
|
||||
}
|
||||
|
||||
char djui_unicode_get_base_char(char* text) {
|
||||
char djui_unicode_get_base_char(const char* text) {
|
||||
if ((u8)*text < ' ') { return '?'; }
|
||||
if ((u8)*text < 128) { return *text; }
|
||||
if (!sCharMap) { return '?'; }
|
||||
|
|
@ -406,7 +406,7 @@ char djui_unicode_get_base_char(char* text) {
|
|||
return (glyph == NULL) ? '?' : glyph->base;
|
||||
}
|
||||
|
||||
void djui_unicode_get_char(char* text, char* output) {
|
||||
void djui_unicode_get_char(const char* text, char* output) {
|
||||
s32 bytes = count_bytes_for_char(text);
|
||||
while (bytes-- > 0) {
|
||||
*output = *text;
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
void djui_unicode_init(void);
|
||||
u32 djui_unicode_get_sprite_index(char* text);
|
||||
f32 djui_unicode_get_sprite_width(char* text, const f32 font_widths[], f32 unicodeScale);
|
||||
u32 djui_unicode_get_sprite_index(const char* text);
|
||||
f32 djui_unicode_get_sprite_width(const char* text, const f32 font_widths[], f32 unicodeScale);
|
||||
char* djui_unicode_next_char(char* text);
|
||||
char* djui_unicode_at_index(char* text, s32 index);
|
||||
size_t djui_unicode_len(char* text);
|
||||
bool djui_unicode_valid_char(char* text);
|
||||
bool djui_unicode_valid_char(const char* text);
|
||||
void djui_unicode_cleanup_end(char* text);
|
||||
char djui_unicode_get_base_char(char* text);
|
||||
void djui_unicode_get_char(char* text, char* output);
|
||||
char djui_unicode_get_base_char(const char* text);
|
||||
void djui_unicode_get_char(const char* text, char* output);
|
||||
|
|
|
|||
|
|
@ -1228,16 +1228,6 @@ static struct LuaObjectField sGraphNodeTranslationRotationFields[LUA_GRAPH_NODE_
|
|||
{ "translation", LVT_COBJECT, offsetof(struct GraphNodeTranslationRotation, translation), true, LOT_VEC3S, 1, sizeof(Vec3s) },
|
||||
};
|
||||
|
||||
#define LUA_HUD_UTILS_ROTATION_FIELD_COUNT 6
|
||||
static struct LuaObjectField sHudUtilsRotationFields[LUA_HUD_UTILS_ROTATION_FIELD_COUNT] = {
|
||||
{ "pivotX", LVT_F32, offsetof(struct HudUtilsRotation, pivotX), false, LOT_NONE, 1, sizeof(f32) },
|
||||
{ "pivotY", LVT_F32, offsetof(struct HudUtilsRotation, pivotY), false, LOT_NONE, 1, sizeof(f32) },
|
||||
{ "prevPivotX", LVT_F32, offsetof(struct HudUtilsRotation, prevPivotX), false, LOT_NONE, 1, sizeof(f32) },
|
||||
{ "prevPivotY", LVT_F32, offsetof(struct HudUtilsRotation, prevPivotY), false, LOT_NONE, 1, sizeof(f32) },
|
||||
{ "rotation", LVT_F32, offsetof(struct HudUtilsRotation, rotation), false, LOT_NONE, 1, sizeof(f32) },
|
||||
{ "rotationDiff", LVT_F32, offsetof(struct HudUtilsRotation, rotationDiff), false, LOT_NONE, 1, sizeof(f32) },
|
||||
};
|
||||
|
||||
#define LUA_INSTANT_WARP_FIELD_COUNT 3
|
||||
static struct LuaObjectField sInstantWarpFields[LUA_INSTANT_WARP_FIELD_COUNT] = {
|
||||
{ "area", LVT_U8, offsetof(struct InstantWarp, area), false, LOT_NONE, 1, sizeof(u8) },
|
||||
|
|
@ -1484,7 +1474,7 @@ static struct LuaObjectField sModFields[LUA_MOD_FIELD_COUNT] = {
|
|||
{ "incompatible", LVT_STRING_P, offsetof(struct Mod, incompatible), true, LOT_NONE, 1, sizeof(char*) },
|
||||
{ "index", LVT_S32, offsetof(struct Mod, index), true, LOT_NONE, 1, sizeof(s32) },
|
||||
{ "isDirectory", LVT_BOOL, offsetof(struct Mod, isDirectory), true, LOT_NONE, 1, sizeof(bool) },
|
||||
{ "name", LVT_STRING_P, offsetof(struct Mod, name), true, LOT_NONE, 1, sizeof(char*) },
|
||||
{ "name", LVT_STRING, offsetof(struct Mod, name), true, LOT_NONE, 1, sizeof(char) },
|
||||
{ "pausable", LVT_BOOL, offsetof(struct Mod, pausable), true, LOT_NONE, 1, sizeof(bool) },
|
||||
{ "relativePath", LVT_STRING, offsetof(struct Mod, relativePath), true, LOT_NONE, 1, sizeof(char) },
|
||||
{ "renderBehindHud", LVT_BOOL, offsetof(struct Mod, renderBehindHud), true, LOT_NONE, 1, sizeof(bool) },
|
||||
|
|
@ -2734,7 +2724,6 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN]
|
|||
{ LOT_GRAPHNODESWITCHCASE, sGraphNodeSwitchCaseFields, LUA_GRAPH_NODE_SWITCH_CASE_FIELD_COUNT },
|
||||
{ LOT_GRAPHNODETRANSLATION, sGraphNodeTranslationFields, LUA_GRAPH_NODE_TRANSLATION_FIELD_COUNT },
|
||||
{ LOT_GRAPHNODETRANSLATIONROTATION, sGraphNodeTranslationRotationFields, LUA_GRAPH_NODE_TRANSLATION_ROTATION_FIELD_COUNT },
|
||||
{ LOT_HUDUTILSROTATION, sHudUtilsRotationFields, LUA_HUD_UTILS_ROTATION_FIELD_COUNT },
|
||||
{ LOT_INSTANTWARP, sInstantWarpFields, LUA_INSTANT_WARP_FIELD_COUNT },
|
||||
{ LOT_LAKITUSTATE, sLakituStateFields, LUA_LAKITU_STATE_FIELD_COUNT },
|
||||
{ LOT_LEVELVALUES, sLevelValuesFields, LUA_LEVEL_VALUES_FIELD_COUNT },
|
||||
|
|
@ -2840,7 +2829,6 @@ const char *sLuaLotNames[] = {
|
|||
[LOT_GRAPHNODESWITCHCASE] = "GraphNodeSwitchCase",
|
||||
[LOT_GRAPHNODETRANSLATION] = "GraphNodeTranslation",
|
||||
[LOT_GRAPHNODETRANSLATIONROTATION] = "GraphNodeTranslationRotation",
|
||||
[LOT_HUDUTILSROTATION] = "HudUtilsRotation",
|
||||
[LOT_INSTANTWARP] = "InstantWarp",
|
||||
[LOT_LAKITUSTATE] = "LakituState",
|
||||
[LOT_LEVELVALUES] = "LevelValues",
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ enum LuaObjectAutogenType {
|
|||
LOT_GRAPHNODESWITCHCASE,
|
||||
LOT_GRAPHNODETRANSLATION,
|
||||
LOT_GRAPHNODETRANSLATIONROTATION,
|
||||
LOT_HUDUTILSROTATION,
|
||||
LOT_INSTANTWARP,
|
||||
LOT_LAKITUSTATE,
|
||||
LOT_LEVELVALUES,
|
||||
|
|
|
|||
|
|
@ -1488,12 +1488,25 @@ char gSmluaConstants[] = ""
|
|||
"CONSOLE_MESSAGE_INFO=0\n"
|
||||
"CONSOLE_MESSAGE_WARNING=1\n"
|
||||
"CONSOLE_MESSAGE_ERROR=2\n"
|
||||
"ROTATION_PIVOT_X_LEFT=0.0\n"
|
||||
"ROTATION_PIVOT_X_CENTER=0.5\n"
|
||||
"ROTATION_PIVOT_X_RIGHT=1.0\n"
|
||||
"ROTATION_PIVOT_Y_TOP=0.0\n"
|
||||
"ROTATION_PIVOT_Y_CENTER=0.5\n"
|
||||
"ROTATION_PIVOT_Y_BOTTOM=1.0\n"
|
||||
"TEXT_HALIGN_LEFT=0.0\n"
|
||||
"TEXT_HALIGN_CENTER=0.5\n"
|
||||
"TEXT_HALIGN_RIGHT=1.0\n"
|
||||
"TEXT_VALIGN_TOP=0.0\n"
|
||||
"TEXT_VALIGN_CENTER=0.5\n"
|
||||
"TEXT_VALIGN_BOTTOM=1.0\n"
|
||||
"RESOLUTION_DJUI=0\n"
|
||||
"RESOLUTION_N64=1\n"
|
||||
"RESOLUTION_COUNT=2\n"
|
||||
"FILTER_NEAREST=0\n"
|
||||
"FILTER_LINEAR=1\n"
|
||||
"FILTER_COUNT=2\n"
|
||||
"FONT_LEGACY=-1\n"
|
||||
"FONT_NORMAL=0\n"
|
||||
"FONT_MENU=1\n"
|
||||
"FONT_HUD=2\n"
|
||||
|
|
|
|||
|
|
@ -945,7 +945,7 @@ int smlua_func_get_uncolored_string(lua_State* L) {
|
|||
const char *str = smlua_to_string(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("get_uncolored_string: Failed to convert parameter 1"); return 0; }
|
||||
|
||||
char *strNoColor = str_remove_color_codes(str);
|
||||
char *strNoColor = djui_text_get_uncolored_string(NULL, strlen(str) + 1, str);
|
||||
lua_pushstring(L, strNoColor);
|
||||
free(strNoColor);
|
||||
|
||||
|
|
|
|||
|
|
@ -12318,7 +12318,7 @@ int smlua_func_djui_hud_reset_color(UNUSED lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_djui_hud_get_rotation(UNUSED lua_State* L) {
|
||||
int smlua_func_djui_hud_get_rotation(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
|
|
@ -12328,9 +12328,17 @@ int smlua_func_djui_hud_get_rotation(UNUSED lua_State* L) {
|
|||
}
|
||||
|
||||
|
||||
smlua_push_object(L, LOT_HUDUTILSROTATION, djui_hud_get_rotation(), NULL);
|
||||
s16 rotation;
|
||||
f32 pivotX;
|
||||
f32 pivotY;
|
||||
|
||||
return 1;
|
||||
djui_hud_get_rotation(&rotation, &pivotX, &pivotY);
|
||||
|
||||
lua_pushinteger(L, rotation);
|
||||
lua_pushnumber(L, pivotX);
|
||||
lua_pushnumber(L, pivotY);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int smlua_func_djui_hud_set_rotation(lua_State* L) {
|
||||
|
|
@ -12363,13 +12371,13 @@ int smlua_func_djui_hud_set_rotation_interpolated(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
s32 prevRotation = smlua_to_integer(L, 1);
|
||||
s16 prevRotation = smlua_to_integer(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_rotation_interpolated"); return 0; }
|
||||
f32 prevPivotX = smlua_to_number(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_rotation_interpolated"); return 0; }
|
||||
f32 prevPivotY = smlua_to_number(L, 3);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_set_rotation_interpolated"); return 0; }
|
||||
s32 rotation = smlua_to_integer(L, 4);
|
||||
s16 rotation = smlua_to_integer(L, 4);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_set_rotation_interpolated"); return 0; }
|
||||
f32 pivotX = smlua_to_number(L, 5);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "djui_hud_set_rotation_interpolated"); return 0; }
|
||||
|
|
@ -12381,6 +12389,69 @@ int smlua_func_djui_hud_set_rotation_interpolated(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_djui_hud_get_text_alignment(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_alignment", 0, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
f32 textHAlign;
|
||||
f32 textVAlign;
|
||||
|
||||
djui_hud_get_text_alignment(&textHAlign, &textVAlign);
|
||||
|
||||
lua_pushnumber(L, textHAlign);
|
||||
lua_pushnumber(L, textVAlign);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int smlua_func_djui_hud_set_text_alignment(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 2) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_hud_set_text_alignment", 2, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
f32 textHAlign = smlua_to_number(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_text_alignment"); return 0; }
|
||||
f32 textVAlign = smlua_to_number(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_text_alignment"); return 0; }
|
||||
|
||||
djui_hud_set_text_alignment(textHAlign, textVAlign);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_djui_hud_set_text_alignment_interpolated(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_alignment_interpolated", 4, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
f32 prevTextHAlign = smlua_to_number(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_hud_set_text_alignment_interpolated"); return 0; }
|
||||
f32 prevTextVAlign = smlua_to_number(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_hud_set_text_alignment_interpolated"); return 0; }
|
||||
f32 textHAlign = smlua_to_number(L, 3);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "djui_hud_set_text_alignment_interpolated"); return 0; }
|
||||
f32 textVAlign = smlua_to_number(L, 4);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "djui_hud_set_text_alignment_interpolated"); return 0; }
|
||||
|
||||
djui_hud_set_text_alignment_interpolated(prevTextHAlign, prevTextVAlign, textHAlign, textVAlign);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_djui_hud_get_screen_width(UNUSED lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -37389,6 +37460,9 @@ void smlua_bind_functions_autogen(void) {
|
|||
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);
|
||||
smlua_bind_function(L, "djui_hud_get_text_alignment", smlua_func_djui_hud_get_text_alignment);
|
||||
smlua_bind_function(L, "djui_hud_set_text_alignment", smlua_func_djui_hud_set_text_alignment);
|
||||
smlua_bind_function(L, "djui_hud_set_text_alignment_interpolated", smlua_func_djui_hud_set_text_alignment_interpolated);
|
||||
smlua_bind_function(L, "djui_hud_get_screen_width", smlua_func_djui_hud_get_screen_width);
|
||||
smlua_bind_function(L, "djui_hud_get_screen_height", smlua_func_djui_hud_get_screen_height);
|
||||
smlua_bind_function(L, "djui_hud_get_mouse_x", smlua_func_djui_hud_get_mouse_x);
|
||||
|
|
|
|||
|
|
@ -952,7 +952,7 @@ char** smlua_get_chat_subcommands_list(const char* maincommand) {
|
|||
for (s32 i = 0; i < sHookedChatCommandsCount; i++) {
|
||||
struct LuaHookedChatCommand* hook = &sHookedChatCommands[i];
|
||||
if (strcmp(hook->command, maincommand) == 0) {
|
||||
char* noColorsDesc = str_remove_color_codes(hook->description);
|
||||
char* noColorsDesc = djui_text_get_uncolored_string(NULL, strlen(hook->description) + 1, hook->description);
|
||||
char* startSubcommands = strstr(noColorsDesc, "[");
|
||||
char* endSubcommands = strstr(noColorsDesc, "]");
|
||||
|
||||
|
|
|
|||
|
|
@ -197,11 +197,6 @@ void mod_clear(struct Mod* mod) {
|
|||
}
|
||||
}
|
||||
|
||||
if (mod->name != NULL) {
|
||||
free(mod->name);
|
||||
mod->name = NULL;
|
||||
}
|
||||
|
||||
if (mod->incompatible != NULL) {
|
||||
free(mod->incompatible);
|
||||
mod->incompatible = NULL;
|
||||
|
|
@ -449,7 +444,7 @@ static void mod_extract_fields(struct Mod* mod) {
|
|||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
// default to null
|
||||
mod->name = NULL;
|
||||
mod->name[0] = 0;
|
||||
mod->incompatible = NULL;
|
||||
mod->category = NULL;
|
||||
mod->description = NULL;
|
||||
|
|
@ -457,7 +452,7 @@ static void mod_extract_fields(struct Mod* mod) {
|
|||
mod->ignoreScriptWarnings = false;
|
||||
|
||||
// read line-by-line
|
||||
#define BUFFER_SIZE MAX(MAX(MOD_NAME_MAX_LENGTH, MOD_INCOMPATIBLE_MAX_LENGTH), MOD_DESCRIPTION_MAX_LENGTH)
|
||||
#define BUFFER_SIZE MAX(MAX(MOD_NAME_SIZE, MOD_INCOMPATIBLE_SIZE), MOD_DESCRIPTION_SIZE)
|
||||
char buffer[BUFFER_SIZE] = { 0 };
|
||||
while (!feof(f)) {
|
||||
file_get_line(buffer, BUFFER_SIZE, f);
|
||||
|
|
@ -470,24 +465,23 @@ static void mod_extract_fields(struct Mod* mod) {
|
|||
|
||||
// extract the field
|
||||
char* extracted = NULL;
|
||||
if (mod->name == NULL && (extracted = extract_lua_field("-- name:", buffer))) {
|
||||
mod->name = calloc(MOD_NAME_MAX_LENGTH + 1, sizeof(char));
|
||||
if (snprintf(mod->name, MOD_NAME_MAX_LENGTH, "%s", extracted) < 0) {
|
||||
if (!mod->name[0] && (extracted = extract_lua_field("-- name:", buffer))) {
|
||||
if (snprintf(mod->name, MOD_NAME_SIZE, "%s", extracted) < 0) {
|
||||
LOG_INFO("Truncated mod name field '%s'", mod->name);
|
||||
}
|
||||
} else if (mod->incompatible == NULL && (extracted = extract_lua_field("-- incompatible:", buffer))) {
|
||||
mod->incompatible = calloc(MOD_INCOMPATIBLE_MAX_LENGTH + 1, sizeof(char));
|
||||
if (snprintf(mod->incompatible, MOD_INCOMPATIBLE_MAX_LENGTH, "%s", extracted) < 0) {
|
||||
mod->incompatible = calloc(MOD_INCOMPATIBLE_SIZE, sizeof(char));
|
||||
if (snprintf(mod->incompatible, MOD_INCOMPATIBLE_SIZE, "%s", extracted) < 0) {
|
||||
LOG_INFO("Truncated mod incompatible field '%s'", mod->incompatible);
|
||||
}
|
||||
} else if (mod->category == NULL && (extracted = extract_lua_field("-- category:", buffer))) {
|
||||
mod->category = calloc(MOD_CATEGORY_MAX_LENGTH + 1, sizeof(char));
|
||||
if (snprintf(mod->category, MOD_CATEGORY_MAX_LENGTH, "%s", extracted) < 0) {
|
||||
mod->category = calloc(MOD_CATEGORY_SIZE, sizeof(char));
|
||||
if (snprintf(mod->category, MOD_CATEGORY_SIZE, "%s", extracted) < 0) {
|
||||
LOG_INFO("Truncated mod category field '%s'", mod->category);
|
||||
}
|
||||
} else if (mod->description == NULL && (extracted = extract_lua_field("-- description:", buffer))) {
|
||||
mod->description = calloc(MOD_DESCRIPTION_MAX_LENGTH + 1, sizeof(char));
|
||||
if (snprintf(mod->description, MOD_DESCRIPTION_MAX_LENGTH, "%s", extracted) < 0) {
|
||||
mod->description = calloc(MOD_DESCRIPTION_SIZE, sizeof(char));
|
||||
if (snprintf(mod->description, MOD_DESCRIPTION_SIZE, "%s", extracted) < 0) {
|
||||
LOG_INFO("Truncated mod description field '%s'", mod->description);
|
||||
}
|
||||
} else if ((extracted = extract_lua_field("-- pausable:", buffer))) {
|
||||
|
|
@ -632,17 +626,19 @@ bool mod_load(struct Mods* mods, char* basePath, char* modName) {
|
|||
mod_extract_fields(mod);
|
||||
|
||||
// set name
|
||||
if (mod->name == NULL) {
|
||||
mod->name = strdup(modName);
|
||||
if (!mod->name[0]) {
|
||||
if (snprintf(mod->name, MOD_NAME_SIZE, "%s", modName) < 0) {
|
||||
LOG_INFO("Truncated mod name field '%s'", mod->name);
|
||||
}
|
||||
}
|
||||
|
||||
// set category
|
||||
if (mod->category == NULL) {
|
||||
char *modNameNoColor = str_remove_color_codes(mod->name);
|
||||
char modNameNoColor[MOD_NAME_SIZE];
|
||||
djui_text_get_uncolored_string(modNameNoColor, MOD_NAME_SIZE, mod->name);
|
||||
if (strstr(modNameNoColor, "[CS]") == modNameNoColor) {
|
||||
mod->category = strdup("cs");
|
||||
}
|
||||
free(modNameNoColor);
|
||||
}
|
||||
|
||||
// print
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@
|
|||
#define MOD_CATEGORY_MAX_LENGTH 64
|
||||
#define MOD_DESCRIPTION_MAX_LENGTH 800
|
||||
|
||||
#define MOD_NAME_SIZE (MOD_NAME_MAX_LENGTH + 1)
|
||||
#define MOD_INCOMPATIBLE_SIZE (MOD_INCOMPATIBLE_MAX_LENGTH + 1)
|
||||
#define MOD_CATEGORY_SIZE (MOD_CATEGORY_MAX_LENGTH + 1)
|
||||
#define MOD_DESCRIPTION_SIZE (MOD_DESCRIPTION_MAX_LENGTH + 1)
|
||||
|
||||
struct Mods;
|
||||
|
||||
struct ModFile {
|
||||
|
|
@ -25,7 +30,7 @@ struct ModFile {
|
|||
};
|
||||
|
||||
struct Mod {
|
||||
char* name;
|
||||
char name[MOD_NAME_SIZE];
|
||||
char* incompatible;
|
||||
char* category;
|
||||
char* description;
|
||||
|
|
|
|||
|
|
@ -184,19 +184,20 @@ static void mods_sort(struct Mods* mods) {
|
|||
}
|
||||
|
||||
// By default, this is the alphabetical order on name
|
||||
char modNameNoColor_i[MOD_NAME_SIZE];
|
||||
char modNameNoColor_j[MOD_NAME_SIZE];
|
||||
for (s32 i = 1; i < mods->entryCount; ++i) {
|
||||
struct Mod* mod = mods->entries[i];
|
||||
struct Mod* mod_i = mods->entries[i];
|
||||
djui_text_get_uncolored_string(modNameNoColor_i, MOD_NAME_SIZE, mod_i->name);
|
||||
for (s32 j = 0; j < i; ++j) {
|
||||
struct Mod* mod2 = mods->entries[j];
|
||||
char* name = str_remove_color_codes(mod->name);
|
||||
char* name2 = str_remove_color_codes(mod2->name);
|
||||
if (strcmp(name, name2) < 0) {
|
||||
mods->entries[i] = mod2;
|
||||
mods->entries[j] = mod;
|
||||
mod = mods->entries[i];
|
||||
struct Mod* mod_j = mods->entries[j];
|
||||
djui_text_get_uncolored_string(modNameNoColor_j, MOD_NAME_SIZE, mod_j->name);
|
||||
if (strcmp(modNameNoColor_i, modNameNoColor_j) < 0) {
|
||||
mods->entries[i] = mod_j;
|
||||
mods->entries[j] = mod_i;
|
||||
mod_i = mod_j;
|
||||
memcpy(modNameNoColor_i, modNameNoColor_j, MOD_NAME_SIZE * sizeof(char));
|
||||
}
|
||||
free(name);
|
||||
free(name2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -318,13 +318,13 @@ after_filled:;
|
|||
|
||||
// Cache any mod that doesn't have "(wip)" or "[wip]" in its name (case-insensitive)
|
||||
static bool should_cache_mod(struct Mod *mod) {
|
||||
char *modName = sys_strdup(mod->name);
|
||||
sys_strlwr(modName);
|
||||
char modNameLowercase[MOD_NAME_SIZE];
|
||||
memcpy(modNameLowercase, mod->name, MOD_NAME_SIZE * sizeof(char));
|
||||
sys_strlwr(modNameLowercase);
|
||||
bool shouldCache = (
|
||||
!strstr(modName, "(wip)") &&
|
||||
!strstr(modName, "[wip]")
|
||||
!strstr(modNameLowercase, "(wip)") &&
|
||||
!strstr(modNameLowercase, "[wip]")
|
||||
);
|
||||
free(modName);
|
||||
return shouldCache;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -197,9 +197,8 @@ void network_receive_mod_list_entry(struct Packet* p) {
|
|||
}
|
||||
|
||||
// get name
|
||||
char name[MOD_NAME_MAX_LENGTH + 1] = { 0 };
|
||||
packet_read(p, name, nameLength * sizeof(u8));
|
||||
mod->name = strdup(name);
|
||||
packet_read(p, mod->name, nameLength * sizeof(u8));
|
||||
mod->name[nameLength] = 0;
|
||||
|
||||
// get incompatible length
|
||||
u16 incompatibleLength = 0;
|
||||
|
|
@ -211,7 +210,7 @@ void network_receive_mod_list_entry(struct Packet* p) {
|
|||
|
||||
// get incompatible
|
||||
if (incompatibleLength > 0) {
|
||||
char incompatible[MOD_INCOMPATIBLE_MAX_LENGTH + 1] = { 0 };
|
||||
char incompatible[MOD_INCOMPATIBLE_SIZE] = { 0 };
|
||||
packet_read(p, incompatible, incompatibleLength * sizeof(u8));
|
||||
mod->incompatible = strdup(incompatible);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -594,18 +594,3 @@ void str_seperator_concat(char *output_buffer, int buffer_size, char** strings,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *str_remove_color_codes(const char *str) {
|
||||
char *output = strdup(str);
|
||||
char *startColor;
|
||||
while ((startColor = strstr(output, "\\#"))) {
|
||||
char *endColor = strchr(startColor + 2, '\\');
|
||||
if (endColor) {
|
||||
memmove(startColor, endColor + 1, strlen(endColor + 1) + 1);
|
||||
} else {
|
||||
*startColor = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,5 @@ void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta);
|
|||
void detect_and_skip_mtx_interpolation(Mtx** mtxPrev, Mtx** mtx);
|
||||
|
||||
void str_seperator_concat(char *output_buffer, int buffer_size, char** strings, int num_strings, char* seperator);
|
||||
char *str_remove_color_codes(const char *str);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 39 KiB |
Loading…
Add table
Reference in a new issue