From 1841b5a0cc28d8883e1a7765620aaf832a951d65 Mon Sep 17 00:00:00 2001 From: rr- Date: Sun, 14 Feb 2021 20:20:53 +0100 Subject: [PATCH] add UI scaling --- README.md | 2 + TR1Main.json | 1 + src/game/health.c | 2 +- src/game/text.c | 147 +++++++++++++++++++++++++++++----------------- src/main.c | 2 + src/mod.c | 52 ++++++++++++++-- src/mod.h | 8 ++- 7 files changed, 153 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index e8bef37b6..9c64911d4 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ Currently the following configuration options are supported: - `enable_enemy_healthbar`: enables showing healthbar for the active enemy. - `enable_enhanced_look`: allows the player to look while running, jumping etc. (similar to TR2 style). +- `enable_enhanced_ui`: enables UI scaling of in-game inventory text and ammo + text (useful for 4k screens). - `enable_numeric_keys`: enables quick weapon draws and medpack usage. - 1: draw pistols - 2: draw shotgun diff --git a/TR1Main.json b/TR1Main.json index 3bc39727e..3917829ec 100644 --- a/TR1Main.json +++ b/TR1Main.json @@ -7,6 +7,7 @@ "enable_red_healthbar": true, "enable_enemy_healthbar": true, "enable_enhanced_look": true, + "enable_enhanced_ui": true, "enable_numeric_keys": true, "fix_end_of_level_freeze": true, "fix_tihocan_secret_sound": true diff --git a/src/game/health.c b/src/game/health.c index 54a34d3fa..fc2bd45b4 100644 --- a/src/game/health.c +++ b/src/game/health.c @@ -141,7 +141,7 @@ void __cdecl DrawPickups() pu->duration = 0; } else { S_DrawUISprite( - x, y, TR1MGetOverlayScale(12288), pu->sprnum, 4096); + x, y, TR1MGetRenderScale(12288), pu->sprnum, 4096); x -= sprite_width; } } diff --git a/src/game/text.c b/src/game/text.c index 31668dcb6..bff778c24 100644 --- a/src/game/text.c +++ b/src/game/text.c @@ -6,6 +6,8 @@ #include "util.h" #include +#define TEXT_BOX_OFFSET 2 + static int8_t TextSpacing[110] = { 14 /*A*/, 11 /*B*/, 11 /*C*/, 11 /*D*/, 11 /*E*/, 11 /*F*/, 11 /*G*/, 13 /*H*/, 8 /*I*/, 11 /*J*/, 12 /*K*/, 11 /*L*/, 13 /*M*/, 13 /*N*/, @@ -224,11 +226,7 @@ int32_t __cdecl T_GetTextWidth(TEXTSTRING* textstring) } if (letter == ' ') { - if (textstring->scale_h == PHD_ONE) { - width += textstring->word_spacing; - } else { - width += (textstring->word_spacing * textstring->scale_h) >> 16; - } + width += textstring->word_spacing * textstring->scale_h / PHD_ONE; continue; } @@ -240,14 +238,9 @@ int32_t __cdecl T_GetTextWidth(TEXTSTRING* textstring) letter = letter + 81; } - if (textstring->scale_h == PHD_ONE) { - width += textstring->letter_spacing + TextSpacing[letter]; - } else { - width += - (((int32_t)textstring->letter_spacing + TextSpacing[letter]) - * textstring->scale_h) - >> 16; - } + width += ((TextSpacing[letter] + textstring->letter_spacing) + * textstring->scale_h) + / PHD_ONE; } width -= textstring->letter_spacing; width &= 0xFFFE; @@ -288,7 +281,8 @@ void __cdecl T_DrawText() } else { int fps_x; int fps_y; - if (TR1MGetOverlayScale(1) > 1) { + if (!TR1MConfig.enable_enhanced_ui + && TR1MGetRenderScaleGLRage(1) > 1) { fps_x = TR1MData.fps_x; fps_y = TR1MData.fps_y; } else { @@ -325,6 +319,7 @@ void __cdecl T_DrawText() void __cdecl T_DrawThisText(TEXTSTRING* textstring) { + int sx, sy, sh, sv; if (textstring->flags & TF_FLASH) { textstring->flash_count -= (int16_t)Camera.number_frames; if (textstring->flash_count <= -textstring->flash_rate) { @@ -340,20 +335,35 @@ void __cdecl T_DrawThisText(TEXTSTRING* textstring) int zpos = textstring->zpos; int textwidth = T_GetTextWidth(textstring); - if (textstring->flags & TF_CENTRE_H) { - xpos += (DumpWidth - textwidth) / 2; - } else if (textstring->flags & TF_RIGHT) { - xpos += DumpWidth - textwidth; - } + if (TR1MConfig.enable_enhanced_ui) { + if (textstring->flags & TF_CENTRE_H) { + xpos += (TR1MGetRenderWidthDownscaled() - textwidth) / 2; + } else if (textstring->flags & TF_RIGHT) { + xpos += TR1MGetRenderWidthDownscaled() - textwidth; + } + + if (textstring->flags & TF_CENTRE_V) { + ypos += TR1MGetRenderHeightDownscaled() / 2; + } else if (textstring->flags & TF_BOTTOM) { + ypos += TR1MGetRenderHeightDownscaled(); + } + } else { + if (textstring->flags & TF_CENTRE_H) { + xpos += (DumpWidth - textwidth) / 2; + } else if (textstring->flags & TF_RIGHT) { + xpos += DumpWidth - textwidth; + } - if (textstring->flags & TF_CENTRE_V) { - ypos += DumpHeight / 2; - } else if (textstring->flags & TF_BOTTOM) { - ypos += DumpHeight; + if (textstring->flags & TF_CENTRE_V) { + ypos += DumpHeight / 2; + } else if (textstring->flags & TF_BOTTOM) { + ypos += DumpHeight; + } } - int bxpos = textstring->bgnd_off_x + xpos - 2; - int bypos = textstring->bgnd_off_y + ypos - 4 - TEXT_HEIGHT; + int bxpos = textstring->bgnd_off_x + xpos - TEXT_BOX_OFFSET; + int bypos = + textstring->bgnd_off_y + ypos - TEXT_BOX_OFFSET * 2 - TEXT_HEIGHT; int letter = '\0'; while (*string) { @@ -363,7 +373,7 @@ void __cdecl T_DrawThisText(TEXTSTRING* textstring) } if (letter == ' ') { - xpos += (textstring->word_spacing * textstring->scale_h) >> 16; + xpos += (textstring->word_spacing * textstring->scale_h) / PHD_ONE; continue; } @@ -376,22 +386,27 @@ void __cdecl T_DrawThisText(TEXTSTRING* textstring) sprite = letter + 81; } + sx = xpos; + sy = ypos; + sh = textstring->scale_h; + sv = textstring->scale_v; + if (TR1MConfig.enable_enhanced_ui) { + sx = TR1MGetRenderScale(sx); + sy = TR1MGetRenderScale(sy); + sh = TR1MGetRenderScale(sh); + sv = TR1MGetRenderScale(sv); + } S_DrawScreenSprite2d( - xpos, ypos, zpos, textstring->scale_h, textstring->scale_v, - Objects[O_ALPHABET].mesh_index + sprite, 16 << 8, - textstring->text_flags, 0); + sx, sy, zpos, sh, sv, Objects[O_ALPHABET].mesh_index + sprite, + 16 << 8, textstring->text_flags, 0); if (letter == '(' || letter == ')' || letter == '$' || letter == '~') { continue; } - if (textstring->scale_h == PHD_ONE) { - xpos += textstring->letter_spacing + TextSpacing[sprite]; - } else { - xpos += (((int32_t)textstring->letter_spacing + TextSpacing[sprite]) - * textstring->scale_h) - >> 16; - } + xpos += (((int32_t)textstring->letter_spacing + TextSpacing[sprite]) + * textstring->scale_h) + / PHD_ONE; } int bwidth = 0; @@ -400,9 +415,9 @@ void __cdecl T_DrawThisText(TEXTSTRING* textstring) if (textstring->bgnd_size_x) { bxpos += textwidth / 2; bxpos -= textstring->bgnd_size_x / 2; - bwidth = textstring->bgnd_size_x + 4; + bwidth = textstring->bgnd_size_x + TEXT_BOX_OFFSET * 2; } else { - bwidth = textwidth + 4; + bwidth = textwidth + TEXT_BOX_OFFSET * 2; } if (textstring->bgnd_size_y) { bheight = textstring->bgnd_size_y; @@ -411,41 +426,65 @@ void __cdecl T_DrawThisText(TEXTSTRING* textstring) } } + sx = bxpos; + sy = bypos; + sh = bwidth; + sv = bheight; + if (TR1MConfig.enable_enhanced_ui) { + sx = TR1MGetRenderScale(sx); + sy = TR1MGetRenderScale(sy); + sh = TR1MGetRenderScale(sh); + sv = TR1MGetRenderScale(sv); + } + if (textstring->flags & TF_BGND) { if (textstring->bgnd_gour) { - int bhw = bwidth / 2; - int bhh = bheight / 2; - int bhw2 = bwidth - bhw; - int bhh2 = bheight - bhh; + int bhw = sh / 2; + int bhh = sv / 2; + int bhw2 = sh - bhw; + int bhh2 = sv - bhh; + S_DrawScreenFBox( - bxpos, bypos, zpos + textstring->bgnd_off_z + 8, bhw, bhh, + sx, sy, zpos + textstring->bgnd_off_z + 8, bhw, bhh, textstring->bgnd_colour, textstring->bgnd_gour, textstring->bgnd_flags); + S_DrawScreenFBox( - bxpos + bhw, bypos, zpos + textstring->bgnd_off_z + 8, bhw2, - bhh, textstring->bgnd_colour, textstring->bgnd_gour + 4, + sx + bhw, sy, zpos + textstring->bgnd_off_z + 8, bhw2, bhh, + textstring->bgnd_colour, textstring->bgnd_gour + 4, textstring->bgnd_flags); + S_DrawScreenFBox( - bxpos + bhw, bypos + bhh, zpos + textstring->bgnd_off_z + 8, - bhw, bhh2, textstring->bgnd_colour, textstring->bgnd_gour + 8, + sx + bhw, sy + bhh, zpos + textstring->bgnd_off_z + 8, bhw, + bhh2, textstring->bgnd_colour, textstring->bgnd_gour + 8, textstring->bgnd_flags); + S_DrawScreenFBox( - bxpos, bypos + bhh, zpos + textstring->bgnd_off_z + 8, bhw2, - bhh2, textstring->bgnd_colour, textstring->bgnd_gour + 12, + sx, sy + bhh, zpos + textstring->bgnd_off_z + 8, bhw2, bhh2, + textstring->bgnd_colour, textstring->bgnd_gour + 12, textstring->bgnd_flags); } else { S_DrawScreenFBox( - bxpos, bypos, zpos + textstring->bgnd_off_z + 8, bwidth, - bheight, textstring->bgnd_colour, 0, textstring->bgnd_flags); + sx, sy, zpos + textstring->bgnd_off_z + 8, sh, sv, + textstring->bgnd_colour, 0, textstring->bgnd_flags); S_DrawScreenBox( - bxpos, bypos, textstring->bgnd_off_z + zpos, bwidth, bheight, 0, - 0, 0); + sx, sy, textstring->bgnd_off_z + zpos, sh, sv, 0, 0, 0); } } if (textstring->flags & TF_OUTLINE) { + sx = bxpos; + sy = bypos; + sh = bwidth; + sv = bheight; + if (TR1MConfig.enable_enhanced_ui) { + sx = TR1MGetRenderScale(sx); + sy = TR1MGetRenderScale(sy); + sh = TR1MGetRenderScale(sh); + sv = TR1MGetRenderScale(sv); + } S_DrawScreenBox( - bxpos, bypos, zpos + textstring->bgnd_off_z, bwidth, bheight, + sx, sy, zpos + textstring->bgnd_off_z, sh, sv, textstring->outl_colour, textstring->outl_gour, textstring->outl_flags); } diff --git a/src/main.c b/src/main.c index bcb3e5789..c517258c1 100644 --- a/src/main.c +++ b/src/main.c @@ -74,6 +74,8 @@ static int TR1MReadConfig() tr1m_json_get_boolean_value(json, "enable_enemy_healthbar"); TR1MConfig.enable_enhanced_look = tr1m_json_get_boolean_value(json, "enable_enhanced_look"); + TR1MConfig.enable_enhanced_ui = + tr1m_json_get_boolean_value(json, "enable_enhanced_ui"); TR1MConfig.enable_numeric_keys = tr1m_json_get_boolean_value(json, "enable_numeric_keys"); TR1MConfig.fix_end_of_level_freeze = diff --git a/src/mod.c b/src/mod.c index f7d4ba2af..746bcaf4d 100644 --- a/src/mod.c +++ b/src/mod.c @@ -3,15 +3,57 @@ #include "mod.h" #include -int TR1MGetOverlayScale(int base) +int MulDiv(int x, int y, int z) { + return (x * y) / z; +} + +int TR1MGetRenderHeightDownscaled() +{ + return PhdWinHeight * PHD_ONE / TR1MGetRenderScale(PHD_ONE); +} + +int TR1MGetRenderWidthDownscaled() +{ + return PhdWinWidth * PHD_ONE / TR1MGetRenderScale(PHD_ONE); +} + +int TR1MGetRenderHeight() +{ + return PhdWinHeight; +} + +int TR1MGetRenderWidth() +{ + return PhdWinWidth; +} + +int TR1MGetRenderScale(int unit) +{ + // TR2Main-style UI scaler + int baseWidth = 800; + int baseHeight = 600; + int scaleX = + (PhdWinWidth > baseWidth) ? MulDiv(PhdWinWidth, unit, baseWidth) : unit; + int scaleY = (PhdWinHeight > baseHeight) + ? MulDiv(PhdWinHeight, unit, baseHeight) + : unit; + if (scaleX < scaleY) { + return scaleX; + } + return scaleY; +} + +int TR1MGetRenderScaleGLRage(int unit) +{ + // GLRage-style UI scaler double result = PhdWinWidth; - result *= base; + result *= unit; result /= 800.0; // only scale up, not down - if (result < base) { - result = base; + if (result < unit) { + result = unit; } return round(result); @@ -50,7 +92,7 @@ void TR1MRenderBar(int value, int value_max, int bar_type) const int color_border_2 = 17; const int color_bgnd = 0; - int scale = TR1MGetOverlayScale(1.0); + int scale = TR1MGetRenderScaleGLRage(1); int width = percent_max * scale; int height = 5 * scale; diff --git a/src/mod.h b/src/mod.h index 593de6cf5..22e1f74f9 100644 --- a/src/mod.h +++ b/src/mod.h @@ -19,6 +19,7 @@ struct { int enable_red_healthbar; int enable_enemy_healthbar; int enable_enhanced_look; + int enable_enhanced_ui; int enable_numeric_keys; int fix_end_of_level_freeze; int fix_tihocan_secret_sound; @@ -32,7 +33,12 @@ struct { int fps_y; } TR1MData; -int TR1MGetOverlayScale(int base); +int TR1MGetRenderScale(int base); +int TR1MGetRenderScaleGLRage(int unit); void TR1MRenderBar(int value, int value_max, int bar_type); +int TR1MGetRenderHeightDownscaled(); +int TR1MGetRenderWidthDownscaled(); +int TR1MGetRenderHeight(); +int TR1MGetRenderWidth(); #endif