diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index 53fca85d0..e6bdcee92 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -660,7 +660,10 @@ xx(Static) xx(Staticconst) xx(DeathmatchStatusScreen) xx(CoopStatusScreen) +xx(DoomStatusScreen) xx(RavenStatusScreen) +xx(DoomStatusScreenSized) +xx(RavenStatusScreenSized) xx(StatusbarWidget) xx(StatusbarHead) xx(StatusbarCondition) @@ -1076,3 +1079,10 @@ xx(NewPlayerMenu) xx(AltHud) xx(GameScreen) +// summary +xx(cwidth) +xx(cheight) +xx(wrapwidth) +xx(scalefactorx) +xx(scalefactory) +xx(scalemode) diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index fca44fd17..c0c666eb2 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -61,6 +61,7 @@ CVAR(Bool, wi_percents, true, CVAR_ARCHIVE) CVAR(Bool, wi_showtotaltime, true, CVAR_ARCHIVE) CVAR(Bool, wi_noautostartmap, false, CVAR_USERINFO | CVAR_ARCHIVE) CVAR(Int, wi_autoadvance, 0, CVAR_SERVERINFO) +CVAR(Bool, wi_cleantextscale, true, CVAR_ARCHIVE) EXTERN_CVAR(Bool, inter_classic_scaling) // States for the intermission @@ -769,12 +770,35 @@ void WI_Start(wbstartstruct_t *wbstartstruct) } WI_Screen = cls->CreateNew(); + + ScaleOverrider s(twod); IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Start) { VMValue val[2] = { WI_Screen, wbstartstruct }; VMCall(func, val, 2, nullptr, 0); } + + if (!wi_cleantextscale) + { + // Only modify the original single player screens. Everything else must set itself up as intended + if (cls->TypeName == NAME_DoomStatusScreen || cls->TypeName == NAME_RavenStatusScreen) + { + int w = screen->GetWidth(); + int h = screen->GetHeight(); + float ratio = ActiveRatio(w, h); + int pixw = int(320 * (ratio * 0.75)); + if (pixw > 336) pixw -= 16; // leave a bit of space at the sides. + + WI_Screen->IntVar(NAME_cwidth) = 320; + WI_Screen->IntVar(NAME_cheight) = 200; + WI_Screen->IntVar(NAME_scalemode) = FSMode_ScaleToFit43; + WI_Screen->IntVar(NAME_scalefactorx) = 1; + WI_Screen->IntVar(NAME_scalefactory) = 1; + WI_Screen->IntVar(NAME_wrapwidth) = pixw; + } + } + GC::AddSoftRoot(WI_Screen); } diff --git a/wadsrc/static/zscript/ui/statscreen/statscreen.zs b/wadsrc/static/zscript/ui/statscreen/statscreen.zs index c1dcca7d5..d118111be 100644 --- a/wadsrc/static/zscript/ui/statscreen/statscreen.zs +++ b/wadsrc/static/zscript/ui/statscreen/statscreen.zs @@ -39,7 +39,6 @@ struct PatchInfo play version("2.5") }; -// Will be made a class later, but for now needs to mirror the internal version. class StatusScreen abstract play version("2.5") { enum EValues @@ -129,6 +128,11 @@ class StatusScreen abstract play version("2.5") int player_deaths[MAXPLAYERS]; int sp_state; + + int cWidth, cHeight; // size of the canvas + int scalemode; + int wrapwidth; // size used to word wrap level names + int scaleFactorX, scaleFactorY; //==================================================================== @@ -140,9 +144,34 @@ class StatusScreen abstract play version("2.5") int DrawCharPatch(Font fnt, int charcode, int x, int y, int translation = Font.CR_UNTRANSLATED, bool nomove = false) { int width = fnt.GetCharWidth(charcode); - screen.DrawChar(fnt, translation, x, y, charcode, nomove ? DTA_CleanNoMove : DTA_Clean, true); + if (scalemode == -1) screen.DrawChar(fnt, translation, x, y, charcode, nomove ? DTA_CleanNoMove : DTA_Clean, true); + else screen.DrawChar(fnt, translation, x, y, charcode, DTA_FullscreenScale, scalemode, DTA_VirtualWidth, cwidth, DTA_VirtualHeight, cheight); return x - width; } + + //==================================================================== + // + // + // + //==================================================================== + + void DrawTexture(TextureID tex, double x, double y, bool nomove = false) + { + if (scalemode == -1) screen.DrawTexture(tex, true, x, y, nomove ? DTA_CleanNoMove : DTA_Clean, true); + else screen.DrawTexture(tex, true, x, y, DTA_FullscreenScale, scalemode, DTA_VirtualWidth, cwidth, DTA_VirtualHeight, cheight); + } + + //==================================================================== + // + // + // + //==================================================================== + + void DrawText(Font fnt, int color, double x, double y, String str, bool nomove = false, bool shadow = false) + { + if (scalemode == -1) screen.DrawText(fnt, color, x, y, str, nomove ? DTA_CleanNoMove : DTA_Clean, true, DTA_Shadow, shadow); + else screen.DrawText(fnt, color, x, y, str, DTA_FullscreenScale, scalemode, DTA_VirtualWidth, cwidth, DTA_VirtualHeight, cheight, DTA_Shadow, shadow); + } //==================================================================== // @@ -159,25 +188,25 @@ class StatusScreen abstract play version("2.5") if (tex.isValid()) { let size = TexMan.GetScaledSize(tex); - screen.DrawTexture(tex, true, (screen.GetWidth() - size.X * CleanXfac) /2, y, DTA_CleanNoMove, true); + DrawTexture(tex, (cwidth - size.X * scaleFactorX) /2, y, true); if (size.Y > 50) { // Fix for Deus Vult II and similar wads that decide to make these hugely tall // patches with vast amounts of empty space at the bottom. size.Y = TexMan.CheckRealHeight(tex); } - return y + int(Size.Y) * CleanYfac; + return y + int(Size.Y) * scaleFactorY; } else if (levelname.Length() > 0) { int h = 0; - int lumph = mapname.mFont.GetHeight() * CleanYfac; + int lumph = mapname.mFont.GetHeight() * scaleFactorY; - BrokenLines lines = mapname.mFont.BreakLines(levelname, screen.GetWidth() / CleanXfac); + BrokenLines lines = mapname.mFont.BreakLines(levelname, wrapwidth / scaleFactorX); int count = lines.Count(); for (int i = 0; i < count; i++) { - screen.DrawText(mapname.mFont, mapname.mColor, (screen.GetWidth() - lines.StringWidth(i) * CleanXfac) / 2, y + h, lines.StringAt(i), DTA_CleanNoMove, true); + DrawText(mapname.mFont, mapname.mColor, (cwidth - lines.StringWidth(i) * scaleFactorX) / 2, y + h, lines.StringAt(i), true); h += lumph; } return y + h; @@ -187,7 +216,7 @@ class StatusScreen abstract play version("2.5") //==================================================================== // - // Draws a level author's name with the big font + // Draws a level author's name with the given font // //==================================================================== @@ -196,14 +225,14 @@ class StatusScreen abstract play version("2.5") if (levelname.Length() > 0) { int h = 0; - int lumph = author.mFont.GetHeight() * CleanYfac; + int lumph = author.mFont.GetHeight() * scaleFactorY; - BrokenLines lines = author.mFont.BreakLines(levelname, screen.GetWidth() / CleanXfac); + BrokenLines lines = author.mFont.BreakLines(levelname, wrapwidth / scaleFactorX); int count = lines.Count(); for (int i = 0; i < count; i++) { - screen.DrawText(author.mFont, author.mColor, (screen.GetWidth() - lines.StringWidth(i) * CleanXfac) / 2, y + h, lines.StringAt(i), DTA_CleanNoMove, true); + DrawText(author.mFont, author.mColor, (cwidth - lines.StringWidth(i) * scaleFactorX) / 2, y + h, lines.StringAt(i), true); h += lumph; } return y + h; @@ -235,22 +264,21 @@ class StatusScreen abstract play version("2.5") int DrawPatchOrText(int y, PatchInfo pinfo, TextureID patch, String stringname) { String string = Stringtable.Localize(stringname); - int midx = screen.GetWidth() / 2; + int midx = cwidth / 2; if (TexMan.OkForLocalization(patch, stringname)) { let size = TexMan.GetScaledSize(patch); - screen.DrawTexture(patch, true, midx - size.X * CleanXfac/2, y, DTA_CleanNoMove, true); - return y + int(size.Y * CleanYfac); + DrawTexture(patch, midx - size.X * scaleFactorX/2, y, true); + return y + int(size.Y * scaleFactorY); } else { - screen.DrawText(pinfo.mFont, pinfo.mColor, midx - pinfo.mFont.StringWidth(string) * CleanXfac/2, y, string, DTA_CleanNoMove, true); - return y + pinfo.mFont.GetHeight() * CleanYfac; + DrawText(pinfo.mFont, pinfo.mColor, midx - pinfo.mFont.StringWidth(string) * scaleFactorX/2, y, string, true); + return y + pinfo.mFont.GetHeight() * scaleFactorY; } } - //==================================================================== // // Draws " Finished!" @@ -263,7 +291,7 @@ class StatusScreen abstract play version("2.5") virtual int drawLF () { bool ispatch = wbs.LName0.isValid(); - int oldy = TITLEY * CleanYfac; + int oldy = TITLEY * scaleFactorY; int h; if (!ispatch) @@ -271,7 +299,7 @@ class StatusScreen abstract play version("2.5") let asc = mapname.mFont.GetMaxAscender(lnametexts[1]); if (asc > TITLEY - 2) { - oldy = (asc+2) * CleanYfac; + oldy = (asc+2) * scaleFactorY; } } @@ -285,7 +313,7 @@ class StatusScreen abstract play version("2.5") if (authortexts[0].length() == 0) { int h1 = BigFont.GetHeight() - BigFont.GetDisplacement(); - int h2 = (y - oldy) / CleanYfac / 4; + int h2 = (y - oldy) / scaleFactorY / 4; disp = min(h1, h2); if (!TexMan.OkForLocalization(finishedPatch, "$WI_FINISHED")) @@ -297,15 +325,15 @@ class StatusScreen abstract play version("2.5") { disp += author.mFont.GetMaxAscender(authortexts[0]); } - y += disp * CleanYfac; + y += disp * scaleFactorY; } y = DrawAuthor(y, authortexts[0]); // draw "Finished!" - int statsy = multiplayer? NG_STATSY : SP_STATSY * CleanYFac; - if (y < (statsy - finished.mFont.GetHeight()*3/4) * CleanYfac) + int statsy = multiplayer? NG_STATSY : SP_STATSY * scaleFactorY; + if (y < (statsy - finished.mFont.GetHeight()*3/4) * scaleFactorY) { // don't draw 'finished' if the level name is too tall y = DrawPatchOrText(y, finished, finishedPatch, "$WI_FINISHED"); @@ -313,7 +341,6 @@ class StatusScreen abstract play version("2.5") return y; } - //==================================================================== // // Draws "Entering " @@ -326,14 +353,14 @@ class StatusScreen abstract play version("2.5") virtual void drawEL () { bool ispatch = TexMan.OkForLocalization(enteringPatch, "$WI_ENTERING"); - int oldy = TITLEY * CleanYfac; + int oldy = TITLEY * scaleFactorY; if (!ispatch) { let asc = entering.mFont.GetMaxAscender("$WI_ENTERING"); if (asc > TITLEY - 2) { - oldy = (asc+2) * CleanYfac; + oldy = (asc+2) * scaleFactorY; } } @@ -352,7 +379,7 @@ class StatusScreen abstract play version("2.5") { disp += mapname.mFont.GetMaxAscender(lnametexts[1]); } - y += disp * CleanYfac; + y += disp * scaleFactorY; } y = DrawName(y, wbs.LName1, lnametexts[1]); @@ -360,14 +387,13 @@ class StatusScreen abstract play version("2.5") if (wbs.LName1.isValid() && authortexts[1].length() > 0) { // Consdider the ascender height of the following text. - y += author.mFont.GetMaxAscender(authortexts[1]) * CleanYfac; + y += author.mFont.GetMaxAscender(authortexts[1]) * scaleFactorY; } DrawAuthor(y, authortexts[1]); } - //==================================================================== // // Draws a number. @@ -383,9 +409,9 @@ class StatusScreen abstract play version("2.5") String text; int len; - if (nomove) + if (nomove && scalemode == -1) { - fntwidth *= CleanXfac; + fntwidth *= scaleFactorX; } text = String.Format("%d", n); len = text.Length(); @@ -435,35 +461,76 @@ class StatusScreen abstract play version("2.5") if (wi_percents) { - if (nomove) + if (nomove && scalemode == -1) { - x -= fnt.StringWidth("%") * CleanXfac; + x -= fnt.StringWidth("%") * scaleFactorX; } else { x -= fnt.StringWidth("%"); } - screen.DrawText(fnt, color, x, y, "%", nomove? DTA_CleanNoMove : DTA_Clean, true); + DrawText(fnt, color, x, y, "%", nomove); if (nomove) { x -= 2*CleanXfac; } - drawNum(fnt, x, y, b == 0 ? 100 : p * 100 / b, -1, false, color); + drawNum(fnt, x, y, b == 0 ? 100 : p * 100 / b, -1, false, color, nomove); } else { if (show_total) { - x = drawNum(fnt, x, y, b, 2, false, color); + x = drawNum(fnt, x, y, b, 2, false, color, nomove); x -= fnt.StringWidth("/"); - screen.DrawText (fnt, color, x, y, "/", nomove? DTA_CleanNoMove : DTA_Clean, true); + DrawText (fnt, color, x, y, "/", nomove); } - drawNum (fnt, x, y, p, -1, false, color); + drawNum (fnt, x, y, p, -1, false, color, nomove); } } + + //==================================================================== + // + // Display level completion time and par, or "sucks" message if overflow. + // + //==================================================================== + + void drawTimeFont (Font printFont, int x, int y, int t, int color) + { + bool sucky; + + if (t < 0) + return; + + int hours = t / 3600; + t -= hours * 3600; + int minutes = t / 60; + t -= minutes * 60; + int seconds = t; + + // Why were these offsets hard coded? Half the WADs with custom patches + // I tested screwed up miserably in this function! + int num_spacing = printFont.GetCharWidth("3"); + int colon_spacing = printFont.GetCharWidth(":"); + + x = drawNum (printFont, x, y, seconds, 2, true, color) - 1; + DrawCharPatch (printFont, ":", x -= colon_spacing, y, color); + x = drawNum (printFont, x, y, minutes, 2, hours!=0, color); + if (hours) + { + DrawCharPatch (printFont, ":", x -= colon_spacing, y, color); + drawNum (printFont, x, y, hours, 2, false, color); + } + } + + void drawTime (int x, int y, int t, bool no_sucks=false) + { + drawTimeFont(IntermissionFont, x, y, t, Font.CR_UNTRANSLATED); + } + //==================================================================== // + // the 'scaled' drawers are for the multiplayer scoreboard // //==================================================================== @@ -531,46 +598,6 @@ class StatusScreen abstract play version("2.5") drawTextScaled(fnt, x - fnt.StringWidth(s) * scale, y, s, scale, color); } - //==================================================================== - // - // Display level completion time and par, or "sucks" message if overflow. - // - //==================================================================== - - void drawTimeFont (Font printFont, int x, int y, int t, int color) - { - bool sucky; - - if (t < 0) - return; - - int hours = t / 3600; - t -= hours * 3600; - int minutes = t / 60; - t -= minutes * 60; - int seconds = t; - - // Why were these offsets hard coded? Half the WADs with custom patches - // I tested screwed up miserably in this function! - int num_spacing = printFont.GetCharWidth("3"); - int colon_spacing = printFont.GetCharWidth(":"); - - x = drawNum (printFont, x, y, seconds, 2, true, color) - 1; - DrawCharPatch (printFont, ":", x -= colon_spacing, y, color); - x = drawNum (printFont, x, y, minutes, 2, hours!=0, color); - if (hours) - { - DrawCharPatch (printFont, ":", x -= colon_spacing, y, color); - drawNum (printFont, x, y, hours, 2, false, color); - } - } - - void drawTime (int x, int y, int t, bool no_sucks=false) - { - drawTimeFont(IntermissionFont, x, y, t, Font.CR_UNTRANSLATED); - } - - //==================================================================== // // @@ -897,6 +924,12 @@ class StatusScreen abstract play version("2.5") bg = InterBackground.Create(wbs); noautostartmap = bg.LoadBackground(false); initStats(); + + wrapwidth = cwidth = screen.GetWidth(); + cheight = screen.GetHeight(); + scalemode = -1; + scaleFactorX = CleanXfac; + scaleFactorY = CleanYfac; } diff --git a/wadsrc/static/zscript/ui/statscreen/statscreen_sp.zs b/wadsrc/static/zscript/ui/statscreen/statscreen_sp.zs index ccce22dda..3ea43d345 100644 --- a/wadsrc/static/zscript/ui/statscreen/statscreen_sp.zs +++ b/wadsrc/static/zscript/ui/statscreen/statscreen_sp.zs @@ -158,11 +158,11 @@ class DoomStatusScreen : StatusScreen if (useGfx) { printFont = IntermissionFont; - screen.DrawTexture (Kills, true, statsx, SP_STATSY, DTA_Clean, true); - screen.DrawTexture (Items, true, statsx, SP_STATSY+lh, DTA_Clean, true); - screen.DrawTexture (P_secret, true, statsx, SP_STATSY+2*lh, DTA_Clean, true); - screen.DrawTexture (Timepic, true, SP_TIMEX, SP_TIMEY, DTA_Clean, true); - if (wbs.partime) screen.DrawTexture (Par, true, 160 + SP_TIMEX, SP_TIMEY, DTA_Clean, true); + DrawTexture (Kills, statsx, SP_STATSY); + DrawTexture (Items, statsx, SP_STATSY+lh); + DrawTexture (P_secret, statsx, SP_STATSY+2*lh); + DrawTexture (Timepic, SP_TIMEX, SP_TIMEY); + if (wbs.partime) DrawTexture (Par, 160 + SP_TIMEX, SP_TIMEY); } else { @@ -179,11 +179,11 @@ class DoomStatusScreen : StatusScreen } printFont = generic_ui? IntermissionFont : content.mFont; - screen.DrawText (textFont, tcolor, statsx, SP_STATSY, "$TXT_IMKILLS", DTA_Clean, true); - screen.DrawText (textFont, tcolor, statsx, SP_STATSY+lh, "$TXT_IMITEMS", DTA_Clean, true); - screen.DrawText (textFont, tcolor, statsx, SP_STATSY+2*lh, "$TXT_IMSECRETS", DTA_Clean, true); - screen.DrawText (textFont, tcolor, SP_TIMEX, SP_TIMEY, "$TXT_IMTIME", DTA_Clean, true); - if (wbs.partime) screen.DrawText (textFont, tcolor, 160 + SP_TIMEX, SP_TIMEY, "$TXT_IMPAR", DTA_Clean, true); + DrawText (textFont, tcolor, statsx, SP_STATSY, "$TXT_IMKILLS"); + DrawText (textFont, tcolor, statsx, SP_STATSY+lh, "$TXT_IMITEMS"); + DrawText (textFont, tcolor, statsx, SP_STATSY+2*lh, "$TXT_IMSECRETS"); + DrawText (textFont, tcolor, SP_TIMEX, SP_TIMEY, "$TXT_IMTIME"); + if (wbs.partime) screen.DrawText (textFont, tcolor, 160 + SP_TIMEX, SP_TIMEY, "$TXT_IMPAR"); } drawPercent (printFont, 320 - statsx, SP_STATSY, cnt_kills[0], wbs.maxkills, true, tcolor); @@ -201,11 +201,11 @@ class DoomStatusScreen : StatusScreen if (useGfx && TexMan.OkForLocalization(Sucks, "$TXT_IMSUCKS")) { let size = TexMan.GetScaledSize(Sucks); - screen.DrawTexture (Sucks, true, x - size.X, y - size.Y - 2, DTA_Clean, true); + DrawTexture (Sucks, x - size.X, y - size.Y - 2); } else { - screen.DrawText (textFont, tColor, x - printFont.StringWidth("$TXT_IMSUCKS"), y - printFont.GetHeight() - 2, "$TXT_IMSUCKS", DTA_Clean, true); + DrawText (textFont, tColor, x - printFont.StringWidth("$TXT_IMSUCKS"), y - printFont.GetHeight() - 2, "$TXT_IMSUCKS"); } } @@ -233,9 +233,9 @@ class RavenStatusScreen : DoomStatusScreen Font textFont = generic_ui? NewSmallFont : content.mFont; let tcolor = content.mColor; - screen.DrawText (textFont, tcolor, 50, 65, "$TXT_IMKILLS", DTA_Clean, true, DTA_Shadow, true); - screen.DrawText (textFont, tcolor, 50, 90, "$TXT_IMITEMS", DTA_Clean, true, DTA_Shadow, true); - screen.DrawText (textFont, tcolor, 50, 115, "$TXT_IMSECRETS", DTA_Clean, true, DTA_Shadow, true); + DrawText (textFont, tcolor, 50, 65, "$TXT_IMKILLS", shadow:true); + DrawText (textFont, tcolor, 50, 90, "$TXT_IMITEMS", shadow:true); + DrawText (textFont, tcolor, 50, 115, "$TXT_IMSECRETS", shadow:true); int countpos = gameinfo.gametype==GAME_Strife? 285:270; if (sp_state >= 2) @@ -252,7 +252,7 @@ class RavenStatusScreen : DoomStatusScreen } if (sp_state >= 8) { - screen.DrawText (textFont, tcolor, 85, 160, "$TXT_IMTIME", DTA_Clean, true, DTA_Shadow, true); + DrawText (textFont, tcolor, 85, 160, "$TXT_IMTIME", shadow:true); drawTimeFont (textFont, 249, 160, cnt_time, tcolor); if (wi_showtotaltime) {