From 4f7ad5b130a6d2e7f32b8eb8d30da830a0db251d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 17 Mar 2019 12:06:09 +0100 Subject: [PATCH] - make the clean scaling system more consistent. Now, all menus will use the same scale, i.e. it only depends on the screen width and a base size of 640. This nearly universally yields better results than trying to make a 320x200 screen fit. The only exceptions to this are the intermission screens and the level summary. These, unlike the menu need to try to make a 320x200 screen fit, but without all the hackery that was present to adjust the menu display. Note that since this affects globally visible script variables, both the intermission and summary drawers will not use their own set but instead temporarily override the global setting as long as they run their own code. Changing the use of variables here might cause much worse problems with menu code so it wasn't attempted --- src/intermission/intermission.cpp | 6 +++ src/v_video.cpp | 65 +++++-------------------------- src/v_video.h | 31 +++++++++++++++ src/wi_stuff.cpp | 3 ++ 4 files changed, 49 insertions(+), 56 deletions(-) diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index f1dd8b9a0..cc2482220 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -847,6 +847,7 @@ void DIntermissionController::OnDestroy () void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t state) { + ScaleOverrider s; if (DIntermissionController::CurrentIntermission != NULL) { DIntermissionController::CurrentIntermission->Destroy(); @@ -892,6 +893,7 @@ void F_StartIntermission(FName seq, uint8_t state) bool F_Responder (event_t* ev) { + ScaleOverrider s; if (DIntermissionController::CurrentIntermission != NULL) { return DIntermissionController::CurrentIntermission->Responder(ev); @@ -907,6 +909,7 @@ bool F_Responder (event_t* ev) void F_Ticker () { + ScaleOverrider s; if (DIntermissionController::CurrentIntermission != NULL) { DIntermissionController::CurrentIntermission->Ticker(); @@ -921,6 +924,7 @@ void F_Ticker () void F_Drawer () { + ScaleOverrider s; if (DIntermissionController::CurrentIntermission != NULL) { DIntermissionController::CurrentIntermission->Drawer(); @@ -936,6 +940,7 @@ void F_Drawer () void F_EndFinale () { + ScaleOverrider s; if (DIntermissionController::CurrentIntermission != NULL) { DIntermissionController::CurrentIntermission->Destroy(); @@ -951,6 +956,7 @@ void F_EndFinale () void F_AdvanceIntermission() { + ScaleOverrider s; if (DIntermissionController::CurrentIntermission != NULL) { DIntermissionController::CurrentIntermission->mAdvance = true; diff --git a/src/v_video.cpp b/src/v_video.cpp index 61a9ceb7b..d82a24704 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -539,13 +539,10 @@ CCMD(clean) void V_UpdateModeSize (int width, int height) -{ - int cx1, cx2; - V_CalcCleanFacs(320, 200, width, height, &CleanXfac, &CleanYfac, &cx1, &cx2); - - CleanWidth = width / CleanXfac; - CleanHeight = height / CleanYfac; - assert(CleanWidth >= 320 && CleanHeight >= 200); +{ + // This calculates the menu scale. + // The optimal scale will always be to fit a virtual 640 pixel wide display onto the screen. + // Exceptions are made for a few ranges where the available virtual width is > 480. int w = screen->GetWidth(); int factor; @@ -554,9 +551,9 @@ void V_UpdateModeSize (int width, int height) else if (w >= 1600 && w < 1920) factor = 3; else factor = w / 640; - CleanXfac_1 = CleanYfac_1 = factor; - CleanWidth_1 = width / CleanXfac_1; - CleanHeight_1 = height / CleanYfac_1; + CleanXfac = CleanYfac = CleanXfac_1 = CleanYfac_1 = factor; + CleanWidth = CleanWidth_1 = width / CleanXfac_1; + CleanHeight = CleanHeight_1 = height / CleanYfac_1; DisplayWidth = width; DisplayHeight = height; @@ -581,52 +578,8 @@ void V_OutputResized (int width, int height) void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2) { - float ratio; - int cwidth; - int cheight; - int cx1, cy1, cx2, cy2; - - // For larger screems always use at least a 16:9 ratio for clean factor calculation, even if the actual ratio is narrower. - if (realwidth > 1280 && (double)realwidth / realheight < 16./9) - { - realheight = realwidth * 9 / 16; - } - - 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; - - if (_cx1 != NULL) *_cx1 = cx1; - if (_cx2 != NULL) *_cx2 = cx2; + if (designheight < 240 && realheight >= 480) designheight = 240; + *cleanx = *cleany = std::min(realwidth / designwidth, realheight / designheight); } bool IVideo::SetResolution () diff --git a/src/v_video.h b/src/v_video.h index 06295b1a8..7f35f3322 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -628,4 +628,35 @@ inline int active_con_scale() } +class ScaleOverrider +{ + int savedxfac, savedyfac, savedwidth, savedheight; + +public: + // This is to allow certain elements to use an optimal fullscreen scale which for the menu would be too large. + // The old code contained far too much mess to compensate for the menus which negatively affected everything else. + // However, for compatibility reasons the currently used variables cannot be changed so they have to be overridden temporarily. + // This class provides a safe interface for this because it ensures that the values get restored afterward. + // Currently, the intermission and the level summary screen use this. + ScaleOverrider() + { + savedxfac = CleanXfac; + savedyfac = CleanYfac; + savedwidth = CleanWidth; + savedheight = CleanHeight; + V_CalcCleanFacs(320, 200, screen->GetWidth(), screen->GetHeight(), &CleanXfac, &CleanYfac); + CleanWidth = screen->GetWidth() / CleanXfac; + CleanHeight = screen->GetHeight() / CleanYfac; + } + + ~ScaleOverrider() + { + CleanXfac = savedxfac; + CleanYfac = savedyfac; + CleanWidth = savedwidth; + CleanHeight = savedheight; + } +}; + + #endif // __V_VIDEO_H__ diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index dedda4602..1e319a146 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -701,6 +701,7 @@ void WI_Ticker() { if (WI_Screen) { + ScaleOverrider s; IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Ticker) { VMValue self = WI_Screen; @@ -720,6 +721,7 @@ void WI_Drawer() { if (WI_Screen) { + ScaleOverrider s; IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Drawer) { VMValue self = WI_Screen; @@ -767,6 +769,7 @@ void WI_Start(wbstartstruct_t *wbstartstruct) SN_StopAllSequences(Level); } WI_Screen = cls->CreateNew(); + ScaleOverrider s; IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Start) { VMValue val[2] = { WI_Screen, wbstartstruct };