diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 9496f6a97..50a4c644e 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -807,6 +807,7 @@ set (PCH_SOURCES core/palette.cpp core/zcompile.cpp core/statusbar.cpp + core/statusbar2.cpp core/gi.cpp core/console/c_notifybuffer.cpp diff --git a/source/blood/src/sbar.cpp b/source/blood/src/sbar.cpp index 721c00b4c..f872634ce 100644 --- a/source/blood/src/sbar.cpp +++ b/source/blood/src/sbar.cpp @@ -108,7 +108,7 @@ struct POWERUPDISPLAY -class DBloodStatusBar : public DBaseStatusBar +class DBloodStatusBar : public DStatusBarCore { enum NewRSFlags { @@ -241,7 +241,7 @@ private: stats.spacing = 6; } if (hud_size <= Hud_StbarOverlay) stats.screenbottomspace = 56; - DBaseStatusBar::PrintAutomapInfo(stats, textfont); + DStatusBarCore::PrintAutomapInfo(stats, textfont); } if (automapMode == am_off && hud_stats) { @@ -253,7 +253,7 @@ private: stats.secrets = gSecretMgr.Founds + gSecretMgr.Super; stats.maxsecrets = gSecretMgr.Total; - DBaseStatusBar::PrintLevelStats(stats); + DStatusBarCore::PrintLevelStats(stats); } } diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index ef7d7a427..f8885ea29 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -1203,146 +1203,16 @@ void GameInterface::FreeLevelData() currentLevel = nullptr; } -//--------------------------------------------------------------------------- -// -// Load crosshair definitions -// -//--------------------------------------------------------------------------- - -FGameTexture* CrosshairImage; -int CrosshairNum; - -CVAR(Int, crosshair, 0, CVAR_ARCHIVE) -CVAR(Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE); -CVAR(Int, crosshairhealth, 2, CVAR_ARCHIVE); - -void ST_LoadCrosshair(int num, bool alwaysload) -{ - char name[16]; - - if (!alwaysload && CrosshairNum == num && CrosshairImage != NULL) - { // No change. - return; - } - - if (num == 0) - { - CrosshairNum = 0; - CrosshairImage = NULL; - return; - } - if (num < 0) - { - num = -num; - } - - mysnprintf(name, countof(name), "XHAIRB%d", num); - FTextureID texid = TexMan.CheckForTexture(name, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ShortNameOnly); - if (!texid.isValid()) - { - mysnprintf(name, countof(name), "XHAIRB1"); - texid = TexMan.CheckForTexture(name, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ShortNameOnly); - if (!texid.isValid()) - { - texid = TexMan.CheckForTexture("XHAIRS1", ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ShortNameOnly); - } - } - CrosshairNum = num; - CrosshairImage = TexMan.GetGameTexture(texid); -} - //--------------------------------------------------------------------------- // // DrawCrosshair // //--------------------------------------------------------------------------- -void DrawGenericCrosshair(int num, int phealth, double xdelta) -{ - uint32_t color; - double size; - int w, h; - - ST_LoadCrosshair(num, false); - - // Don't draw the crosshair if there is none - if (CrosshairImage == NULL) - { - return; - } - - float crosshairscale = cl_crosshairscale * 0.005; - if (crosshairscale > 0.0f) - { - size = twod->GetHeight() * crosshairscale / 200.; - } - else - { - size = 1.; - } - - w = int(CrosshairImage->GetDisplayWidth() * size); - h = int(CrosshairImage->GetDisplayHeight() * size); - - if (crosshairhealth == 1) - { - // "Standard" crosshair health (green-red) - int health = phealth; - - if (health >= 85) - { - color = 0x00ff00; - } - else - { - int red, green; - health -= 25; - if (health < 0) - { - health = 0; - } - if (health < 30) - { - red = 255; - green = health * 255 / 30; - } - else - { - red = (60 - health) * 255 / 30; - green = 255; - } - color = (red << 16) | (green << 8); - } - } - else if (crosshairhealth == 2) - { - // "Enhanced" crosshair health (blue-green-yellow-red) - int health = clamp(phealth, 0, 200); - float rr, gg, bb; - - float saturation = health < 150 ? 1.f : 1.f - (health - 150) / 100.f; - - HSVtoRGB(&rr, &gg, &bb, health * 1.2f, saturation, 1); - int red = int(rr * 255); - int green = int(gg * 255); - int blue = int(bb * 255); - - color = (red << 16) | (green << 8) | blue; - } - else - { - color = crosshaircolor; - } - - DrawTexture(twod, CrosshairImage, - (windowxy1.x + windowxy2.x) / 2 + xdelta * (windowxy2.y - windowxy1.y) / 240., - (windowxy1.y + windowxy2.y) / 2, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_AlphaChannel, true, - DTA_FillColor, color & 0xFFFFFF, - TAG_DONE); -} +void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale); +//void DrawGenericCrosshair(int num, int phealth, double xdelta); +void ST_LoadCrosshair(int num, bool alwaysload); +CVAR(Int, crosshair, 0, CVAR_ARCHIVE) void DrawCrosshair(int deftile, int health, double xdelta, double ydelta, double scale, PalEntry color) @@ -1363,7 +1233,12 @@ void DrawCrosshair(int deftile, int health, double xdelta, double ydelta, double return; } } - DrawGenericCrosshair(crosshair == 0 ? 2 : *crosshair, health, xdelta); + // 0 means 'game provided crosshair' - use type 2 as fallback. + ST_LoadCrosshair(crosshair == 0 ? 2 : *crosshair, false); + + double xpos = (windowxy1.x + windowxy2.x) / 2 + xdelta * (windowxy2.y - windowxy1.y) / 240.; + double ypos = (windowxy1.y + windowxy2.y) / 2; + ST_DrawCrosshair(health, xpos, ypos, 1); } } //--------------------------------------------------------------------------- diff --git a/source/core/statusbar.cpp b/source/core/statusbar.cpp index fba769692..b9cd33eaa 100644 --- a/source/core/statusbar.cpp +++ b/source/core/statusbar.cpp @@ -77,46 +77,195 @@ EXTERN_CVAR (Bool, am_showtotaltime) EXTERN_CVAR (Bool, noisedebug) EXTERN_CVAR(Bool, vid_fps) EXTERN_CVAR(Bool, inter_subtitles) -CVAR(Bool, log_vgafont, false, CVAR_ARCHIVE) -DBaseStatusBar *StatusBar; +DStatusBarCore *StatusBar; extern int setblocks; CVAR (Bool, idmypos, false, 0); -//--------------------------------------------------------------------------- -// ST_Clear -// -//--------------------------------------------------------------------------- +FGameTexture* CrosshairImage; +static int CrosshairNum; -void ST_Clear() +CVAR(Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE); +CVAR(Int, crosshairhealth, 2, CVAR_ARCHIVE); +CVAR(Float, crosshairscale, 1.0, CVAR_ARCHIVE); +CVAR(Bool, crosshairgrow, false, CVAR_ARCHIVE); +EXTERN_CVAR(Bool, vid_fps) + +void ST_LoadCrosshair(int num, bool alwaysload) { - if (StatusBar != NULL) - { - delete StatusBar; - StatusBar = NULL; + char name[16]; + char size; + + if (!alwaysload && CrosshairNum == num && CrosshairImage != NULL) + { // No change. + return; } + + if (num == 0) + { + CrosshairNum = 0; + CrosshairImage = NULL; + return; + } + if (num < 0) + { + num = -num; + } + size = (twod->GetWidth() < 640) ? 'S' : 'B'; + + mysnprintf(name, countof(name), "XHAIR%c%d", size, num); + FTextureID texid = TexMan.CheckForTexture(name, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ShortNameOnly); + if (!texid.isValid()) + { + mysnprintf(name, countof(name), "XHAIR%c1", size); + texid = TexMan.CheckForTexture(name, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ShortNameOnly); + if (!texid.isValid()) + { + texid = TexMan.CheckForTexture("XHAIRS1", ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ShortNameOnly); + } + } + CrosshairNum = num; + CrosshairImage = TexMan.GetGameTexture(texid); } -//--------------------------------------------------------------------------- -// -// Constructor -// -//--------------------------------------------------------------------------- -DBaseStatusBar::DBaseStatusBar () +void ST_UnloadCrosshair() { - CompleteBorder = false; - Centering = false; - FixedOrigin = false; - CrosshairSize = 1.; - Displacement = 0; - ShowLog = false; - SetSize(0); + CrosshairImage = NULL; + CrosshairNum = 0; } -static void ValidateResolution(int &hres, int &vres) + +//--------------------------------------------------------------------------- +// +// DrawCrosshair +// +//--------------------------------------------------------------------------- + +void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale) +{ + uint32_t color; + double size; + int w, h; + + // Don't draw the crosshair if there is none + if (CrosshairImage == NULL) + { + return; + } + + if (crosshairscale > 0.0f) + { + size = twod->GetHeight() * crosshairscale * 0.005; + } + else + { + size = 1.; + } + + if (crosshairgrow) + { + size *= scale; + } + + w = int(CrosshairImage->GetDisplayWidth() * size); + h = int(CrosshairImage->GetDisplayHeight() * size); + + if (crosshairhealth == 1) + { + // "Standard" crosshair health (green-red) + int health = phealth; + + if (health >= 85) + { + color = 0x00ff00; + } + else + { + int red, green; + health -= 25; + if (health < 0) + { + health = 0; + } + if (health < 30) + { + red = 255; + green = health * 255 / 30; + } + else + { + red = (60 - health) * 255 / 30; + green = 255; + } + color = (red << 16) | (green << 8); + } + } + else if (crosshairhealth == 2) + { + // "Enhanced" crosshair health (blue-green-yellow-red) + int health = clamp(phealth, 0, 200); + float rr, gg, bb; + + float saturation = health < 150 ? 1.f : 1.f - (health - 150) / 100.f; + + HSVtoRGB(&rr, &gg, &bb, health * 1.2f, saturation, 1); + int red = int(rr * 255); + int green = int(gg * 255); + int blue = int(bb * 255); + + color = (red << 16) | (green << 8) | blue; + } + else + { + color = crosshaircolor; + } + + DrawTexture(twod, CrosshairImage, + xpos, ypos, + DTA_DestWidth, w, + DTA_DestHeight, h, + DTA_AlphaChannel, true, + DTA_FillColor, color & 0xFFFFFF, + TAG_DONE); +} + + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +enum ENumFlags +{ + FNF_WHENNOTZERO = 0x1, + FNF_FILLZEROS = 0x2, +}; + +void FormatNumber(int number, int minsize, int maxsize, int flags, const FString& prefix, FString* result) +{ + static int maxvals[] = { 1, 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999 }; + + if (number == 0 && (flags & FNF_WHENNOTZERO)) + { + *result = ""; + return; + } + if (maxsize > 0 && maxsize < 10) + { + number = clamp(number, -maxvals[maxsize - 1], maxvals[maxsize]); + } + FString& fmt = *result; + if (minsize <= 1) fmt.Format("%s%d", prefix.GetChars(), number); + else if (flags & FNF_FILLZEROS) fmt.Format("%s%0*d", prefix.GetChars(), minsize, number); + else fmt.Format("%s%*d", prefix.GetChars(), minsize, number); +} + + +void ValidateResolution(int &hres, int &vres) { if (hres == 0) { @@ -131,121 +280,6 @@ static void ValidateResolution(int &hres, int &vres) } } -void DBaseStatusBar::SetSize(int reltop, int hres, int vres, int hhres, int hvres) -{ - ValidateResolution(hres, vres); - - BaseRelTop = reltop; - BaseSBarHorizontalResolution = hres; - BaseSBarVerticalResolution = vres; - BaseHUDHorizontalResolution = hhres < 0? hres : hhres; - BaseHUDVerticalResolution = hvres < 0? vres : hvres; - SetDrawSize(reltop, hres, vres); -} - -void DBaseStatusBar::SetDrawSize(int reltop, int hres, int vres) -{ - ValidateResolution(hres, vres); - - RelTop = reltop; - HorizontalResolution = hres; - VerticalResolution = vres; - SetScale(); // recalculate positioning info. -} - -//--------------------------------------------------------------------------- -// -// PROC SetScaled -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::SetScale () -{ - ValidateResolution(HorizontalResolution, VerticalResolution); - - double w = SCREENWIDTH; - double h = SCREENHEIGHT; - double refw, refh; - - int horz = HorizontalResolution; - int vert = VerticalResolution; - double refaspect = horz / double(vert); - double screenaspect = w / double(h); - - if ((horz == 320 && vert == 200) || (horz == 640 && vert == 400)) - { - refaspect = 1.333; - } - - if (screenaspect < refaspect) - { - refw = w; - refh = w / refaspect; - } - else - { - refh = h; - refw = h * refaspect; - } - refw *= hud_scale; - refh *= hud_scale; - - int sby = VerticalResolution - RelTop; - // Use full pixels for destination size. - - ST_X = xs_CRoundToInt((w - refw) / 2); - ST_Y = xs_CRoundToInt(h - refh); - SBarTop = Scale(sby, h, VerticalResolution); - SBarScale.X = refw / horz; - SBarScale.Y = refh / vert; -} - -//--------------------------------------------------------------------------- -// -// PROC GetHUDScale -// -//--------------------------------------------------------------------------- - -DVector2 DBaseStatusBar::GetHUDScale() const -{ - return SBarScale; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::BeginStatusBar(int resW, int resH, int relTop) -{ - SetDrawSize(relTop < 0? BaseRelTop : relTop, resW < 0? BaseSBarHorizontalResolution : resW, resH < 0? BaseSBarVerticalResolution : resH); - fullscreenOffsets = false; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::BeginHUD(int resW, int resH, double Alpha) -{ - SetDrawSize(RelTop, resW < 0? BaseHUDHorizontalResolution : resW, resH < 0? BaseHUDVerticalResolution : resH); - this->Alpha = Alpha; - CompleteBorder = false; - fullscreenOffsets = true; -} - -//--------------------------------------------------------------------------- -// -// PROC Tick -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::Tick () -{ -} //============================================================================ // @@ -253,7 +287,7 @@ void DBaseStatusBar::Tick () // //============================================================================ -void DBaseStatusBar::StatusbarToRealCoords(double &x, double &y, double &w, double &h) const +void DStatusBarCore::StatusbarToRealCoords(double &x, double &y, double &w, double &h) const { x = ST_X + x * SBarScale.X; y = ST_Y + y * SBarScale.Y; @@ -267,7 +301,7 @@ void DBaseStatusBar::StatusbarToRealCoords(double &x, double &y, double &w, doub // //============================================================================ -void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation, double rotate, ERenderStyle style) +void DStatusBarCore::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation, double rotate, ERenderStyle style) { if (!texture.isValid()) return; @@ -276,7 +310,7 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int fla DrawGraphic(tex, x, y, flags, Alpha, boxwidth, boxheight, scaleX, scaleY, color, translation, rotate, style); } -void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation, double rotate, ERenderStyle style) +void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation, double rotate, ERenderStyle style) { double texwidth = tex->GetDisplayWidth() * scaleX; double texheight = tex->GetDisplayHeight() * scaleY; @@ -349,8 +383,6 @@ void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flag case DI_ITEM_VOFFSET: yo = tex->GetDisplayTopOffset(); break; } } - //xo *= scaleX; - //yo *= scaleY; if (!fullscreenOffsets) { @@ -363,19 +395,19 @@ void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flag switch (flags & DI_SCREEN_HMASK) { default: orgx = 0; break; - case DI_SCREEN_HCENTER: orgx = screen->GetWidth() / 2; break; - case DI_SCREEN_RIGHT: orgx = screen->GetWidth(); break; + case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break; + case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break; } switch (flags & DI_SCREEN_VMASK) { default: orgy = 0; break; - case DI_SCREEN_VCENTER: orgy = screen->GetHeight() / 2; break; - case DI_SCREEN_BOTTOM: orgy = screen->GetHeight(); break; + case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break; + case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break; } // move stuff in the top right corner a bit down if the fps counter is on. - if ((flags & (DI_SCREEN_HMASK|DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; + if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; DVector2 Scale = GetHUDScale(); @@ -413,7 +445,7 @@ void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flag // //============================================================================ -void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY) +void DStatusBarCore::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY) { bool monospaced = monospacing != EMonospacing::Off; double dx = 0; @@ -452,15 +484,15 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d switch (flags & DI_SCREEN_HMASK) { default: orgx = 0; break; - case DI_SCREEN_HCENTER: orgx = screen->GetWidth() / 2; break; - case DI_SCREEN_RIGHT: orgx = screen->GetWidth(); break; + case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break; + case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break; } switch (flags & DI_SCREEN_VMASK) { default: orgy = 0; break; - case DI_SCREEN_VCENTER: orgy = screen->GetHeight() / 2; break; - case DI_SCREEN_BOTTOM: orgy = screen->GetHeight(); break; + case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break; + case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break; } // move stuff in the top right corner a bit down if the fps counter is on. @@ -531,15 +563,12 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d // This may have to be changed to draw the shadow text up front separately. if ((shadowX != 0 || shadowY != 0) && !(flags & DI_NOSHADOW)) { -#if 0 - // This doesn't work with the limited backend the engine currently uses. DrawChar(twod, font, CR_UNTRANSLATED, rx + shadowX, ry + shadowY, ch, DTA_DestWidthF, rw, DTA_DestHeightF, rh, - DTA_Alpha, (Alpha * 0.33), + DTA_Alpha, (Alpha * 0.4), DTA_FillColor, 0, TAG_DONE); -#endif } DrawChar(twod, font, fontcolor, rx, ry, ch, DTA_DestWidthF, rw, @@ -556,7 +585,7 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d } } -void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY) +void SBar_DrawString(DStatusBarCore *self, DHUDFont *font, const FString &string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY) { //if (font == nullptr) ThrowAbortException(X_READ_NIL, nullptr); //if (!screen->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); @@ -592,7 +621,7 @@ void SBar_DrawString(DBaseStatusBar *self, DHUDFont *font, const FString &string // //============================================================================ -void DBaseStatusBar::TransformRect(double &x, double &y, double &w, double &h, int flags) +void DStatusBarCore::TransformRect(double &x, double &y, double &w, double &h, int flags) { // resolve auto-alignment before making any adjustments to the position values. if (!(flags & DI_SCREEN_MANUAL_ALIGN)) @@ -617,15 +646,15 @@ void DBaseStatusBar::TransformRect(double &x, double &y, double &w, double &h, i switch (flags & DI_SCREEN_HMASK) { default: orgx = 0; break; - case DI_SCREEN_HCENTER: orgx = screen->GetWidth() / 2; break; - case DI_SCREEN_RIGHT: orgx = screen->GetWidth(); break; + case DI_SCREEN_HCENTER: orgx = twod->GetWidth() / 2; break; + case DI_SCREEN_RIGHT: orgx = twod->GetWidth(); break; } switch (flags & DI_SCREEN_VMASK) { default: orgy = 0; break; - case DI_SCREEN_VCENTER: orgy = screen->GetHeight() / 2; break; - case DI_SCREEN_BOTTOM: orgy = screen->GetHeight(); break; + case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break; + case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break; } // move stuff in the top right corner a bit down if the fps counter is on. @@ -643,286 +672,3 @@ void DBaseStatusBar::TransformRect(double &x, double &y, double &w, double &h, i } -static DObject *InitObject(PClass *type, int paramnum, VM_ARGS) -{ - auto obj = type->CreateNew(); - // Todo: init - return obj; -} - -//============================================================================ -// -// -// -//============================================================================ - -enum ENumFlags -{ - FNF_WHENNOTZERO = 0x1, - FNF_FILLZEROS = 0x2, -}; - -void FormatNumber(int number, int minsize, int maxsize, int flags, const FString &prefix, FString *result) -{ - static int maxvals[] = { 1, 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999 }; - - if (number == 0 && (flags & FNF_WHENNOTZERO)) - { - *result = ""; - return; - } - if (maxsize > 0 && maxsize < 10) - { - number = clamp(number, -maxvals[maxsize - 1], maxvals[maxsize]); - } - FString &fmt = *result; - if (minsize <= 1) fmt.Format("%s%d", prefix.GetChars(), number); - else if (flags & FNF_FILLZEROS) fmt.Format("%s%0*d", prefix.GetChars(), minsize, number); - else fmt.Format("%s%*d", prefix.GetChars(), minsize, number); -} - -//============================================================================ -// -// -// -//============================================================================ - -void DBaseStatusBar::PrintLevelStats(FLevelStats &stats) -{ - double y; - double scale = stats.fontscale * hud_statscale; - if (stats.spacing <= 0) stats.spacing = stats.font->GetHeight() * stats.fontscale; - double spacing = stats.spacing * hud_statscale; - if (stats.screenbottomspace < 0) - { - y = 200 - RelTop - spacing; - } - else - { - y = 200 - stats.screenbottomspace - spacing; - } - - double y1, y2, y3; - - if (stats.maxsecrets > 0) // don't bother if there are no secrets. - { - y1 = y; - y -= spacing; - } - if (stats.frags >= 0 || stats.maxkills != -1) - { - y2 = y; - y -= spacing; - } - y3 = y; - - - FString text; - int black = 0x80000000; - - text.Format(TEXTCOLOR_ESCAPESTR "%cT: " TEXTCOLOR_ESCAPESTR "%c%d:%02d", stats.letterColor + 'A', stats.standardColor + 'A', stats.time / 60000, (stats.time % 60000) / 1000); - DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale + scale, y3 + scale, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_LegacyRenderStyle, STYLE_TranslucentStencil, DTA_Color, black, TAG_DONE); - DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale, y3, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); - - text = ""; - if (stats.frags > -1) text.Format(TEXTCOLOR_ESCAPESTR "%cF: " TEXTCOLOR_ESCAPESTR "%c%d", stats.letterColor + 'A', stats.standardColor + 'A', stats.frags); - else if (stats.maxkills == -2) text.Format(TEXTCOLOR_ESCAPESTR "%cK: " TEXTCOLOR_ESCAPESTR "%c%d", stats.letterColor + 'A', stats.standardColor + 'A', stats.kills); - else if (stats.maxkills != -1) text.Format(TEXTCOLOR_ESCAPESTR "%cK: " TEXTCOLOR_ESCAPESTR "%c%d/%d", - stats.letterColor + 'A', stats.kills == stats.maxkills ? stats.completeColor + 'A' : stats.standardColor + 'A', stats.kills, stats.maxkills); - - if (text.IsNotEmpty()) - { - DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale+scale, y2+scale, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_LegacyRenderStyle, STYLE_TranslucentStencil, DTA_Color, black, TAG_DONE); - - DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale, y2, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); - } - - if (stats.maxsecrets > 0) // don't bother if there are no secrets. - { - text.Format(TEXTCOLOR_ESCAPESTR "%cS: " TEXTCOLOR_ESCAPESTR "%c%d/%d", - stats.letterColor + 'A', stats.secrets == stats.maxsecrets ? stats.completeColor + 'A' : stats.standardColor + 'A', stats.secrets, stats.maxsecrets); - - DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale + scale, y1 + scale, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_LegacyRenderStyle, STYLE_TranslucentStencil, DTA_Color, black, TAG_DONE); - - DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale, y1, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); - } -} - -//============================================================================ -// -// -// -//============================================================================ - -void DBaseStatusBar::PrintAutomapInfo(FLevelStats& stats, bool forcetextfont) -{ - auto lev = currentLevel; - FString mapname; - if (am_showlabel) - mapname.Format(TEXTCOLOR_ESCAPESTR "%c%s: " TEXTCOLOR_ESCAPESTR "%c%s", stats.letterColor+'A', lev->LabelName(), stats.standardColor+'A', lev->DisplayName()); - else - mapname = lev->DisplayName(); - - forcetextfont |= am_textfont; - double y; - double scale = stats.fontscale * (forcetextfont ? *hud_statscale : 1); // the tiny default font used by all games here cannot be scaled for readability purposes. - if (stats.spacing <= 0) stats.spacing = stats.font->GetHeight() * stats.fontscale; - double spacing = stats.spacing * (forcetextfont ? *hud_statscale : 1); - if (am_nameontop) - { - y = spacing + 1; - } - else if (stats.screenbottomspace < 0) - { - y = 200 - RelTop - spacing; - } - else - { - y = 200 - stats.screenbottomspace - spacing; - } - const auto &volname = gVolumeNames[volfromlevelnum(lev->levelNumber)]; - if (volname.IsEmpty() && am_nameontop) y = 1; - - DrawText(twod, stats.font, stats.standardColor, 2 * hud_statscale, y, mapname, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_KeepRatio, true, TAG_DONE); - y -= spacing; - if (!(lev->flags & MI_USERMAP) && !(g_gameType & GAMEFLAG_PSEXHUMED) && volname.IsNotEmpty()) - DrawText(twod, stats.font, stats.standardColor, 2 * hud_statscale, y, GStrings.localize(volname), - DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, - DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_KeepRatio, true, TAG_DONE); -} - -//============================================================================ -// -// -// -//============================================================================ - -short DBaseStatusBar::CalcMagazineAmount(short ammo_remaining, short clip_capacity, bool reloading) -{ - // Determine amount in clip. - short clip_amount = ammo_remaining % clip_capacity; - - // Set current clip value to clip capacity if wrapped around to zero, otherwise use determined value. - short clip_current = ammo_remaining != 0 && clip_amount == 0 ? clip_capacity : clip_amount; - - // Return current clip value if weapon has rounds or is not on a reload cycle. - return ammo_remaining == 0 || (reloading && clip_amount == 0) ? 0 : clip_current; -} - -//============================================================================ -// -// -// -//============================================================================ - -void DBaseStatusBar::Set43ClipRect() -{ - auto GetWidth = [=]() { return twod->GetWidth(); }; - auto GetHeight = [=]() {return twod->GetHeight(); }; - - auto screenratio = ActiveRatio(GetWidth(), GetHeight()); - if (screenratio < 1.34) return; - - int width = xs_CRoundToInt(GetWidth() * 1.333 / screenratio); - int left = (GetWidth() - width) / 2; - twod->SetClipRect(left, 0, width, GetHeight()); -} - -//============================================================================ -// -// -// -//============================================================================ - -void setViewport(int viewSize) -{ - int x0, y0, x1, y1; - if (screen == nullptr) return; - int xdim = screen->GetWidth(); - int ydim = screen->GetHeight(); - if (xdim == 0 || ydim == 0) return; - auto reserved = gi->GetReservedScreenSpace(viewSize); - reserved.top = xs_CRoundToInt((reserved.top * hud_scale * ydim) / 200); - reserved.statusbar = xs_CRoundToInt((reserved.statusbar * hud_scale * ydim) / 200); - - int xdimcorrect = std::min(Scale(ydim, 4, 3), xdim); - if (viewSize > Hud_Stbar) - { - x0 = 0; - x1 = xdim - 1; - y0 = reserved.top; - y1 = ydim - 1; - } - else - { - x0 = 0; - y0 = reserved.top; - x1 = xdim - 1; - y1 = ydim - 1 - reserved.statusbar; - - int height = y1 - y0; - int frameheight = (height * (5 - viewSize) / 20); - int framewidth = Scale(frameheight, xdim, y1+1); - x0 += framewidth; - x1 -= framewidth; - y0 += frameheight; - y1 -= frameheight; - } - videoSetViewableArea(x0, y0, x1, y1); -} - -//============================================================================ -// -// -// -//============================================================================ - -int levelTextTime; - -void SerializeHud(FSerializer &arc) -{ - if (arc.BeginObject("hud")) - { - arc("texttimer", levelTextTime) - .EndObject(); - } -} - -void setLevelStarted(MapRecord *mi) -{ - levelTextTime = 85; - Printf(PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s: %s\n", mi->LabelName(), mi->DisplayName()); -} - -void drawMapTitle() -{ - if (!hud_showmapname || levelTextTime <= 0 || M_Active()) - return; - - double alpha = levelTextTime > 16? 1.0 : levelTextTime / 16.; - if (alpha > 0) - { - double scale = (g_gameType & GAMEFLAG_RRALL)? 0.4 : (g_gameType & GAMEFLAG_SW)? 0.7 : 1.0; - auto text = currentLevel->DisplayName(); - double x = 160 - BigFont->StringWidth(text) * scale / 2.; - double y = (g_gameType & GAMEFLAG_BLOOD)? 50 : 100 - BigFont->GetHeight()/2.; - bool shadow = true; - - if (shadow) - { - DrawText(twod, BigFont, CR_UNDEFINED, x+1, y+1, text, DTA_FullscreenScale, FSMode_Fit320x200, DTA_Color, 0xff000000, DTA_Alpha, alpha / 2., DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); - } - DrawText(twod, BigFont, CR_UNDEFINED, x, y, text, DTA_FullscreenScale, FSMode_Fit320x200, DTA_Alpha, alpha, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); - } -} - - - - diff --git a/source/core/statusbar.h b/source/core/statusbar.h index ec9ede161..a37a202ec 100644 --- a/source/core/statusbar.h +++ b/source/core/statusbar.h @@ -108,9 +108,9 @@ public: }; -class DBaseStatusBar //: public DObject +class DStatusBarCore //: public DObject { - //DECLARE_CLASS (DBaseStatusBar, DObject) + //DECLARE_CLASS (DStatusBarCore, DObject) //HAS_OBJECT_POINTERS public: // Popup screens for Strife's status bar @@ -161,8 +161,8 @@ public: CENTER_BOTTOM = BOTTOM | HCENTER }; - DBaseStatusBar (); - virtual ~DBaseStatusBar() = default; + DStatusBarCore (); + virtual ~DStatusBarCore() = default; void SetSize(int reltop = 32, int hres = 320, int vres = 200, int hhres = -1, int hvres = -1); void ShowPlayerName (); @@ -199,6 +199,8 @@ public: short CalcMagazineAmount(short ammo_remaining, short clip_capacity, bool reloading); void Set43ClipRect(); + void SetClipRect(double x, double y, double w, double h, int flags); + //protected: void DrawPowerups (); @@ -245,11 +247,11 @@ private: }; -extern DBaseStatusBar *StatusBar; +extern DStatusBarCore *StatusBar; // Status bar factories ----------------------------------------------------- -DBaseStatusBar *CreateCustomStatusBar(int script=0); +DStatusBarCore *CreateCustomStatusBar(int script=0); // Crosshair stuff ---------------------------------------------------------- @@ -343,7 +345,7 @@ enum DI_Flags }; -void SBar_DrawString(DBaseStatusBar* self, DHUDFont* font, const FString& string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY); +void SBar_DrawString(DStatusBarCore* self, DHUDFont* font, const FString& string, double x, double y, int flags, int trans, double alpha, int wrapwidth, int linespacing, double scaleX, double scaleY); void setViewport(int viewSize); struct MapRecord; void setLevelStarted(MapRecord *); diff --git a/source/core/statusbar2.cpp b/source/core/statusbar2.cpp new file mode 100644 index 000000000..b45623e1f --- /dev/null +++ b/source/core/statusbar2.cpp @@ -0,0 +1,485 @@ +/* +** shared_sbar.cpp +** Base status bar implementation +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** Copyright 2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include + +#include "build.h" +#include "templates.h" +#include "statusbar.h" +#include "c_cvars.h" +#include "c_dispatch.h" +#include "c_console.h" +#include "v_video.h" +#include "filesystem.h" +#include "s_soundinternal.h" +#include "serializer.h" +#include "serialize_obj.h" +#include "cmdlib.h" +#include "vm.h" +#include "gstrings.h" +#include "utf8.h" +#include "texturemanager.h" +#include "cmdlib.h" +#include "v_draw.h" +#include "v_font.h" +#include "v_draw.h" +#include "gamecvars.h" +#include "m_fixed.h" +#include "gamecontrol.h" +#include "gamestruct.h" +#include "razemenu.h" +#include "mapinfo.h" + +#include "../version.h" + +#define XHAIRSHRINKSIZE (1./18) +#define XHAIRPICKUPSIZE (2+XHAIRSHRINKSIZE) +#define POWERUPICONSIZE 32 + +//IMPLEMENT_CLASS(DHUDFont, true, false); + +EXTERN_CVAR (Bool, am_showmonsters) +EXTERN_CVAR (Bool, am_showsecrets) +EXTERN_CVAR (Bool, am_showtime) +EXTERN_CVAR (Bool, am_showtotaltime) +EXTERN_CVAR (Bool, noisedebug) +EXTERN_CVAR(Bool, vid_fps) +EXTERN_CVAR(Bool, inter_subtitles) + +extern DStatusBarCore *StatusBar; + +extern int setblocks; + + +//--------------------------------------------------------------------------- +// ST_Clear +// +//--------------------------------------------------------------------------- + +void ST_Clear() +{ + if (StatusBar != NULL) + { + delete StatusBar; + StatusBar = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// Constructor +// +//--------------------------------------------------------------------------- +DStatusBarCore::DStatusBarCore () +{ + CompleteBorder = false; + Centering = false; + FixedOrigin = false; + CrosshairSize = 1.; + Displacement = 0; + ShowLog = false; + SetSize(0); +} + +void ValidateResolution(int& hres, int& vres); + +void DStatusBarCore::SetSize(int reltop, int hres, int vres, int hhres, int hvres) +{ + ValidateResolution(hres, vres); + + BaseRelTop = reltop; + BaseSBarHorizontalResolution = hres; + BaseSBarVerticalResolution = vres; + BaseHUDHorizontalResolution = hhres < 0? hres : hhres; + BaseHUDVerticalResolution = hvres < 0? vres : hvres; + SetDrawSize(reltop, hres, vres); +} + +void DStatusBarCore::SetDrawSize(int reltop, int hres, int vres) +{ + ValidateResolution(hres, vres); + + RelTop = reltop; + HorizontalResolution = hres; + VerticalResolution = vres; + SetScale(); // recalculate positioning info. +} + +//--------------------------------------------------------------------------- +// +// PROC SetScaled +// +//--------------------------------------------------------------------------- + +void DStatusBarCore::SetScale () +{ + ValidateResolution(HorizontalResolution, VerticalResolution); + + double w = SCREENWIDTH; + double h = SCREENHEIGHT; + double refw, refh; + + int horz = HorizontalResolution; + int vert = VerticalResolution; + double refaspect = horz / double(vert); + double screenaspect = w / double(h); + + if ((horz == 320 && vert == 200) || (horz == 640 && vert == 400)) + { + refaspect = 1.333; + } + + if (screenaspect < refaspect) + { + refw = w; + refh = w / refaspect; + } + else + { + refh = h; + refw = h * refaspect; + } + refw *= hud_scale; + refh *= hud_scale; + + int sby = VerticalResolution - RelTop; + // Use full pixels for destination size. + + ST_X = xs_CRoundToInt((w - refw) / 2); + ST_Y = xs_CRoundToInt(h - refh); + SBarTop = Scale(sby, h, VerticalResolution); + SBarScale.X = refw / horz; + SBarScale.Y = refh / vert; +} + +//--------------------------------------------------------------------------- +// +// PROC GetHUDScale +// +//--------------------------------------------------------------------------- + +DVector2 DStatusBarCore::GetHUDScale() const +{ + return SBarScale; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void DStatusBarCore::BeginStatusBar(int resW, int resH, int relTop) +{ + SetDrawSize(relTop < 0? BaseRelTop : relTop, resW < 0? BaseSBarHorizontalResolution : resW, resH < 0? BaseSBarVerticalResolution : resH); + fullscreenOffsets = false; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void DStatusBarCore::BeginHUD(int resW, int resH, double Alpha) +{ + SetDrawSize(RelTop, resW < 0? BaseHUDHorizontalResolution : resW, resH < 0? BaseHUDVerticalResolution : resH); + this->Alpha = Alpha; + CompleteBorder = false; + fullscreenOffsets = true; +} + +//--------------------------------------------------------------------------- +// +// PROC Tick +// +//--------------------------------------------------------------------------- + +void DStatusBarCore::Tick () +{ +} + + +static DObject *InitObject(PClass *type, int paramnum, VM_ARGS) +{ + auto obj = type->CreateNew(); + // Todo: init + return obj; +} + +//============================================================================ +// +// +// +//============================================================================ + +void DStatusBarCore::PrintLevelStats(FLevelStats &stats) +{ + double y; + double scale = stats.fontscale * hud_statscale; + if (stats.spacing <= 0) stats.spacing = stats.font->GetHeight() * stats.fontscale; + double spacing = stats.spacing * hud_statscale; + if (stats.screenbottomspace < 0) + { + y = 200 - RelTop - spacing; + } + else + { + y = 200 - stats.screenbottomspace - spacing; + } + + double y1, y2, y3; + + if (stats.maxsecrets > 0) // don't bother if there are no secrets. + { + y1 = y; + y -= spacing; + } + if (stats.frags >= 0 || stats.maxkills != -1) + { + y2 = y; + y -= spacing; + } + y3 = y; + + + FString text; + int black = 0x80000000; + + text.Format(TEXTCOLOR_ESCAPESTR "%cT: " TEXTCOLOR_ESCAPESTR "%c%d:%02d", stats.letterColor + 'A', stats.standardColor + 'A', stats.time / 60000, (stats.time % 60000) / 1000); + DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale + scale, y3 + scale, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_LegacyRenderStyle, STYLE_TranslucentStencil, DTA_Color, black, TAG_DONE); + DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale, y3, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); + + text = ""; + if (stats.frags > -1) text.Format(TEXTCOLOR_ESCAPESTR "%cF: " TEXTCOLOR_ESCAPESTR "%c%d", stats.letterColor + 'A', stats.standardColor + 'A', stats.frags); + else if (stats.maxkills == -2) text.Format(TEXTCOLOR_ESCAPESTR "%cK: " TEXTCOLOR_ESCAPESTR "%c%d", stats.letterColor + 'A', stats.standardColor + 'A', stats.kills); + else if (stats.maxkills != -1) text.Format(TEXTCOLOR_ESCAPESTR "%cK: " TEXTCOLOR_ESCAPESTR "%c%d/%d", + stats.letterColor + 'A', stats.kills == stats.maxkills ? stats.completeColor + 'A' : stats.standardColor + 'A', stats.kills, stats.maxkills); + + if (text.IsNotEmpty()) + { + DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale+scale, y2+scale, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_LegacyRenderStyle, STYLE_TranslucentStencil, DTA_Color, black, TAG_DONE); + + DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale, y2, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); + } + + if (stats.maxsecrets > 0) // don't bother if there are no secrets. + { + text.Format(TEXTCOLOR_ESCAPESTR "%cS: " TEXTCOLOR_ESCAPESTR "%c%d/%d", + stats.letterColor + 'A', stats.secrets == stats.maxsecrets ? stats.completeColor + 'A' : stats.standardColor + 'A', stats.secrets, stats.maxsecrets); + + DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale + scale, y1 + scale, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_LegacyRenderStyle, STYLE_TranslucentStencil, DTA_Color, black, TAG_DONE); + + DrawText(twod, stats.font, CR_UNTRANSLATED, 2 * hud_statscale, y1, text, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_KeepRatio, true, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); + } +} + +//============================================================================ +// +// +// +//============================================================================ + +void DStatusBarCore::PrintAutomapInfo(FLevelStats& stats, bool forcetextfont) +{ + auto lev = currentLevel; + FString mapname; + if (am_showlabel) + mapname.Format(TEXTCOLOR_ESCAPESTR "%c%s: " TEXTCOLOR_ESCAPESTR "%c%s", stats.letterColor+'A', lev->LabelName(), stats.standardColor+'A', lev->DisplayName()); + else + mapname = lev->DisplayName(); + + forcetextfont |= am_textfont; + double y; + double scale = stats.fontscale * (forcetextfont ? *hud_statscale : 1); // the tiny default font used by all games here cannot be scaled for readability purposes. + if (stats.spacing <= 0) stats.spacing = stats.font->GetHeight() * stats.fontscale; + double spacing = stats.spacing * (forcetextfont ? *hud_statscale : 1); + if (am_nameontop) + { + y = spacing + 1; + } + else if (stats.screenbottomspace < 0) + { + y = 200 - RelTop - spacing; + } + else + { + y = 200 - stats.screenbottomspace - spacing; + } + const auto &volname = gVolumeNames[volfromlevelnum(lev->levelNumber)]; + if (volname.IsEmpty() && am_nameontop) y = 1; + + DrawText(twod, stats.font, stats.standardColor, 2 * hud_statscale, y, mapname, DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_KeepRatio, true, TAG_DONE); + y -= spacing; + if (!(lev->flags & MI_USERMAP) && !(g_gameType & GAMEFLAG_PSEXHUMED) && volname.IsNotEmpty()) + DrawText(twod, stats.font, stats.standardColor, 2 * hud_statscale, y, GStrings.localize(volname), + DTA_FullscreenScale, FSMode_ScaleToHeight, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, + DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_KeepRatio, true, TAG_DONE); +} + +//============================================================================ +// +// +// +//============================================================================ + +short DStatusBarCore::CalcMagazineAmount(short ammo_remaining, short clip_capacity, bool reloading) +{ + // Determine amount in clip. + short clip_amount = ammo_remaining % clip_capacity; + + // Set current clip value to clip capacity if wrapped around to zero, otherwise use determined value. + short clip_current = ammo_remaining != 0 && clip_amount == 0 ? clip_capacity : clip_amount; + + // Return current clip value if weapon has rounds or is not on a reload cycle. + return ammo_remaining == 0 || (reloading && clip_amount == 0) ? 0 : clip_current; +} + +//============================================================================ +// +// +// +//============================================================================ + +void DStatusBarCore::Set43ClipRect() +{ + auto GetWidth = [=]() { return twod->GetWidth(); }; + auto GetHeight = [=]() {return twod->GetHeight(); }; + + auto screenratio = ActiveRatio(GetWidth(), GetHeight()); + if (screenratio < 1.34) return; + + int width = xs_CRoundToInt(GetWidth() * 1.333 / screenratio); + int left = (GetWidth() - width) / 2; + twod->SetClipRect(left, 0, width, GetHeight()); +} + +//============================================================================ +// +// +// +//============================================================================ + +void setViewport(int viewSize) +{ + int x0, y0, x1, y1; + if (screen == nullptr) return; + int xdim = screen->GetWidth(); + int ydim = screen->GetHeight(); + if (xdim == 0 || ydim == 0) return; + auto reserved = gi->GetReservedScreenSpace(viewSize); + reserved.top = xs_CRoundToInt((reserved.top * hud_scale * ydim) / 200); + reserved.statusbar = xs_CRoundToInt((reserved.statusbar * hud_scale * ydim) / 200); + + int xdimcorrect = std::min(Scale(ydim, 4, 3), xdim); + if (viewSize > Hud_Stbar) + { + x0 = 0; + x1 = xdim - 1; + y0 = reserved.top; + y1 = ydim - 1; + } + else + { + x0 = 0; + y0 = reserved.top; + x1 = xdim - 1; + y1 = ydim - 1 - reserved.statusbar; + + int height = y1 - y0; + int frameheight = (height * (5 - viewSize) / 20); + int framewidth = Scale(frameheight, xdim, y1+1); + x0 += framewidth; + x1 -= framewidth; + y0 += frameheight; + y1 -= frameheight; + } + videoSetViewableArea(x0, y0, x1, y1); +} + +//============================================================================ +// +// +// +//============================================================================ + +int levelTextTime; + +void SerializeHud(FSerializer &arc) +{ + if (arc.BeginObject("hud")) + { + arc("texttimer", levelTextTime) + .EndObject(); + } +} + +void setLevelStarted(MapRecord *mi) +{ + levelTextTime = 85; + Printf(PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s: %s\n", mi->LabelName(), mi->DisplayName()); +} + +void drawMapTitle() +{ + if (!hud_showmapname || levelTextTime <= 0 || M_Active()) + return; + + double alpha = levelTextTime > 16? 1.0 : levelTextTime / 16.; + if (alpha > 0) + { + double scale = (g_gameType & GAMEFLAG_RRALL)? 0.4 : (g_gameType & GAMEFLAG_SW)? 0.7 : 1.0; + auto text = currentLevel->DisplayName(); + double x = 160 - BigFont->StringWidth(text) * scale / 2.; + double y = (g_gameType & GAMEFLAG_BLOOD)? 50 : 100 - BigFont->GetHeight()/2.; + bool shadow = true; + + if (shadow) + { + DrawText(twod, BigFont, CR_UNDEFINED, x+1, y+1, text, DTA_FullscreenScale, FSMode_Fit320x200, DTA_Color, 0xff000000, DTA_Alpha, alpha / 2., DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); + } + DrawText(twod, BigFont, CR_UNDEFINED, x, y, text, DTA_FullscreenScale, FSMode_Fit320x200, DTA_Alpha, alpha, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); + } +} + + + diff --git a/source/exhumed/src/status.cpp b/source/exhumed/src/status.cpp index 3e145b754..91fc3c7fd 100644 --- a/source/exhumed/src/status.cpp +++ b/source/exhumed/src/status.cpp @@ -512,7 +512,7 @@ void MoveStatus() } -class DExhumedStatusBar : public DBaseStatusBar +class DExhumedStatusBar : public DStatusBarCore { DHUDFont textfont, numberFont; @@ -936,7 +936,7 @@ private: if (automapMode == am_full) { - DBaseStatusBar::PrintAutomapInfo(stats, true); + DStatusBarCore::PrintAutomapInfo(stats, true); } else if (hud_stats) { @@ -948,7 +948,7 @@ private: stats.secrets = 0; stats.maxsecrets = 0; - DBaseStatusBar::PrintLevelStats(stats); + DStatusBarCore::PrintLevelStats(stats); } } diff --git a/source/games/duke/src/sbar.cpp b/source/games/duke/src/sbar.cpp index 5a7b1ff28..e512174e2 100644 --- a/source/games/duke/src/sbar.cpp +++ b/source/games/duke/src/sbar.cpp @@ -211,7 +211,7 @@ void DDukeCommonStatusBar::PrintLevelStats(int bottomy) else stats.spacing = stats.font->GetHeight() + 1; stats.standardColor = (isNamWW2GI() && am_textfont)? CR_ORANGE : CR_UNTRANSLATED; stats.letterColor = CR_GOLD; - DBaseStatusBar::PrintAutomapInfo(stats, textfont); + DStatusBarCore::PrintAutomapInfo(stats, textfont); } else if (hud_stats) { @@ -242,7 +242,7 @@ void DDukeCommonStatusBar::PrintLevelStats(int bottomy) stats.standardColor = stats.completeColor = CR_UNTRANSLATED; } - DBaseStatusBar::PrintLevelStats(stats); + DStatusBarCore::PrintLevelStats(stats); } } diff --git a/source/games/duke/src/sbar.h b/source/games/duke/src/sbar.h index f1423d76f..c9bffd089 100644 --- a/source/games/duke/src/sbar.h +++ b/source/games/duke/src/sbar.h @@ -7,7 +7,7 @@ BEGIN_DUKE_NS -class DDukeCommonStatusBar : public DBaseStatusBar +class DDukeCommonStatusBar : public DStatusBarCore { protected: DHUDFont numberFont; diff --git a/source/sw/src/sbar.cpp b/source/sw/src/sbar.cpp index 9b3d78524..6e24fe6dc 100644 --- a/source/sw/src/sbar.cpp +++ b/source/sw/src/sbar.cpp @@ -67,7 +67,7 @@ static const short icons[] = { ID_PanelCaltrops, }; -class DSWStatusBar : public DBaseStatusBar +class DSWStatusBar : public DStatusBarCore { DHUDFont miniFont, numberFont; @@ -967,7 +967,7 @@ private: stats.spacing = 6; } else stats.spacing = SmallFont->GetHeight() + 1; - DBaseStatusBar::PrintAutomapInfo(stats, textfont); + DStatusBarCore::PrintAutomapInfo(stats, textfont); } // JBF 20040124: display level stats in screen corner else if (hud_stats && !(CommEnabled || numplayers > 1)) @@ -984,7 +984,7 @@ private: stats.standardColor = CR_TAN; stats.completeColor = CR_FIRE; - DBaseStatusBar::PrintLevelStats(stats); + DStatusBarCore::PrintLevelStats(stats); } }