Scale "Menu" GUIs (incl. PDA + fullscreen vids) to 4:3

So stuff doesn't look so distorted in widescreen resolutions.
Implies that there are black bars on the left/right then..

Can be disabled with "r_scaleMenusTo43 0"

Does *not* affect the HUD (incl. crosshair) - scaling it automagically
would be very hard (or impossible), because it doesn't only render
the crosshair, healthpoints etc, but also fullscreen effects like the
screen turning red when the player is hit - and fullscreen effects
would look very shitty if they didn't cover the whole screen but had
"empty" bars on left/right.

(Mostly) fixes #188 and #189
This commit is contained in:
Daniel Gibson 2018-10-28 03:34:01 +01:00
parent 7a8f0e9fdb
commit e41bf2b147
6 changed files with 142 additions and 11 deletions

View file

@ -223,6 +223,9 @@ idCVar r_materialOverride( "r_materialOverride", "", CVAR_RENDERER, "overrides a
idCVar r_debugRenderToTexture( "r_debugRenderToTexture", "0", CVAR_RENDERER | CVAR_INTEGER, "" );
// DG: let users disable the "scale menus to 4:3" hack
idCVar r_scaleMenusTo43( "r_scaleMenusTo43", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Scale menus, fullscreen videos and PDA to 4:3 aspect ratio" );
// define qgl functions
#define QGLPROC(name, rettype, args) rettype (APIENTRYP q##name) args;
#include "renderer/qgl_proc.h"

View file

@ -135,6 +135,10 @@ void idDeviceContext::Init() {
mat.Identity();
origin.Zero();
initialized = true;
// DG: this is used for the "make sure menus are rendered as 4:3" hack
fixScaleForMenu.Set(1, 1);
fixOffsetForMenu.Set(0, 0);
}
void idDeviceContext::Shutdown() {
@ -254,8 +258,67 @@ bool idDeviceContext::ClippedCoords(float *x, float *y, float *w, float *h, floa
return (*w == 0 || *h == 0) ? true : false;
}
// DG: this is used for the "make sure menus are rendered as 4:3" hack
void idDeviceContext::SetMenuScaleFix(bool enable) {
if(enable) {
float w = renderSystem->GetScreenWidth();
float h = renderSystem->GetScreenHeight();
float aspectRatio = w/h;
static const float virtualAspectRatio = float(VIRTUAL_WIDTH)/float(VIRTUAL_HEIGHT); // 4:3
if(aspectRatio > 1.4f) {
// widescreen (4:3 is 1.333 3:2 is 1.5, 16:10 is 1.6, 16:9 is 1.7778)
// => we need to scale and offset X
// All the coordinates here assume 640x480 (VIRTUAL_WIDTH x VIRTUAL_HEIGHT)
// screensize, so to fit a 4:3 menu into 640x480 stretched to a widescreen,
// we need do decrease the width to something smaller than 640 and center
// the result with an offset
float scaleX = virtualAspectRatio/aspectRatio;
float offsetX = (1.0f-scaleX)*(VIRTUAL_WIDTH*0.5f); // (640 - scale*640)/2
fixScaleForMenu.Set(scaleX, 1);
fixOffsetForMenu.Set(offsetX, 0);
} else if(aspectRatio < 1.24f) {
// portrait-mode, "thinner" than 5:4 (which is 1.25)
// => we need to scale and offset Y
// it's analogue to the other case, but inverted and with height and Y
float scaleY = aspectRatio/virtualAspectRatio;
float offsetY = (1.0f - scaleY)*(VIRTUAL_HEIGHT*0.5f); // (480 - scale*480)/2
fixScaleForMenu.Set(1, scaleY);
fixOffsetForMenu.Set(0, offsetY);
}
} else {
fixScaleForMenu.Set(1, 1);
fixOffsetForMenu.Set(0, 0);
}
}
void idDeviceContext::AdjustCoords(float *x, float *y, float *w, float *h) {
if (x) {
*x *= xScale;
*x *= fixScaleForMenu.x; // DG: for "render menus as 4:3" hack
*x += fixOffsetForMenu.x;
}
if (y) {
*y *= yScale;
*y *= fixScaleForMenu.y; // DG: for "render menus as 4:3" hack
*y += fixOffsetForMenu.y;
}
if (w) {
*w *= xScale;
*w *= fixScaleForMenu.x; // DG: for "render menus as 4:3" hack
}
if (h) {
*h *= yScale;
*h *= fixScaleForMenu.y; // DG: for "render menus as 4:3" hack
}
}
// DG: same as AdjustCoords, but ignore fixupMenus because for the cursor that must be handled seperately
void idDeviceContext::AdjustCursorCoords(float *x, float *y, float *w, float *h) {
if (x) {
*x *= xScale;
}
@ -637,8 +700,16 @@ void idDeviceContext::DrawCursor(float *x, float *y, float size) {
}
renderSystem->SetColor(colorWhite);
AdjustCoords(x, y, &size, &size);
DrawStretchPic( *x, *y, size, size, 0, 0, 1, 1, cursorImages[cursor]);
// DG: I use this instead of plain AdjustCursorCoords and the following lines
// to scale menus and other fullscreen GUIs to 4:3 aspect ratio
AdjustCursorCoords(x, y, &size, &size);
float sizeW = size * fixScaleForMenu.x;
float sizeH = size * fixScaleForMenu.y;
float fixedX = *x * fixScaleForMenu.x + fixOffsetForMenu.x;
float fixedY = *y * fixScaleForMenu.y + fixOffsetForMenu.y;
DrawStretchPic(fixedX, fixedY, sizeW, sizeH, 0, 0, 1, 1, cursorImages[cursor]);
}
/*
=======================================================================================================================

View file

@ -82,6 +82,7 @@ public:
void SetCursor(int n);
void AdjustCoords(float *x, float *y, float *w, float *h);
void AdjustCursorCoords(float *x, float *y, float *w, float *h); // DG: added for "render menus as 4:3" hack
bool ClippedCoords(float *x, float *y, float *w, float *h);
bool ClippedCoords(float *x, float *y, float *w, float *h, float *s1, float *t1, float *s2, float *t2);
@ -98,6 +99,12 @@ public:
void DrawEditCursor(float x, float y, float scale);
// DG: this is used for the "make sure menus are rendered as 4:3" hack
void SetMenuScaleFix(bool enable);
bool IsMenuScaleFixActive() const {
return fixOffsetForMenu.x != 0.0f || fixOffsetForMenu.y != 0.0f;
}
enum {
CURSOR_ARROW,
CURSOR_HAND,
@ -165,6 +172,10 @@ private:
bool initialized;
bool mbcs;
// DG: this is used for the "make sure menus are rendered as 4:3" hack
idVec2 fixScaleForMenu;
idVec2 fixOffsetForMenu;
};
#endif /* !__DEVICECONTEXT_H__ */

View file

@ -140,7 +140,7 @@ void idRenderWindow::Render( int time ) {
void idRenderWindow::Draw(int time, float x, float y) {
void idRenderWindow::Draw(int time, float x_, float y_) {
PreRender();
Render(time);
@ -154,10 +154,20 @@ void idRenderWindow::Draw(int time, float x, float y) {
refdef.shaderParms[2] = 1;
refdef.shaderParms[3] = 1;
refdef.x = drawRect.x;
refdef.y = drawRect.y;
refdef.width = drawRect.w;
refdef.height = drawRect.h;
// DG: for scaling menus to 4:3 (like that spinning mars globe in the main menu)
float x = drawRect.x;
float y = drawRect.y;
float w = drawRect.w;
float h = drawRect.h;
if(dc->IsMenuScaleFixActive()) {
dc->AdjustCoords(&x, &y, &w, &h);
}
refdef.x = x;
refdef.y = y;
refdef.width = w;
refdef.height = h;
// DG end
refdef.fov_x = 90;
refdef.fov_y = 2 * atan((float)drawRect.h / drawRect.w) * idMath::M_RAD2DEG;

View file

@ -37,6 +37,7 @@ If you have questions concerning this license or the applicable additional terms
#include "ui/UserInterfaceLocal.h"
extern idCVar r_skipGuiShaders; // 1 = don't render any gui elements on surfaces
extern idCVar r_scaleMenusTo43; // DG: for the "scale menus to 4:3" hack
idUserInterfaceManagerLocal uiManagerLocal;
idUserInterfaceManager * uiManager = &uiManagerLocal;
@ -349,11 +350,30 @@ const char *idUserInterfaceLocal::HandleEvent( const sysEvent_t *event, int _tim
float w = renderSystem->GetScreenWidth();
float h = renderSystem->GetScreenHeight();
if( w <= 0.0f || h <= 0.0f ) {
w = 640.0f;
h = 480.0f;
w = VIRTUAL_WIDTH;
h = VIRTUAL_HEIGHT;
}
cursorX += event->evValue * (640.0f/w);
cursorY += event->evValue2 * (480.0f/h);
if(r_scaleMenusTo43.GetBool()) {
// in case we're scaling menus to 4:3, we need to take that into account
// when scaling the mouse events.
// no, we can't just call uiManagerLocal.dc.GetFixScaleForMenu() or sth like that,
// because when we're here dc.SetMenuScaleFix(true) is not active and it'd just return (1, 1)!
float aspectRatio = w/h;
static const float virtualAspectRatio = float(VIRTUAL_WIDTH)/float(VIRTUAL_HEIGHT); // 4:3
if(aspectRatio > 1.4f) {
// widescreen (4:3 is 1.333 3:2 is 1.5, 16:10 is 1.6, 16:9 is 1.7778)
// => we need to modify cursorX scaling, by modifying w
w *= virtualAspectRatio/aspectRatio;
} else if(aspectRatio < 1.24f) {
// portrait-mode, "thinner" than 5:4 (which is 1.25)
// => we need to scale cursorY via h
h *= aspectRatio/virtualAspectRatio;
}
}
cursorX += event->evValue * (float(VIRTUAL_WIDTH)/w);
cursorY += event->evValue2 * (float(VIRTUAL_HEIGHT)/h);
} else {
// not a fullscreen GUI but some ingame thing - no scaling needed
cursorX += event->evValue;

View file

@ -56,6 +56,7 @@ idCVar idWindow::gui_debug( "gui_debug", "0", CVAR_GUI | CVAR_BOOL, "" );
idCVar idWindow::gui_edit( "gui_edit", "0", CVAR_GUI | CVAR_BOOL, "" );
extern idCVar r_skipGuiShaders; // 1 = don't render any gui elements on surfaces
extern idCVar r_scaleMenusTo43;
// made RegisterVars a member of idWindow
const idRegEntry idWindow::RegisterVars[] = {
@ -1207,6 +1208,14 @@ void idWindow::Redraw(float x, float y) {
return;
}
// DG: allow scaling menus to 4:3
bool fixupFor43 = false;
if ( (flags & (WIN_MENUGUI | WIN_DESKTOP)) == (WIN_MENUGUI | WIN_DESKTOP)
&& r_scaleMenusTo43.GetBool() ) {
fixupFor43 = true;
dc->SetMenuScaleFix(true);
}
if ( flags & WIN_SHOWTIME ) {
dc->DrawText(va(" %0.1f seconds\n%s", (float)(time - timeLine) / 1000, gui->State().GetString("name")), 0.35f, 0, dc->colorWhite, idRectangle(100, 0, 80, 80), false);
}
@ -1219,6 +1228,9 @@ void idWindow::Redraw(float x, float y) {
}
if (!visible) {
if (fixupFor43) { // DG: gotta reset that before returning this function
dc->SetMenuScaleFix(false);
}
return;
}
@ -1287,6 +1299,10 @@ void idWindow::Redraw(float x, float y) {
dc->EnableClipping(true);
}
if (fixupFor43) { // DG: gotta reset that before returning this function
dc->SetMenuScaleFix(false);
}
drawRect.Offset(-x, -y);
clientRect.Offset(-x, -y);
textRect.Offset(-x, -y);