Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions neo/d3xp/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,13 @@ void idPlayer::Spawn( void ) {
cursor = uiManager->FindGui( temp, true, gameLocal.isMultiplayer, gameLocal.isMultiplayer );
}
if ( cursor ) {
// DG: make it scale to 4:3 so crosshair looks properly round
// yes, like so many scaling-related things this is a bit hacky
// and note that this is special cased in StateChanged and you
// can *not* generally set windowDef properties like this.
cursor->SetStateBool("scaleto43", true);
cursor->StateChanged(gameLocal.time); // DG end

cursor->Activate( true, gameLocal.time );
}

Expand Down Expand Up @@ -2459,6 +2466,12 @@ void idPlayer::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( focusTime );
savefile->ReadObject( reinterpret_cast<idClass *&>( focusVehicle ) );
savefile->ReadUserInterface( cursor );
// DG: make it scale to 4:3 so crosshair looks properly round
// yes, like so many scaling-related things this is a bit hacky
// and note that this is special cased in StateChanged and you
// can *not* generally set windowDef properties like this.
cursor->SetStateBool("scaleto43", true);
cursor->StateChanged(gameLocal.time); // DG end

savefile->ReadInt( oldMouseX );
savefile->ReadInt( oldMouseY );
Expand Down
14 changes: 14 additions & 0 deletions neo/game/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,13 @@ void idPlayer::Spawn( void ) {
cursor = uiManager->FindGui( temp, true, gameLocal.isMultiplayer, gameLocal.isMultiplayer );
}
if ( cursor ) {
// DG: make it scale to 4:3 so crosshair looks properly round
// yes, like so many scaling-related things this is a bit hacky
// and note that this is special cased in StateChanged and you
// can *not* generally set windowDef properties like this.
cursor->SetStateBool("scaleto43", true);
cursor->StateChanged(gameLocal.time); // DG end

cursor->Activate( true, gameLocal.time );
}

Expand Down Expand Up @@ -2018,6 +2025,13 @@ void idPlayer::Restore( idRestoreGame *savefile ) {
savefile->ReadObject( reinterpret_cast<idClass *&>( focusVehicle ) );
savefile->ReadUserInterface( cursor );

// DG: make it scale to 4:3 so crosshair looks properly round
// yes, like so many scaling-related things this is a bit hacky
// and note that this is special cased in StateChanged and you
// can *not* generally set windowDef properties like this.
cursor->SetStateBool("scaleto43", true);
cursor->StateChanged(gameLocal.time); // DG end

savefile->ReadInt( oldMouseX );
savefile->ReadInt( oldMouseY );

Expand Down
4 changes: 4 additions & 0 deletions neo/renderer/Framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ class fhFramebuffer {
}
void Resize(int width, int height, int samples, pixelFormat_t colorFormat, pixelFormat_t depthFormat);

int GetID() { // JW : for clearing framebuffer effects
return num;
}

idImage* GetColorAttachment() {
return colorAttachment;
}
Expand Down
3 changes: 3 additions & 0 deletions neo/renderer/RenderSystem_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,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");

idCVar r_softParticles( "r_softParticles", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "enabled soft particles");
idCVar r_defaultParticleSoftness( "r_defaultParticleSoftness", "0.35", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_FLOAT, "");

Expand Down
10 changes: 10 additions & 0 deletions neo/renderer/tr_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,16 @@ static void RB_CopyRender( const void *data, bool copyFromDefaultFramebuffer ) {
fhFramebuffer framebuffer("tmp", cmd->imageWidth, cmd->imageHeight, image, nullptr );
fhFramebuffer::BlitColor( src, cmd->x, cmd->y, cmd->imageWidth, cmd->imageHeight, &framebuffer );
framebuffer.Purge();
if ( image == fhFramebuffer::currentRenderFramebuffer->GetColorAttachment() ) // JW : need to do below to clear the mirror hell effect in Mars City 2 so it doesn't leave artifacts in subsequent uses of reflection, imp fireball heat distortion etc.
{
fhFramebuffer *currentDrawBuffer = fhFramebuffer::GetCurrentDrawBuffer();
fhFramebuffer::currentRenderFramebuffer->Bind();
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, fhFramebuffer::currentRenderFramebuffer->GetID() );
int samples = fhFramebuffer::currentRenderFramebuffer->GetSamples();
auto target = samples > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, fhFramebuffer::currentRenderFramebuffer->GetColorAttachment()->texnum, 0 ); // just reattaching it why
currentDrawBuffer->Bind();
}
}
}

Expand Down
95 changes: 93 additions & 2 deletions neo/ui/DeviceContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -581,6 +644,26 @@ void idDeviceContext::DrawFilledRect( float x, float y, float w, float h, const
DrawStretchPic( x, y, w, h, 0, 0, 0, 0, whiteImage);
}

// JW : use to draw pillarboxing background for menus in 4:3 mode.
// uses AdjustCursorCoords instead of AdjustCoords. That method ignores fixupMenus because for the cursor that must be handled seperately
// which also allows us to draw a background that covers the whole screen, causing black pillarboxing outside the 4:3 menu
// instead of just leaving whatever was drawn there before, as happens with r_useFramebuffer 1 (but not r_useFramebuffer 0)
void idDeviceContext::DrawFilledRectNo43(float x, float y, float w, float h, const idVec4 &color) {

if (color.w == 0.0f) {
return;
}

renderSystem->SetColor(color);

if (ClippedCoords(&x, &y, &w, &h, NULL, NULL, NULL, NULL)) {
return;
}

AdjustCursorCoords(&x, &y, &w, &h);
DrawStretchPic(x, y, w, h, 0, 0, 0, 0, whiteImage);
}


void idDeviceContext::DrawRect( float x, float y, float w, float h, float size, const idVec4 &color) {

Expand Down Expand Up @@ -637,8 +720,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]);
}
/*
=======================================================================================================================
Expand Down
12 changes: 12 additions & 0 deletions neo/ui/DeviceContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class idDeviceContext {
void DrawMaterial(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex = 1.0, float scaley = 1.0);
void DrawRect(float x, float y, float width, float height, float size, const idVec4 &color);
void DrawFilledRect(float x, float y, float width, float height, const idVec4 &color);
void DrawFilledRectNo43(float x, float y, float width, float height, const idVec4 &color); // JW : for drawing rectangles unaffected by the 4:3 menu hack (to draw pillarboxes behind menus with r_useFramebuffer 1)
int DrawText(const char *text, float textScale, int textAlign, idVec4 color, idRectangle rectDraw, bool wrap, int cursor = -1, bool calcOnly = false, idList<int> *breaks = NULL, int limit = 0 );
void DrawMaterialRect( float x, float y, float w, float h, float size, const idMaterial *mat, const idVec4 &color);
void DrawStretchPic(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat);
Expand All @@ -80,6 +81,7 @@ class idDeviceContext {
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);

Expand All @@ -96,6 +98,12 @@ class idDeviceContext {

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,
Expand Down Expand Up @@ -163,6 +171,10 @@ class idDeviceContext {
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__ */
20 changes: 15 additions & 5 deletions neo/ui/RenderWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,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);

Expand All @@ -153,10 +153,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;

Expand Down
52 changes: 50 additions & 2 deletions neo/ui/UserInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ If you have questions concerning this license or the applicable additional terms
#include "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;
Expand Down Expand Up @@ -343,8 +344,42 @@ const char *idUserInterfaceLocal::HandleEvent( const sysEvent_t *event, int _tim
}

if ( event->evType == SE_MOUSE ) {
cursorX += event->evValue;
cursorY += event->evValue2;
if (!desktop || (desktop->GetFlags() & WIN_MENUGUI)) {
// DG: this is a fullscreen GUI, scale the mousedelta added to cursorX/Y
// by 640/w, because the GUI pretends that everything is 640x480
// even if the actual resolution is higher => mouse moved too fast
float w = renderSystem->GetScreenWidth();
float h = renderSystem->GetScreenHeight();
if (w <= 0.0f || h <= 0.0f) {
w = VIRTUAL_WIDTH;
h = VIRTUAL_HEIGHT;
}

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;
cursorY += event->evValue2;
}

if (cursorX < 0) {
cursorX = 0;
Expand Down Expand Up @@ -428,6 +463,19 @@ float idUserInterfaceLocal::GetStateFloat( const char *varName, const char* defa
void idUserInterfaceLocal::StateChanged( int _time, bool redraw ) {
time = _time;
if (desktop) {
// DG: little hack: allow game DLLs to do
// ui->SetStateBool("scaleto43", true);
// ui->StateChanged(gameLocal.time);
// so we can force cursors.gui (crosshair) to be scaled, for example
bool scaleTo43 = false;
if(state.GetBool("scaleto43", "0", scaleTo43)) {
if(scaleTo43)
desktop->SetFlag(WIN_SCALETO43);
else
desktop->ClearFlag(WIN_SCALETO43);
}
// DG end

desktop->StateChanged( redraw );
}
if ( state.GetBool( "noninteractive" ) ) {
Expand Down
Loading