From 1169922bf00174582c0db9d4c9e5c0acba65d303 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 28 Oct 2020 17:50:05 +0100 Subject: [PATCH] - building the new base class. --- src/g_statusbar/base_sbar.cpp | 226 ++++++++++++++++++++++++++++++-- src/g_statusbar/base_sbar.h | 24 +++- src/g_statusbar/sbar.h | 13 -- src/g_statusbar/shared_sbar.cpp | 120 ++++------------- 4 files changed, 257 insertions(+), 126 deletions(-) diff --git a/src/g_statusbar/base_sbar.cpp b/src/g_statusbar/base_sbar.cpp index cd0fb577dc..fde2a1c966 100644 --- a/src/g_statusbar/base_sbar.cpp +++ b/src/g_statusbar/base_sbar.cpp @@ -56,12 +56,12 @@ IMPLEMENT_CLASS(DHUDFont, true, false); CVAR(Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE); -CVAR(Int, crosshairhealth, 1, 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) - +EXTERN_CVAR(Float, hud_scalefactor) void ST_LoadCrosshair(int num, bool alwaysload) { @@ -249,6 +249,178 @@ void DStatusBarCore::ValidateResolution(int& hres, int& vres) const } +//============================================================================ +// +// +// +//============================================================================ + +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); +} + +//============================================================================ +// +// calculates a clean scale for the status bar +// +//============================================================================ + +static void ST_CalcCleanFacs(int designwidth, int designheight, int realwidth, int realheight, int* cleanx, int* cleany) +{ + float ratio; + int cwidth; + int cheight; + int cx1, cy1, cx2, cy2; + + ratio = ActiveRatio(realwidth, realheight); + if (AspectTallerThanWide(ratio)) + { + cwidth = realwidth; + cheight = realheight * AspectMultiplier(ratio) / 48; + } + else + { + cwidth = realwidth * AspectMultiplier(ratio) / 48; + cheight = realheight; + } + // Use whichever pair of cwidth/cheight or width/height that produces less difference + // between CleanXfac and CleanYfac. + cx1 = MAX(cwidth / designwidth, 1); + cy1 = MAX(cheight / designheight, 1); + cx2 = MAX(realwidth / designwidth, 1); + cy2 = MAX(realheight / designheight, 1); + if (abs(cx1 - cy1) <= abs(cx2 - cy2) || MAX(cx1, cx2) >= 4) + { // e.g. 640x360 looks better with this. + *cleanx = cx1; + *cleany = cy1; + } + else + { // e.g. 720x480 looks better with this. + *cleanx = cx2; + *cleany = cy2; + } + + if (*cleanx < *cleany) + *cleany = *cleanx; + else + *cleanx = *cleany; +} + +//============================================================================ +// +// +// +//============================================================================ + +void DStatusBarCore::SetDrawSize(int reltop, int hres, int vres) +{ + ValidateResolution(hres, vres); + + RelTop = reltop; + HorizontalResolution = hres; + VerticalResolution = vres; + + int x, y; + ST_CalcCleanFacs(hres, vres, twod->GetWidth(), twod->GetHeight(), &x, &y); + defaultScale = { (double)x, (double)y }; + + SetScale(); // recalculate positioning info. +} + +//--------------------------------------------------------------------------- +// +// PROC SetScaled +// +//--------------------------------------------------------------------------- + +void DStatusBarCore::SetScale() +{ + ValidateResolution(HorizontalResolution, VerticalResolution); + + int w = twod->GetWidth(); + int h = twod->GetHeight(); + 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_scalefactor; + refh *= hud_scalefactor; + + 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, bool forceScaled) +{ + SetDrawSize(relTop < 0 ? BaseRelTop : relTop, resW < 0 ? BaseSBarHorizontalResolution : resW, resH < 0 ? BaseSBarVerticalResolution : resH); + ForcedScale = forceScaled; + fullscreenOffsets = false; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void DStatusBarCore::BeginHUD(int resW, int resH, double Alpha, bool forcescaled) +{ + SetDrawSize(RelTop, resW < 0 ? BaseHUDHorizontalResolution : resW, resH < 0 ? BaseHUDVerticalResolution : resH); + this->Alpha = Alpha; + ForcedScale = forcescaled; + CompleteBorder = false; + fullscreenOffsets = true; +} + //============================================================================ // // draw stuff @@ -280,15 +452,22 @@ void DStatusBarCore::StatusbarToRealCoords(double& x, double& y, double& w, doub // //============================================================================ -void DStatusBarCore::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY) +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; FGameTexture* tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE)); + DrawGraphic(tex, x, y, flags, Alpha, boxwidth, boxheight, scaleX, scaleY, color, translation, rotate, 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; + double texleftoffs = tex->GetDisplayLeftOffset() * scaleY; + double textopoffs = tex->GetDisplayTopOffset() * scaleY; + double boxleftoffs, boxtopoffs; if (boxwidth > 0 || boxheight > 0) { @@ -314,12 +493,16 @@ void DStatusBarCore::DrawGraphic(FTextureID texture, double x, double y, int fla boxwidth = texwidth * scale1; boxheight = texheight * scale1; + boxleftoffs = texleftoffs * scale1; + boxtopoffs = textopoffs * scale1; } } else { boxwidth = texwidth; boxheight = texheight; + boxleftoffs = texleftoffs; + boxtopoffs = textopoffs; } // resolve auto-alignment before making any adjustments to the position values. @@ -336,18 +519,28 @@ void DStatusBarCore::DrawGraphic(FTextureID texture, double x, double y, int fla x += drawOffset.X; y += drawOffset.Y; - switch (flags & DI_ITEM_HMASK) + if (flags & DI_ITEM_RELCENTER) { - case DI_ITEM_HCENTER: x -= boxwidth / 2; break; - case DI_ITEM_RIGHT: x -= boxwidth; break; - case DI_ITEM_HOFFSET: x -= tex->GetDisplayLeftOffset() * boxwidth / texwidth; break; + if (flags & DI_MIRROR) boxleftoffs = -boxleftoffs; + if (flags & DI_MIRRORY) boxtopoffs = -boxtopoffs; + x -= boxwidth / 2 + boxleftoffs; + y -= boxheight / 2 + boxtopoffs; } - - switch (flags & DI_ITEM_VMASK) + else { - case DI_ITEM_VCENTER: y -= boxheight / 2; break; - case DI_ITEM_BOTTOM: y -= boxheight; break; - case DI_ITEM_VOFFSET: y -= tex->GetDisplayTopOffset() * boxheight / texheight; break; + switch (flags & DI_ITEM_HMASK) + { + case DI_ITEM_HCENTER: x -= boxwidth / 2; break; + case DI_ITEM_RIGHT: x -= boxwidth; break; + case DI_ITEM_HOFFSET: x -= boxleftoffs; break; + } + + switch (flags & DI_ITEM_VMASK) + { + case DI_ITEM_VCENTER: y -= boxheight / 2; break; + case DI_ITEM_BOTTOM: y -= boxheight; break; + case DI_ITEM_VOFFSET: y -= boxtopoffs; break; + } } if (!fullscreenOffsets) @@ -389,12 +582,16 @@ void DStatusBarCore::DrawGraphic(FTextureID texture, double x, double y, int fla DTA_LeftOffset, 0, DTA_DestWidthF, boxwidth, DTA_DestHeightF, boxheight, - DTA_TranslationIndex, (flags & DI_TRANSLATABLE) ? GetTranslation() : 0, + DTA_Color, color, + DTA_TranslationIndex, translation? translation : (flags & DI_TRANSLATABLE) ? GetTranslation() : 0, DTA_ColorOverlay, (flags & DI_DIM) ? MAKEARGB(170, 0, 0, 0) : 0, DTA_Alpha, Alpha, DTA_AlphaChannel, !!(flags & DI_ALPHAMAPPED), DTA_FillColor, (flags & DI_ALPHAMAPPED) ? 0 : -1, DTA_FlipX, !!(flags & DI_MIRROR), + DTA_FlipY, !!(flags& DI_MIRRORY), + DTA_Rotate, rotate, + DTA_LegacyRenderStyle, style, TAG_DONE); } @@ -476,11 +673,12 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d } int width; - auto c = font->GetChar(ch, fontcolor, &width); + FGameTexture* c = font->GetChar(ch, fontcolor, &width); if (c == NULL) //missing character. { continue; } + width += font->GetDefaultKerning(); if (!monospaced) //If we are monospaced lets use the offset x += (c->GetDisplayLeftOffset() + 1); //ignore x offsets since we adapt to character size diff --git a/src/g_statusbar/base_sbar.h b/src/g_statusbar/base_sbar.h index 794df9425b..4d575c3d3f 100644 --- a/src/g_statusbar/base_sbar.h +++ b/src/g_statusbar/base_sbar.h @@ -20,6 +20,8 @@ enum DI_Flags DI_SKIPSPAWN = 0x4, DI_SKIPREADY = 0x8, DI_ALTICONFIRST = 0x10, + + DI_TRANSLATABLE = 0x20, DI_FORCESCALE = 0x40, DI_DIM = 0x80, @@ -28,6 +30,8 @@ enum DI_Flags DI_DIMDEPLETED = 0x400, DI_DONTANIMATE = 0x800, // do not animate the texture DI_MIRROR = 0x1000, // flip the texture horizontally, like a mirror + DI_ITEM_RELCENTER = 0x2000, + DI_MIRRORY = 0x40000000, DI_SCREEN_AUTO = 0, // decide based on given offsets. DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect @@ -148,21 +152,35 @@ public: int ST_X; int ST_Y; int SBarTop; - DVector2 SBarScale; int RelTop; int HorizontalResolution, VerticalResolution; double Alpha = 1.; + DVector2 SBarScale; DVector2 drawOffset = { 0,0 }; // can be set by subclasses to offset drawing operations + DVector2 defaultScale; // factor for clean fully scaled display. double drawClip[4] = { 0,0,0,0 }; // defines a clipping rectangle (not used yet) bool fullscreenOffsets = false; // current screen is displayed with fullscreen behavior. bool ForcedScale = false; + bool CompleteBorder = false; + + int BaseRelTop; + int BaseSBarHorizontalResolution; + int BaseSBarVerticalResolution; + int BaseHUDHorizontalResolution; + int BaseHUDVerticalResolution; - virtual DVector2 GetHUDScale() const = 0; + void BeginStatusBar(int resW, int resH, int relTop, bool forceScaled = false); + void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false); + void SetSize(int reltop = 32, int hres = 320, int vres = 200, int hhres = -1, int hvres = -1); + virtual DVector2 GetHUDScale() const; virtual uint32_t GetTranslation() const { return 0; } + void SetDrawSize(int reltop, int hres, int vres); + virtual void SetScale(); void ValidateResolution(int& hres, int& vres) const; void StatusbarToRealCoords(double& x, double& y, double& w, double& h) const; - void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY); + void DrawGraphic(FGameTexture* texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, double rotate = 0, ERenderStyle style = STYLE_Translucent); + void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, double rotate = 0, ERenderStyle style = STYLE_Translucent); void 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 TransformRect(double& x, double& y, double& w, double& h, int flags = 0); void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0); diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index ae08b425b7..85fd623055 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -369,7 +369,6 @@ public: DBaseStatusBar (); - void SetSize(int reltop = 32, int hres = 320, int vres = 200, int hhres = -1, int hvres = -1); void OnDestroy() override; void AttachMessage (DHUDMessageBase *msg, uint32_t id=0, int layer=HUDMSGLayer_Default); @@ -407,8 +406,6 @@ public: void CreateAltHUD(); void DrawAltHUD(); - void BeginStatusBar(int resW, int resH, int relTop, bool forceScaled); - void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false); bool ForceHUDScale(bool on) { std::swap(ForcedScale, on); return on; } // This is for SBARINFO which should not use BeginStatusBar or BeginHUD. int GetTopOfStatusbar() const { @@ -433,11 +430,9 @@ public: // Sizing info for ths status bar. bool Scaled; // This needs to go away. - DVector2 defaultScale; // factor for fully scaled fullscreen display. bool Centering; bool FixedOrigin; - bool CompleteBorder; double CrosshairSize; double Displacement; bool ShowLog; @@ -453,16 +448,8 @@ private: void DrawMessages (int layer, int bottom); void DrawConsistancy () const; void DrawWaiting () const; - void SetDrawSize(int reltop, int hres, int vres); TObjPtr Messages[NUM_HUDMSGLAYERS]; - - int BaseRelTop; - int BaseSBarHorizontalResolution; - int BaseSBarVerticalResolution; - int BaseHUDHorizontalResolution; - int BaseHUDVerticalResolution; - }; extern DBaseStatusBar *StatusBar; diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index f2a4d92ce3..82f9372018 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -92,6 +92,7 @@ EXTERN_CVAR(Bool, ui_screenborder_classic_scaling) CVAR(Int, hud_scale, 0, CVAR_ARCHIVE); CVAR(Bool, log_vgafont, false, CVAR_ARCHIVE) +CVAR(Bool, hud_oldscale, true, CVAR_ARCHIVE) DBaseStatusBar *StatusBar; @@ -103,6 +104,18 @@ CVAR (Flag, pf_poison, paletteflash, PF_POISON) CVAR (Flag, pf_ice, paletteflash, PF_ICE) CVAR (Flag, pf_hazard, paletteflash, PF_HAZARD) +CUSTOM_CVARD(Float, hud_scalefactor, 1, CVAR_ARCHIVE, "changes the hud scale") +{ + if (self < 0.36f) self = 0.36f; + else if (self > 1) self = 1; + else if (StatusBar) + { + StatusBar->SetScale(); + setsizeneeded = true; + } +} + + // Stretch status bar to full screen width? CUSTOM_CVAR (Int, st_scale, 0, CVAR_ARCHIVE) { @@ -400,74 +413,6 @@ DBaseStatusBar::DBaseStatusBar () CreateAltHUD(); } -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); -} - -static void ST_CalcCleanFacs(int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany) -{ - float ratio; - int cwidth; - int cheight; - int cx1, cy1, cx2, cy2; - - ratio = ActiveRatio(realwidth, realheight); - if (AspectTallerThanWide(ratio)) - { - cwidth = realwidth; - cheight = realheight * AspectMultiplier(ratio) / 48; - } - else - { - cwidth = realwidth * AspectMultiplier(ratio) / 48; - cheight = realheight; - } - // Use whichever pair of cwidth/cheight or width/height that produces less difference - // between CleanXfac and CleanYfac. - cx1 = MAX(cwidth / designwidth, 1); - cy1 = MAX(cheight / designheight, 1); - cx2 = MAX(realwidth / designwidth, 1); - cy2 = MAX(realheight / designheight, 1); - if (abs(cx1 - cy1) <= abs(cx2 - cy2) || MAX(cx1, cx2) >= 4) - { // e.g. 640x360 looks better with this. - *cleanx = cx1; - *cleany = cy1; - } - else - { // e.g. 720x480 looks better with this. - *cleanx = cx2; - *cleany = cy2; - } - - if (*cleanx < *cleany) - *cleany = *cleanx; - else - *cleanx = *cleany; -} - -void DBaseStatusBar::SetDrawSize(int reltop, int hres, int vres) -{ - ValidateResolution(hres, vres); - - RelTop = reltop; - HorizontalResolution = hres; - VerticalResolution = vres; - int x, y; - ST_CalcCleanFacs(hres, vres, twod->GetWidth(), twod->GetHeight(), &x, &y); - defaultScale = { (double)x, (double)y }; - - SetScale(); // recalculate positioning info. -} - - //--------------------------------------------------------------------------- // // PROP Destroy @@ -500,6 +445,12 @@ void DBaseStatusBar::OnDestroy () void DBaseStatusBar::SetScale () { + if (!hud_oldscale) + { + Super::SetScale(); + return; + } + ValidateResolution(HorizontalResolution, VerticalResolution); int w = twod->GetWidth(); @@ -561,6 +512,11 @@ void DBaseStatusBar::SetScale () DVector2 DBaseStatusBar::GetHUDScale() const { + if (!hud_oldscale) + { + return Super::GetHUDScale(); + } + int scale; if (hud_scale < 0 || ForcedScale) // a negative value is the equivalent to the old boolean hud_scale. This can yield different values for x and y for higher resolutions. { @@ -579,34 +535,6 @@ DVector2 DBaseStatusBar::GetHUDScale() const return{ double(realscale), double(realscale * (hud_aspectscale ? 1.2 : 1.)) }; } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::BeginStatusBar(int resW, int resH, int relTop, bool forceScaled) -{ - SetDrawSize(relTop < 0? BaseRelTop : relTop, resW < 0? BaseSBarHorizontalResolution : resW, resH < 0? BaseSBarVerticalResolution : resH); - ForcedScale = forceScaled; - fullscreenOffsets = false; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::BeginHUD(int resW, int resH, double Alpha, bool forcescaled) -{ - SetDrawSize(RelTop, resW < 0? BaseHUDHorizontalResolution : resW, resH < 0? BaseHUDVerticalResolution : resH); - this->Alpha = Alpha; - ForcedScale = forcescaled; - CompleteBorder = false; - fullscreenOffsets = true; -} - //============================================================================ // // automap HUD common drawer