From 46cb46630d29ecd9de779edb463eb54f84650e24 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Fri, 17 Jan 2025 18:30:27 +0100 Subject: [PATCH 1/4] Changes from CstDoom3 for anchored GUIs, #324 those GUIs are aspectratio-independent doesn't properly work yet, esp. together with my hack that makes sure menus are rendered in 4:3 --- neo/d3xp/PlayerView.cpp | 40 ++++++- neo/game/PlayerView.cpp | 40 ++++++- neo/ui/DeviceContext.cpp | 238 ++++++++++++++++++++++++++++++++++++++- neo/ui/DeviceContext.h | 38 ++++++- neo/ui/SimpleWindow.cpp | 79 ++++++++++++- neo/ui/SimpleWindow.h | 7 ++ neo/ui/Window.cpp | 104 ++++++++++++++++- neo/ui/Window.h | 7 ++ 8 files changed, 540 insertions(+), 13 deletions(-) diff --git a/neo/d3xp/PlayerView.cpp b/neo/d3xp/PlayerView.cpp index 750e20d0..9e3d4f09 100644 --- a/neo/d3xp/PlayerView.cpp +++ b/neo/d3xp/PlayerView.cpp @@ -694,8 +694,44 @@ void idPlayerView::RenderPlayerView( idUserInterface *hud ) { ScreenFade(); if ( net_clientLagOMeter.GetBool() && lagoMaterial && gameLocal.isClient ) { - renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f ); - renderSystem->DrawStretchPic( 10.0f, 380.0f, 64.0f, 64.0f, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial ); + //#modified-fva; BEGIN + float x = 10.0f; + float y = 380.0f; + float w = 64.0f; + float h = 64.0f; + if (cvarSystem->GetCVarBool("cst_hudAdjustAspect")) { + // similar to CST_ANCHOR_BOTTOM_LEFT + int glWidth, glHeight; + renderSystem->GetGLSettings(glWidth, glHeight); + if (glWidth > 0 && glHeight > 0) { + float glAspectRatio = (float)glWidth / (float)glHeight; + + const float vidWidth = SCREEN_WIDTH; + const float vidHeight = SCREEN_HEIGHT; + const float vidAspectRatio = (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT; + + float modWidth = vidWidth; + float modHeight = vidHeight; + if (glAspectRatio >= vidAspectRatio) { + modWidth = modHeight * glAspectRatio; + } else { + modHeight = modWidth / glAspectRatio; + } + + float xScale = vidWidth / modWidth; + float yScale = vidHeight / modHeight; + float xOffset = 0.0f; + float yOffset = vidHeight * (1.0f - yScale); + + x = x * xScale + xOffset; + y = y * yScale + yOffset; + w *= xScale; + h *= yScale; + } + } + renderSystem->SetColor4(1.0f, 1.0f, 1.0f, 1.0f); + renderSystem->DrawStretchPic(x, y, w, h, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial); + //#modified-fva; END } } diff --git a/neo/game/PlayerView.cpp b/neo/game/PlayerView.cpp index 549ce3ab..16dc8094 100644 --- a/neo/game/PlayerView.cpp +++ b/neo/game/PlayerView.cpp @@ -721,7 +721,43 @@ void idPlayerView::RenderPlayerView( idUserInterface *hud ) { } if ( net_clientLagOMeter.GetBool() && lagoMaterial && gameLocal.isClient ) { - renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f ); - renderSystem->DrawStretchPic( 10.0f, 380.0f, 64.0f, 64.0f, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial ); + //#modified-fva; BEGIN + float x = 10.0f; + float y = 380.0f; + float w = 64.0f; + float h = 64.0f; + if (cvarSystem->GetCVarBool("cst_hudAdjustAspect")) { + // similar to CST_ANCHOR_BOTTOM_LEFT + int glWidth, glHeight; + renderSystem->GetGLSettings(glWidth, glHeight); + if (glWidth > 0 && glHeight > 0) { + float glAspectRatio = (float)glWidth / (float)glHeight; + + const float vidWidth = SCREEN_WIDTH; + const float vidHeight = SCREEN_HEIGHT; + const float vidAspectRatio = (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT; + + float modWidth = vidWidth; + float modHeight = vidHeight; + if (glAspectRatio >= vidAspectRatio) { + modWidth = modHeight * glAspectRatio; + } else { + modHeight = modWidth / glAspectRatio; + } + + float xScale = vidWidth / modWidth; + float yScale = vidHeight / modHeight; + float xOffset = 0.0f; + float yOffset = vidHeight * (1.0f - yScale); + + x = x * xScale + xOffset; + y = y * yScale + yOffset; + w *= xScale; + h *= yScale; + } + } + renderSystem->SetColor4(1.0f, 1.0f, 1.0f, 1.0f); + renderSystem->DrawStretchPic(x, y, w, h, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial); + //#modified-fva; END } } diff --git a/neo/ui/DeviceContext.cpp b/neo/ui/DeviceContext.cpp index 6a5db6da..41c5002e 100644 --- a/neo/ui/DeviceContext.cpp +++ b/neo/ui/DeviceContext.cpp @@ -291,6 +291,7 @@ void idDeviceContext::SetMenuScaleFix(bool enable) { } } +// FIXME: CSTD3 comments this out void idDeviceContext::AdjustCoords(float *x, float *y, float *w, float *h) { if (x) { @@ -333,7 +334,8 @@ void idDeviceContext::AdjustCursorCoords(float *x, float *y, float *w, float *h) } } -void idDeviceContext::DrawStretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader) { +// fva's cst: added _cstAdjustCoords arg +void idDeviceContext::DrawStretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, bool _cstAdjustCoords) { idDrawVert verts[4]; glIndex_t indexes[6]; indexes[0] = 3; @@ -415,6 +417,19 @@ void idDeviceContext::DrawStretchPic(float x, float y, float w, float h, float s verts[3].xyz += origin; } + //#modified-fva; BEGIN + if (_cstAdjustCoords) { + verts[0].xyz[0] = verts[0].xyz[0] * xScale + cst_xOffset; + verts[0].xyz[1] = verts[0].xyz[1] * yScale + cst_yOffset; + verts[1].xyz[0] = verts[1].xyz[0] * xScale + cst_xOffset; + verts[1].xyz[1] = verts[1].xyz[1] * yScale + cst_yOffset; + verts[2].xyz[0] = verts[2].xyz[0] * xScale + cst_xOffset; + verts[2].xyz[1] = verts[2].xyz[1] * yScale + cst_yOffset; + verts[3].xyz[0] = verts[3].xyz[0] * xScale + cst_xOffset; + verts[3].xyz[1] = verts[3].xyz[1] * yScale + cst_yOffset; + } + //#modified-fva; END + renderSystem->DrawStretchPic( &verts[0], &indexes[0], 4, 6, shader, ident ); } @@ -462,9 +477,14 @@ void idDeviceContext::DrawMaterial(float x, float y, float w, float h, const idM return; } + //#modified-fva; BEGIN + /* AdjustCoords(&x, &y, &w, &h); DrawStretchPic( x, y, w, h, s0, t0, s1, t1, mat); + */ + DrawStretchPic(x, y, w, h, s0, t0, s1, t1, mat, cstAdjustCoords); + //#modified-fva; END } void idDeviceContext::DrawMaterialRotated(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex, float scaley, float angle) { @@ -509,12 +529,18 @@ void idDeviceContext::DrawMaterialRotated(float x, float y, float w, float h, co return; } + //#modified-fva; BEGIN + /* AdjustCoords(&x, &y, &w, &h); DrawStretchPicRotated( x, y, w, h, s0, t0, s1, t1, mat, angle); + */ + DrawStretchPicRotated(x, y, w, h, s0, t0, s1, t1, mat, angle, cstAdjustCoords); + //#modified-fva; END } -void idDeviceContext::DrawStretchPicRotated(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, float angle) { +// fva's cst: added _cstAdjustCoords arg +void idDeviceContext::DrawStretchPicRotated(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, float angle, bool _cstAdjustCoords) { idDrawVert verts[4]; glIndex_t indexes[6]; @@ -624,6 +650,18 @@ void idDeviceContext::DrawStretchPicRotated(float x, float y, float w, float h, verts[i].xyz += origTrans; } + //#modified-fva; BEGIN + if (_cstAdjustCoords) { + verts[0].xyz[0] = verts[0].xyz[0] * xScale + cst_xOffset; + verts[0].xyz[1] = verts[0].xyz[1] * yScale + cst_yOffset; + verts[1].xyz[0] = verts[1].xyz[0] * xScale + cst_xOffset; + verts[1].xyz[1] = verts[1].xyz[1] * yScale + cst_yOffset; + verts[2].xyz[0] = verts[2].xyz[0] * xScale + cst_xOffset; + verts[2].xyz[1] = verts[2].xyz[1] * yScale + cst_yOffset; + verts[3].xyz[0] = verts[3].xyz[0] * xScale + cst_xOffset; + verts[3].xyz[1] = verts[3].xyz[1] * yScale + cst_yOffset; + } + //#modified-fva; END renderSystem->DrawStretchPic( &verts[0], &indexes[0], 4, 6, shader, (angle == 0.0) ? false : true ); } @@ -640,8 +678,13 @@ void idDeviceContext::DrawFilledRect( float x, float y, float w, float h, const return; } + //#modified-fva; BEGIN + /* AdjustCoords(&x, &y, &w, &h); DrawStretchPic( x, y, w, h, 0, 0, 0, 0, whiteImage); + */ + DrawStretchPic(x, y, w, h, 0, 0, 0, 0, whiteImage, cstAdjustCoords); + //#modified-fva; END } @@ -657,11 +700,19 @@ void idDeviceContext::DrawRect( float x, float y, float w, float h, float size, return; } + //#modified-fva; BEGIN + /* AdjustCoords(&x, &y, &w, &h); DrawStretchPic( x, y, size, h, 0, 0, 0, 0, whiteImage ); DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, whiteImage ); DrawStretchPic( x, y, w, size, 0, 0, 0, 0, whiteImage ); DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, whiteImage ); + */ + DrawStretchPic(x, y + size, size, h - 2.0f * size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); + DrawStretchPic(x + w - size, y + size, size, h - 2.0f * size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); + DrawStretchPic(x, y, w, size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); + DrawStretchPic(x, y + h - size, w, size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); + //#modified-fva; END } void idDeviceContext::DrawMaterialRect( float x, float y, float w, float h, float size, const idMaterial *mat, const idVec4 &color) { @@ -703,12 +754,15 @@ void idDeviceContext::DrawCursor(float *x, float *y, float size) { // 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); + // FIXME: how could this ever work with xScale = 0 or yScale = 0 ?! + //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; + // FIXME: CSTD3 just comments the AdjustCoords() call out and uses *x and *y instead of fixedX/Y + DrawStretchPic(fixedX, fixedY, sizeW, sizeH, 0, 0, 1, 1, cursorImages[cursor]); } /* @@ -725,8 +779,13 @@ void idDeviceContext::PaintChar(float x,float y,float width,float height,float s return; } + //#modified-fva; BEGIN + /* AdjustCoords(&x, &y, &w, &h); DrawStretchPic(x, y, w, h, s, t, s2, t2, hShader); + */ + DrawStretchPic(x, y, w, h, s, t, s2, t2, hShader, cstAdjustCoords); + //#modified-fva; END } @@ -818,13 +877,182 @@ int idDeviceContext::DrawText(float x, float y, float scale, idVec4 color, const void idDeviceContext::SetSize(float width, float height) { vidWidth = VIRTUAL_WIDTH; vidHeight = VIRTUAL_HEIGHT; - xScale = yScale = 0.0f; - if ( width != 0.0f && height != 0.0f ) { + xScale = yScale = 1.0f; // DG: I think this was also changed by fva + //#modified-fva; BEGIN + cst_xOffset = cst_yOffset = 0.0f; + cstAdjustCoords = false; + if ((width != vidWidth || height != vidHeight) && width > 0.0f && height > 0.0f) { + cstAdjustCoords = true; + //#modified-fva; END xScale = vidWidth * ( 1.0f / width ); yScale = vidHeight * ( 1.0f / height ); } } +//#modified-fva; BEGIN +// =============== +static bool CstGetVidScale(float &_xScale, float &_yScale) { + int glWidth, glHeight; + renderSystem->GetGLSettings(glWidth, glHeight); + if (glWidth <= 0 || glHeight <= 0) { + return false; + } + + float glAspectRatio = (float)glWidth / (float)glHeight; + + const float vidWidth = VIRTUAL_WIDTH; + const float vidHeight = VIRTUAL_HEIGHT; + const float vidAspectRatio = (float)VIRTUAL_WIDTH / (float)VIRTUAL_HEIGHT; + + float modWidth = vidWidth; + float modHeight = vidHeight; + if (glAspectRatio >= vidAspectRatio) { + modWidth = modHeight * glAspectRatio; + } else { + modHeight = modWidth / glAspectRatio; + } + + _xScale = vidWidth / modWidth; + _yScale = vidHeight / modHeight; + return true; +} + + +static void CstAdjustParmsForAnchor(int anchor, float &_xScale, float &_yScale, float &_xOffset, float &_yOffset) { + const float vidWidth = VIRTUAL_WIDTH; + const float vidHeight = VIRTUAL_HEIGHT; + + switch (anchor) { + case idDeviceContext::CST_ANCHOR_TOP_LEFT: { + _xOffset = 0.0f; + _yOffset = 0.0f; + break; + } + case idDeviceContext::CST_ANCHOR_TOP_CENTER: { + _xOffset = (vidWidth * 0.5f) * (1.0f - _xScale); + _yOffset = 0.0f; + break; + } + case idDeviceContext::CST_ANCHOR_TOP_RIGHT: { + _xOffset = vidWidth * (1.0f - _xScale); + _yOffset = 0.0f; + break; + } + case idDeviceContext::CST_ANCHOR_CENTER_LEFT: { + _xOffset = 0.0f; + _yOffset = (vidHeight * 0.5f) * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_CENTER_CENTER: { + _xOffset = (vidWidth * 0.5f) * (1.0f - _xScale); + _yOffset = (vidHeight * 0.5f) * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_CENTER_RIGHT: { + _xOffset = vidWidth * (1.0f - _xScale); + _yOffset = (vidHeight * 0.5f) * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_BOTTOM_LEFT: { + _xOffset = 0.0f; + _yOffset = vidHeight * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_BOTTOM_CENTER: { + _xOffset = (vidWidth * 0.5f) * (1.0f - _xScale); + _yOffset = vidHeight * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_BOTTOM_RIGHT: { + _xOffset = vidWidth * (1.0f - _xScale); + _yOffset = vidHeight * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_TOP: { + _xScale = 1.0f; // no horizontal scaling + _xOffset = 0.0f; + _yOffset = 0.0f; + break; + } + case idDeviceContext::CST_ANCHOR_VCENTER: { + _xScale = 1.0f; // no horizontal scaling + _xOffset = 0.0f; + _yOffset = (vidHeight * 0.5f) * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_BOTTOM: { + _xScale = 1.0f; // no horizontal scaling + _xOffset = 0.0f; + _yOffset = vidHeight * (1.0f - _yScale); + break; + } + case idDeviceContext::CST_ANCHOR_LEFT: { + _yScale = 1.0f; // no vertical scaling + _xOffset = 0.0f; + _yOffset = 0.0f; + break; + } + case idDeviceContext::CST_ANCHOR_HCENTER: { + _yScale = 1.0f; // no vertical scaling + _xOffset = (vidWidth * 0.5f) * (1.0f - _xScale); + _yOffset = 0.0f; + break; + } + case idDeviceContext::CST_ANCHOR_RIGHT: { + _yScale = 1.0f; // no vertical scaling + _xOffset = vidWidth * (1.0f - _xScale); + _yOffset = 0.0f; + break; + } + default: { + _xOffset = 0.0f; + _yOffset = 0.0f; + break; + } + } +} + + +void idDeviceContext::CstSetSize(int anchor, int anchorTo, float factor) { + vidWidth = VIRTUAL_WIDTH; + vidHeight = VIRTUAL_HEIGHT; + xScale = 1.0f; + yScale = 1.0f; + cst_xOffset = 0.0f; + cst_yOffset = 0.0f; + cstAdjustCoords = false; + + if (!CstGetVidScale(xScale, yScale)) { + return; + } + + if (anchorTo == idDeviceContext::CST_ANCHOR_NONE) { + CstAdjustParmsForAnchor(anchor, xScale, yScale, cst_xOffset, cst_yOffset); + } else { + float from_xScale = xScale; + float from_yScale = yScale; + float from_xOffset = 0.0f; + float from_yOffset = 0.0f; + CstAdjustParmsForAnchor(anchor, from_xScale, from_yScale, from_xOffset, from_yOffset); + + float to_xScale = xScale; + float to_yScale = yScale; + float to_xOffset = 0.0f; + float to_yOffset = 0.0f; + CstAdjustParmsForAnchor(anchorTo, to_xScale, to_yScale, to_xOffset, to_yOffset); + + factor = idMath::ClampFloat(0.0f, 1.0f, factor); + + xScale = from_xScale * (1.0f - factor) + to_xScale * factor; + yScale = from_yScale * (1.0f - factor) + to_yScale * factor; + + cst_xOffset = from_xOffset * (1.0f - factor) + to_xOffset * factor; + cst_yOffset = from_yOffset * (1.0f - factor) + to_yOffset * factor; + } + cstAdjustCoords = true; +} +//#modified-fva; END + int idDeviceContext::CharWidth( const char c, float scale ) { glyphInfo_t *glyph; float useScale; diff --git a/neo/ui/DeviceContext.h b/neo/ui/DeviceContext.h index 93d70343..9c5fa3d4 100644 --- a/neo/ui/DeviceContext.h +++ b/neo/ui/DeviceContext.h @@ -58,10 +58,12 @@ public: void DrawFilledRect(float x, float y, float width, float height, const idVec4 &color); int DrawText(const char *text, float textScale, int textAlign, idVec4 color, idRectangle rectDraw, bool wrap, int cursor = -1, bool calcOnly = false, idList *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); + // fva's cst: added _cstAdjustCoords arg + void DrawStretchPic(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, bool _cstAdjustCoords = false); void DrawMaterialRotated(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex = 1.0, float scaley = 1.0, float angle = 0.0f); - void DrawStretchPicRotated(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, float angle = 0.0f); + // fva's cst: added _cstAdjustCoords arg + void DrawStretchPicRotated(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, float angle = 0.0f, bool _cstAdjustCoords = false); int CharWidth( const char c, float scale ); int TextWidth(const char *text, float scale, int limit); @@ -76,11 +78,16 @@ public: void SetSize(float width, float height); + //#modified-fva; BEGIN + void CstSetSize(int anchor, int anchorTo, float factor); + //#modified-fva; END + const idMaterial *GetScrollBarImage(int index); void DrawCursor(float *x, float *y, float size); void SetCursor(int n); + // FIXME: CSTD3 comments AdjustCoords out, what does that mean for AdjustCursorCoords? 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); @@ -128,6 +135,27 @@ public: SCROLLBAR_COUNT }; + //#modified-fva; BEGIN + enum { + CST_ANCHOR_NONE = -1, + CST_ANCHOR_TOP_LEFT, + CST_ANCHOR_TOP_CENTER, + CST_ANCHOR_TOP_RIGHT, + CST_ANCHOR_CENTER_LEFT, + CST_ANCHOR_CENTER_CENTER, + CST_ANCHOR_CENTER_RIGHT, + CST_ANCHOR_BOTTOM_LEFT, + CST_ANCHOR_BOTTOM_CENTER, + CST_ANCHOR_BOTTOM_RIGHT, + CST_ANCHOR_TOP, + CST_ANCHOR_VCENTER, + CST_ANCHOR_BOTTOM, + CST_ANCHOR_LEFT, + CST_ANCHOR_HCENTER, + CST_ANCHOR_RIGHT + }; + //#modified-fva; END + static idVec4 colorPurple; static idVec4 colorOrange; static idVec4 colorYellow; @@ -153,6 +181,12 @@ private: float xScale; float yScale; + //#modified-fva; BEGIN + float cst_xOffset; + float cst_yOffset; + bool cstAdjustCoords; + //#modified-fva; END + float vidHeight; float vidWidth; diff --git a/neo/ui/SimpleWindow.cpp b/neo/ui/SimpleWindow.cpp index d8884cee..4c986710 100644 --- a/neo/ui/SimpleWindow.cpp +++ b/neo/ui/SimpleWindow.cpp @@ -77,6 +77,13 @@ idSimpleWindow::idSimpleWindow(idWindow *win) { hideCursor = win->hideCursor; + //#modified-fva; BEGIN + cstAnchor = win->cstAnchor; + cstAnchorTo = win->cstAnchorTo; + cstAnchorFactor = win->cstAnchorFactor; + cstNoClipBackground = win->cstNoClipBackground; + //#modified-fva; END + idWindow *parent = win->GetParent(); if (parent) { if (text.NeedsUpdate()) { @@ -112,6 +119,18 @@ idSimpleWindow::idSimpleWindow(idWindow *win) { if (backGroundName.NeedsUpdate()) { parent->AddUpdateVar(&backGroundName); } + + //#modified-fva; BEGIN + if (cstAnchor.NeedsUpdate()) { + parent->AddUpdateVar(&cstAnchor); + } + if (cstAnchorTo.NeedsUpdate()) { + parent->AddUpdateVar(&cstAnchorTo); + } + if (cstAnchorFactor.NeedsUpdate()) { + parent->AddUpdateVar(&cstAnchorFactor); + } + //#modified-fva; END } } @@ -223,14 +242,41 @@ void idSimpleWindow::Redraw(float x, float y) { CalcClientRect(0, 0); dc->SetFont(fontNum); + + //#modified-fva; BEGIN + if (mParent && mParent->cstAnchor != idDeviceContext::CST_ANCHOR_NONE) { + cstAnchor = mParent->cstAnchor; + cstAnchorTo = mParent->cstAnchorTo; + cstAnchorFactor = mParent->cstAnchorFactor; + } + extern idCVar cst_hudAdjustAspect; + if (!cst_hudAdjustAspect.GetBool() || cstAnchor == idDeviceContext::CST_ANCHOR_NONE) { + if (mParent) { + dc->SetSize(mParent->forceAspectWidth, mParent->forceAspectHeight); + } else { + dc->SetSize(VIRTUAL_WIDTH, VIRTUAL_HEIGHT); + } + } else { + dc->CstSetSize(cstAnchor, cstAnchorTo, cstAnchorFactor); + } + //#modified-fva; END + drawRect.Offset(x, y); clientRect.Offset(x, y); textRect.Offset(x, y); SetupTransforms(x, y); - if ( flags & WIN_NOCLIP ) { + // fva's cst: added cstNoClipBackground + if ((flags & WIN_NOCLIP) || cstNoClipBackground) { dc->EnableClipping( false ); } DrawBackground(drawRect); + + //#modified-fva; BEGIN + if (!(flags & WIN_NOCLIP) && cstNoClipBackground) { + dc->EnableClipping(true); + } + //#modified-fva; END + DrawBorderAndCaption(drawRect); if ( textShadow ) { idStr shadowText = text; @@ -283,6 +329,12 @@ intptr_t idSimpleWindow::GetWinVarOffset( idWinVar *wv, drawWin_t* owner) { ret = (ptrdiff_t)&this->rotate - (ptrdiff_t)this; } + //#modified-fva; BEGIN + if (wv == &cstAnchorFactor) { + ret = (ptrdiff_t)&this->cstAnchorFactor - (ptrdiff_t)this; + } + //#modified-fva; END + if ( ret != -1 ) { owner->simp = this; } @@ -324,6 +376,17 @@ idWinVar *idSimpleWindow::GetWinVarByName(const char *_name) { if (idStr::Icmp(_name, "text") == 0) { retVar = &text; } + + //#modified-fva; BEGIN + if (idStr::Icmp(_name, "cstAnchor") == 0) { + retVar = &cstAnchor; + } else if (idStr::Icmp(_name, "cstAnchorTo") == 0) { + retVar = &cstAnchorTo; + } else if (idStr::Icmp(_name, "cstAnchorFactor") == 0) { + retVar = &cstAnchorFactor; + } + //#modified-fva; END + return retVar; } @@ -359,6 +422,13 @@ void idSimpleWindow::WriteToSaveGame( idFile *savefile ) { rotate.WriteToSaveGame( savefile ); shear.WriteToSaveGame( savefile ); backGroundName.WriteToSaveGame( savefile ); + + //#modified-fva; BEGIN // FIXME: savegame version? + cstAnchor.WriteToSaveGame(savefile); + cstAnchorTo.WriteToSaveGame(savefile); + cstAnchorFactor.WriteToSaveGame(savefile); + savefile->Write(&cstNoClipBackground, sizeof(cstNoClipBackground)); + //#modified-fva; END int stringLen; @@ -406,6 +476,13 @@ void idSimpleWindow::ReadFromSaveGame( idFile *savefile ) { shear.ReadFromSaveGame( savefile ); backGroundName.ReadFromSaveGame( savefile ); + //#modified-fva; BEGIN // FIXME: savegame version? + cstAnchor.ReadFromSaveGame(savefile); + cstAnchorTo.ReadFromSaveGame(savefile); + cstAnchorFactor.ReadFromSaveGame(savefile); + savefile->Read(&cstNoClipBackground, sizeof(cstNoClipBackground)); + //#modified-fva; END + int stringLen; savefile->Read( &stringLen, sizeof( stringLen ) ); diff --git a/neo/ui/SimpleWindow.h b/neo/ui/SimpleWindow.h index 0268cc6d..3256d8b7 100644 --- a/neo/ui/SimpleWindow.h +++ b/neo/ui/SimpleWindow.h @@ -98,6 +98,13 @@ protected: idWindow * mParent; idWinBool hideCursor; + + //#modified-fva; BEGIN + idWinInt cstAnchor; + idWinInt cstAnchorTo; // for anchor transitions + idWinFloat cstAnchorFactor; // for anchor transitions + bool cstNoClipBackground; + //#modified-fva; END }; #endif /* !__SIMPLEWIN_H__ */ diff --git a/neo/ui/Window.cpp b/neo/ui/Window.cpp index 3948cea3..e64dbe17 100644 --- a/neo/ui/Window.cpp +++ b/neo/ui/Window.cpp @@ -54,6 +54,9 @@ bool idWindow::registerIsTemporary[MAX_EXPRESSION_REGISTERS]; // statics to ass idCVar idWindow::gui_debug( "gui_debug", "0", CVAR_GUI | CVAR_BOOL, "" ); idCVar idWindow::gui_edit( "gui_edit", "0", CVAR_GUI | CVAR_BOOL, "" ); +//#modified-fva; BEGIN +idCVar cst_hudAdjustAspect("cst_hudAdjustAspect", "0", CVAR_GUI | CVAR_BOOL | CVAR_ARCHIVE, "adjust the HUD's aspect when the screen aspect ratio isn't 4:3"); +//#modified-fva; END extern idCVar r_skipGuiShaders; // 1 = don't render any gui elements on surfaces extern idCVar r_scaleMenusTo43; @@ -80,6 +83,15 @@ const idRegEntry idWindow::RegisterVars[] = { { "choices", idRegister::STRING }, { "choiceVar", idRegister::STRING }, { "bind", idRegister::STRING }, + //#modified-fva; BEGIN - FIXME: why not at the end of the list? + { "cstLayer", idRegister::INT }, + { "cstPseudoBit", idRegister::INT }, + { "cstResetScrollbar", idRegister::BOOL }, + { "cstWriteTop", idRegister::BOOL }, + { "cstAnchor", idRegister::INT }, + { "cstAnchorTo", idRegister::INT }, + { "cstAnchorFactor", idRegister::FLOAT }, + //#modified-fva; END { "modelRotate", idRegister::VEC4 }, { "modelOrigin", idRegister::VEC4 }, { "lightOrigin", idRegister::VEC4 }, @@ -154,6 +166,13 @@ void idWindow::CommonInit() { } hideCursor = false; + + //#modified-fva; BEGIN + cstAnchor = idDeviceContext::CST_ANCHOR_NONE; + cstAnchorTo = idDeviceContext::CST_ANCHOR_NONE; + cstAnchorFactor = 0.0f; + cstNoClipBackground = false; + //#modified-fva; END } /* @@ -1247,10 +1266,25 @@ void idWindow::Redraw(float x, float y) { CalcClientRect(0, 0); SetFont(); + + //#modified-fva; BEGIN + /* //if (flags & WIN_DESKTOP) { // see if this window forces a new aspect ratio dc->SetSize(forceAspectWidth, forceAspectHeight); //} + */ + if (parent && parent->cstAnchor != idDeviceContext::CST_ANCHOR_NONE) { + cstAnchor = parent->cstAnchor; + cstAnchorTo = parent->cstAnchorTo; + cstAnchorFactor = parent->cstAnchorFactor; + } + if (!cst_hudAdjustAspect.GetBool() || cstAnchor == idDeviceContext::CST_ANCHOR_NONE) { + dc->SetSize(forceAspectWidth, forceAspectHeight); + } else { + dc->CstSetSize(cstAnchor, cstAnchorTo, cstAnchorFactor); + } + //#modified-fva; END //FIXME: go to screen coord tracking drawRect.Offset(x, y); @@ -1265,7 +1299,19 @@ void idWindow::Redraw(float x, float y) { dc->GetTransformInfo( oldOrg, oldTrans ); SetupTransforms(x, y); + //#modified-fva; BEGIN + if (cstNoClipBackground) { + dc->EnableClipping(false); + } + //#modified-fva; END + DrawBackground(drawRect); + + //#modified-fva; BEGIN + if (cstNoClipBackground) { + dc->EnableClipping(true); + } + //#modified-fva; END DrawBorderAndCaption(drawRect); if ( !( flags & WIN_NOCLIP) ) { @@ -1328,6 +1374,15 @@ void idWindow::SetDC(idDeviceContext *d) { //if (flags & WIN_DESKTOP) { dc->SetSize(forceAspectWidth, forceAspectHeight); //} + + //#modified-fva; BEGIN + if (parent && parent->cstAnchor != idDeviceContext::CST_ANCHOR_NONE) { + cstAnchor = parent->cstAnchor; + cstAnchorTo = parent->cstAnchorTo; + cstAnchorFactor = parent->cstAnchorFactor; + } + //#modified-fva; END + int c = children.Num(); for (int i = 0; i < c; i++) { children[i]->SetDC(d); @@ -1774,6 +1829,12 @@ intptr_t idWindow::GetWinVarOffset( idWinVar *wv, drawWin_t* owner) { ret = (ptrdiff_t)&this->rotate - (ptrdiff_t)this; } + //#modified-fva; BEGIN + if (wv == &cstAnchorFactor) { + ret = (ptrdiff_t)&this->cstAnchorFactor - (ptrdiff_t)this; + } + //#modified-fva; END + if ( ret != -1 ) { owner->win = this; return ret; @@ -1807,7 +1868,7 @@ idWinVar *idWindow::GetWinVarByName(const char *_name, bool fixup, drawWin_t** o if (idStr::Icmp(_name, "notime") == 0) { retVar = &noTime; - } + } // FIXME: why does all this code not use "else if"?! if (idStr::Icmp(_name, "background") == 0) { retVar = &backGroundName; } @@ -1850,6 +1911,15 @@ idWinVar *idWindow::GetWinVarByName(const char *_name, bool fixup, drawWin_t** o if (idStr::Icmp(_name, "hidecursor") == 0) { retVar = &hideCursor; } + //#modified-fva; BEGIN + if (idStr::Icmp(_name, "cstAnchor") == 0) { + retVar = &cstAnchor; + } else if (idStr::Icmp(_name, "cstAnchorTo") == 0) { + retVar = &cstAnchorTo; + } else if (idStr::Icmp(_name, "cstAnchorFactor") == 0) { + retVar = &cstAnchorFactor; + } + //#modified-fva; END idStr key = _name; bool guiVar = (key.Find(VAR_GUIPREFIX) >= 0); @@ -2075,6 +2145,14 @@ bool idWindow::ParseInternalVar(const char *_name, idParser *src) { fontNum = dc->FindFont( fontStr ); return true; } + + //#modified-fva; BEGIN + if (idStr::Icmp(_name, "cstNoClipBackground") == 0) { + cstNoClipBackground = src->ParseBool(); + return true; + } + //#modified-fva; END + return false; } @@ -3543,6 +3621,13 @@ void idWindow::WriteToSaveGame( idFile *savefile ) { backGroundName.WriteToSaveGame( savefile ); hideCursor.WriteToSaveGame(savefile); + //#modified-fva; BEGIN // FIXME: savegame version? + cstAnchor.WriteToSaveGame(savefile); + cstAnchorTo.WriteToSaveGame(savefile); + cstAnchorFactor.WriteToSaveGame(savefile); + savefile->Write(&cstNoClipBackground, sizeof(cstNoClipBackground)); + //#modified-fva; END + // Defined Vars for ( i = 0; i < definedVars.Num(); i++ ) { definedVars[i]->WriteToSaveGame( savefile ); @@ -3693,6 +3778,13 @@ void idWindow::ReadFromSaveGame( idFile *savefile ) { hideCursor = false; } + //#modified-fva; BEGIN // FIXME: savegame version? + cstAnchor.ReadFromSaveGame(savefile); + cstAnchorTo.ReadFromSaveGame(savefile); + cstAnchorFactor.ReadFromSaveGame(savefile); + savefile->Read(&cstNoClipBackground, sizeof(cstNoClipBackground)); + //#modified-fva; END + // Defined Vars for ( i = 0; i < definedVars.Num(); i++ ) { definedVars[i]->ReadFromSaveGame( savefile ); @@ -3825,6 +3917,11 @@ void idWindow::FixupTransitions() { } else if ( transitions[i].offset == (ptrdiff_t)&this->rotate - (ptrdiff_t)this ) { transitions[i].data = &dw->win->rotate; } + //#modified-fva; BEGIN + else if ( transitions[i].offset == (ptrdiff_t)&this->cstAnchorFactor - (ptrdiff_t)this ) { + transitions[i].data = &dw->win->cstAnchorFactor; + } + //#modified-fva; END } else { if ( transitions[i].offset == (ptrdiff_t)&this->rect - (ptrdiff_t)this ) { transitions[i].data = &dw->simp->rect; @@ -3841,6 +3938,11 @@ void idWindow::FixupTransitions() { } else if ( transitions[i].offset == (ptrdiff_t)&this->rotate - (ptrdiff_t)this ) { transitions[i].data = &dw->simp->rotate; } + //#modified-fva; BEGIN + else if ( transitions[i].offset == (ptrdiff_t)&this->cstAnchorFactor - (ptrdiff_t)this ) { + transitions[i].data = &dw->simp->cstAnchorFactor; + } + //#modified-fva; END } } if ( transitions[i].data == NULL ) { diff --git a/neo/ui/Window.h b/neo/ui/Window.h index 96f6534e..1cf29f85 100644 --- a/neo/ui/Window.h +++ b/neo/ui/Window.h @@ -452,6 +452,13 @@ protected: idRegisterList regList; idWinBool hideCursor; + + //#modified-fva; BEGIN + idWinInt cstAnchor; + idWinInt cstAnchorTo; // for anchor transitions + idWinFloat cstAnchorFactor; // for anchor transitions + bool cstNoClipBackground; + //#modified-fva; END }; ID_INLINE void idWindow::AddDefinedVar( idWinVar* var ) { From 565d3e3fc123089882ece53dd356526eb3d73f20 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sat, 18 Jan 2025 02:27:03 +0100 Subject: [PATCH 2/4] Make CstDoom3 anchored GUIs work with dhewm3's menu scale fix In idWindow::Redraw(), I had to make sure the menu scale fix (which, if enabled for a window, renders that in 4:3 with empty or black bars on the side if needed for widescreen etc, instead of stretching it) is disabled if a window uses CST anchors, because the CST anchor code also adjusts for the display aspect ratio and if we do both, things get distorted in the other way. The biggest change is that idDeviceContext::DrawStretchPic(Rotated) now has code to adjust the coordinates for both CST and the menu scale fix, so idDeviceContext::AdjustCoords() is mostly obsolete - it's only still used by idRenderWindow. Unlike DstDoom3 now that extra adjustCoords argument to those Draw functions indicates that any coordinate adjustment should be done, so if it's set by a caller, it's set to true. I removed idDeviceContext::AdjustCursorCoords() because it was only used in one place anyway --- neo/ui/DeviceContext.cpp | 106 +++++++++++++++++++-------------------- neo/ui/DeviceContext.h | 13 +++-- neo/ui/Window.cpp | 4 ++ 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/neo/ui/DeviceContext.cpp b/neo/ui/DeviceContext.cpp index 41c5002e..7ab11320 100644 --- a/neo/ui/DeviceContext.cpp +++ b/neo/ui/DeviceContext.cpp @@ -291,17 +291,20 @@ void idDeviceContext::SetMenuScaleFix(bool enable) { } } -// FIXME: CSTD3 comments this out +// DG: Note: not sure if AdjustCoords() works entirely as it should, but it seems +// good enough for the idRenderWindow with the mars globe in the main menu void idDeviceContext::AdjustCoords(float *x, float *y, float *w, float *h) { - + // TODO: not sure about cst_*Offset if (x) { *x *= xScale; + *x += cst_xOffset; // DG: for CstDoom3 anchored windows *x *= fixScaleForMenu.x; // DG: for "render menus as 4:3" hack *x += fixOffsetForMenu.x; } if (y) { *y *= yScale; + *y += cst_yOffset; // DG: for CstDoom3 anchored windows *y *= fixScaleForMenu.y; // DG: for "render menus as 4:3" hack *y += fixOffsetForMenu.y; @@ -318,24 +321,10 @@ void idDeviceContext::AdjustCoords(float *x, float *y, float *w, float *h) { } } -// 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; - } - if (y) { - *y *= yScale; - } - if (w) { - *w *= xScale; - } - if (h) { - *h *= yScale; - } -} - -// fva's cst: added _cstAdjustCoords arg -void idDeviceContext::DrawStretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, bool _cstAdjustCoords) { +// fva/DG: added adjustCoords argument for CstDoom3 anchored GUIs and our old +// scale-menus-to-4:3-fix, it basically replaces calling AdjustCoords(&x, &y, &w, &h) +// before calling this +void idDeviceContext::DrawStretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, bool adjustCoords) { idDrawVert verts[4]; glIndex_t indexes[6]; indexes[0] = 3; @@ -418,15 +407,14 @@ void idDeviceContext::DrawStretchPic(float x, float y, float w, float h, float s } //#modified-fva; BEGIN - if (_cstAdjustCoords) { - verts[0].xyz[0] = verts[0].xyz[0] * xScale + cst_xOffset; - verts[0].xyz[1] = verts[0].xyz[1] * yScale + cst_yOffset; - verts[1].xyz[0] = verts[1].xyz[0] * xScale + cst_xOffset; - verts[1].xyz[1] = verts[1].xyz[1] * yScale + cst_yOffset; - verts[2].xyz[0] = verts[2].xyz[0] * xScale + cst_xOffset; - verts[2].xyz[1] = verts[2].xyz[1] * yScale + cst_yOffset; - verts[3].xyz[0] = verts[3].xyz[0] * xScale + cst_xOffset; - verts[3].xyz[1] = verts[3].xyz[1] * yScale + cst_yOffset; + if (adjustCoords) { + for( int i=0; i<4; ++i) { + // Note: if cstAdjustCoords == false; cst_*Offset is 0, so that doesn't require special handling + float x = verts[i].xyz[0] * xScale + cst_xOffset; + float y = verts[i].xyz[1] * yScale + cst_yOffset; + verts[i].xyz[0] = x * fixScaleForMenu.x + fixOffsetForMenu.x; + verts[i].xyz[1] = y * fixScaleForMenu.y + fixOffsetForMenu.y; + } } //#modified-fva; END @@ -483,7 +471,7 @@ void idDeviceContext::DrawMaterial(float x, float y, float w, float h, const idM DrawStretchPic( x, y, w, h, s0, t0, s1, t1, mat); */ - DrawStretchPic(x, y, w, h, s0, t0, s1, t1, mat, cstAdjustCoords); + DrawStretchPic(x, y, w, h, s0, t0, s1, t1, mat, true); //#modified-fva; END } @@ -535,12 +523,14 @@ void idDeviceContext::DrawMaterialRotated(float x, float y, float w, float h, co DrawStretchPicRotated( x, y, w, h, s0, t0, s1, t1, mat, angle); */ - DrawStretchPicRotated(x, y, w, h, s0, t0, s1, t1, mat, angle, cstAdjustCoords); + DrawStretchPicRotated(x, y, w, h, s0, t0, s1, t1, mat, angle, true); //#modified-fva; END } -// fva's cst: added _cstAdjustCoords arg -void idDeviceContext::DrawStretchPicRotated(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, float angle, bool _cstAdjustCoords) { +// fva/DG: added adjustCoords argument for CstDoom3 anchored GUIs and our old +// scale-menus-to-4:3-fix, it basically replaces calling AdjustCoords(&x, &y, &w, &h) +// before calling this +void idDeviceContext::DrawStretchPicRotated(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, float angle, bool adjustCoords) { idDrawVert verts[4]; glIndex_t indexes[6]; @@ -651,15 +641,14 @@ void idDeviceContext::DrawStretchPicRotated(float x, float y, float w, float h, } //#modified-fva; BEGIN - if (_cstAdjustCoords) { - verts[0].xyz[0] = verts[0].xyz[0] * xScale + cst_xOffset; - verts[0].xyz[1] = verts[0].xyz[1] * yScale + cst_yOffset; - verts[1].xyz[0] = verts[1].xyz[0] * xScale + cst_xOffset; - verts[1].xyz[1] = verts[1].xyz[1] * yScale + cst_yOffset; - verts[2].xyz[0] = verts[2].xyz[0] * xScale + cst_xOffset; - verts[2].xyz[1] = verts[2].xyz[1] * yScale + cst_yOffset; - verts[3].xyz[0] = verts[3].xyz[0] * xScale + cst_xOffset; - verts[3].xyz[1] = verts[3].xyz[1] * yScale + cst_yOffset; + if (adjustCoords) { + for( int i=0; i<4; ++i) { + // Note: if cstAdjustCoords == false; cst_*Offset is 0, so that doesn't require special handling + float x = verts[i].xyz[0] * xScale + cst_xOffset; + float y = verts[i].xyz[1] * yScale + cst_yOffset; + verts[i].xyz[0] = x * fixScaleForMenu.x + fixOffsetForMenu.x; + verts[i].xyz[1] = y * fixScaleForMenu.y + fixOffsetForMenu.y; + } } //#modified-fva; END @@ -683,7 +672,7 @@ void idDeviceContext::DrawFilledRect( float x, float y, float w, float h, const AdjustCoords(&x, &y, &w, &h); DrawStretchPic( x, y, w, h, 0, 0, 0, 0, whiteImage); */ - DrawStretchPic(x, y, w, h, 0, 0, 0, 0, whiteImage, cstAdjustCoords); + DrawStretchPic(x, y, w, h, 0, 0, 0, 0, whiteImage, true); //#modified-fva; END } @@ -708,10 +697,10 @@ void idDeviceContext::DrawRect( float x, float y, float w, float h, float size, DrawStretchPic( x, y, w, size, 0, 0, 0, 0, whiteImage ); DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, whiteImage ); */ - DrawStretchPic(x, y + size, size, h - 2.0f * size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); - DrawStretchPic(x + w - size, y + size, size, h - 2.0f * size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); - DrawStretchPic(x, y, w, size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); - DrawStretchPic(x, y + h - size, w, size, 0, 0, 0, 0, whiteImage, cstAdjustCoords); + DrawStretchPic(x, y + size, size, h - 2.0f * size, 0, 0, 0, 0, whiteImage, true); + DrawStretchPic(x + w - size, y + size, size, h - 2.0f * size, 0, 0, 0, 0, whiteImage, true); + DrawStretchPic(x, y, w, size, 0, 0, 0, 0, whiteImage, true); + DrawStretchPic(x, y + h - size, w, size, 0, 0, 0, 0, whiteImage, true); //#modified-fva; END } @@ -752,17 +741,26 @@ void idDeviceContext::DrawCursor(float *x, float *y, float size) { renderSystem->SetColor(colorWhite); - // DG: I use this instead of plain AdjustCursorCoords and the following lines - // to scale menus and other fullscreen GUIs to 4:3 aspect ratio - // FIXME: how could this ever work with xScale = 0 or yScale = 0 ?! - //AdjustCursorCoords(x, y, &size, &size); + // DG: originally, this just called AdjustCoords() and then DrawStretchPic(). + // It had to be adjusted to scale menus and other fullscreen GUIs to 4:3 aspect ratio + // and for the CstDoom3 anchored GUIs, so all that is now done here + + // the following block used to be Adjust(Cursor)Coords() + // (no point in keeping that function when it's only used here) + *x *= xScale; + *y *= yScale; + size *= xScale; + // TODO: not sure if scaling it by both is the right thing to do.. + // but OTOH, probably one of them is always 1, at least when not using an anchor + // (and why would a cursor use an anchor) + size *= yScale; + + // the *actual* sizes used (but not set to *x and *y) need to apply the menu fixes float sizeW = size * fixScaleForMenu.x; float sizeH = size * fixScaleForMenu.y; float fixedX = *x * fixScaleForMenu.x + fixOffsetForMenu.x; float fixedY = *y * fixScaleForMenu.y + fixOffsetForMenu.y; - // FIXME: CSTD3 just comments the AdjustCoords() call out and uses *x and *y instead of fixedX/Y - DrawStretchPic(fixedX, fixedY, sizeW, sizeH, 0, 0, 1, 1, cursorImages[cursor]); } /* @@ -784,7 +782,7 @@ void idDeviceContext::PaintChar(float x,float y,float width,float height,float s AdjustCoords(&x, &y, &w, &h); DrawStretchPic(x, y, w, h, s, t, s2, t2, hShader); */ - DrawStretchPic(x, y, w, h, s, t, s2, t2, hShader, cstAdjustCoords); + DrawStretchPic(x, y, w, h, s, t, s2, t2, hShader, true); //#modified-fva; END } diff --git a/neo/ui/DeviceContext.h b/neo/ui/DeviceContext.h index 9c5fa3d4..e57d0f78 100644 --- a/neo/ui/DeviceContext.h +++ b/neo/ui/DeviceContext.h @@ -58,12 +58,12 @@ public: void DrawFilledRect(float x, float y, float width, float height, const idVec4 &color); int DrawText(const char *text, float textScale, int textAlign, idVec4 color, idRectangle rectDraw, bool wrap, int cursor = -1, bool calcOnly = false, idList *breaks = NULL, int limit = 0 ); void DrawMaterialRect( float x, float y, float w, float h, float size, const idMaterial *mat, const idVec4 &color); - // fva's cst: added _cstAdjustCoords arg - void DrawStretchPic(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, bool _cstAdjustCoords = false); + // fva/DG: added adjustCoords argument for CstDoom3 anchored GUIs and our old scale-menus-to-4:3-fix + void DrawStretchPic(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, bool adjustCoords = false); void DrawMaterialRotated(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex = 1.0, float scaley = 1.0, float angle = 0.0f); - // fva's cst: added _cstAdjustCoords arg - void DrawStretchPicRotated(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, float angle = 0.0f, bool _cstAdjustCoords = false); + // fva/DG: added adjustCoords argument for CstDoom3 anchored GUIs and our old scale-menus-to-4:3-fix + void DrawStretchPicRotated(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, float angle = 0.0f, bool adjustCoords = false); int CharWidth( const char c, float scale ); int TextWidth(const char *text, float scale, int limit); @@ -86,10 +86,9 @@ public: void DrawCursor(float *x, float *y, float size); void SetCursor(int n); - - // FIXME: CSTD3 comments AdjustCoords out, what does that mean for AdjustCursorCoords? + // DG: Note: not sure if AdjustCoords() works entirely as it should, but it seems + // good enough for the idRenderWindow with the mars globe in the main menu 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); diff --git a/neo/ui/Window.cpp b/neo/ui/Window.cpp index e64dbe17..8a6802b9 100644 --- a/neo/ui/Window.cpp +++ b/neo/ui/Window.cpp @@ -1282,6 +1282,10 @@ void idWindow::Redraw(float x, float y) { if (!cst_hudAdjustAspect.GetBool() || cstAnchor == idDeviceContext::CST_ANCHOR_NONE) { dc->SetSize(forceAspectWidth, forceAspectHeight); } else { + // DG: if this Window uses anchors, it already is aspect-ratio-aware + // so a potentially active menuscalefix must be disabled + // (else it's "fixed" twice => wrong ratio in other direction) + dc->SetMenuScaleFix(false); dc->CstSetSize(cstAnchor, cstAnchorTo, cstAnchorFactor); } //#modified-fva; END From f3192be0f87abac0b44cdf43b3beed2d0abdc3b0 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sat, 18 Jan 2025 03:44:37 +0100 Subject: [PATCH 3/4] Bump SAVEGAME_VERSION to 18 for the CstDoom3 GUI changes incl. backwards compat for older savegames. only partly useful: old savegames only work if you didn't change the gamedata, with the CstDoom3 .gui files, loading them crashes. I don't think that can be avoided, apparently Doom3 has no way to detect that the GUIs have changed? --- neo/framework/Licensee.h | 3 ++- neo/framework/Session.cpp | 3 +-- neo/ui/SimpleWindow.cpp | 14 +++++++++----- neo/ui/Window.cpp | 13 ++++++++----- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/neo/framework/Licensee.h b/neo/framework/Licensee.h index 53bb4374..ddcff1db 100644 --- a/neo/framework/Licensee.h +++ b/neo/framework/Licensee.h @@ -93,7 +93,8 @@ If you have questions concerning this license or the applicable additional terms // NOTE: a seperate core savegame version and game savegame version could be useful // 16: Doom v1.1 // 17: Doom v1.2 / D3XP. Can still read old v16 with defaults for new data -#define SAVEGAME_VERSION 17 +// 18: dhewm3 with CstDoom3 anchored window support - can still read v16 and v17, unless gamedata changed +#define SAVEGAME_VERSION 18 // <= Doom v1.1: 1. no DS_VERSION token ( default ) // Doom v1.2: 2 diff --git a/neo/framework/Session.cpp b/neo/framework/Session.cpp index 65f205e8..713132fa 100644 --- a/neo/framework/Session.cpp +++ b/neo/framework/Session.cpp @@ -2130,8 +2130,7 @@ bool idSessionLocal::LoadGame( const char *saveName ) { // check the version, if it doesn't match, cancel the loadgame, // but still load the map with the persistant playerInfo from the header // so that the player doesn't lose too much progress. - if ( savegameVersion != SAVEGAME_VERSION && - !( savegameVersion == 16 && SAVEGAME_VERSION == 17 ) ) { // handle savegame v16 in v17 + if ( savegameVersion < 16 || savegameVersion > SAVEGAME_VERSION ) { // dhewm3 supports savegames with v16 - v18 common->Warning( "Savegame Version mismatch: aborting loadgame and starting level with persistent data" ); loadingSaveGame = false; fileSystem->CloseFile( savegameFile ); diff --git a/neo/ui/SimpleWindow.cpp b/neo/ui/SimpleWindow.cpp index 4c986710..b5099b2e 100644 --- a/neo/ui/SimpleWindow.cpp +++ b/neo/ui/SimpleWindow.cpp @@ -27,6 +27,7 @@ If you have questions concerning this license or the applicable additional terms */ #include "sys/platform.h" +#include "framework/Session.h" #include "ui/DeviceContext.h" #include "ui/Window.h" #include "ui/UserInterfaceLocal.h" @@ -476,11 +477,14 @@ void idSimpleWindow::ReadFromSaveGame( idFile *savefile ) { shear.ReadFromSaveGame( savefile ); backGroundName.ReadFromSaveGame( savefile ); - //#modified-fva; BEGIN // FIXME: savegame version? - cstAnchor.ReadFromSaveGame(savefile); - cstAnchorTo.ReadFromSaveGame(savefile); - cstAnchorFactor.ReadFromSaveGame(savefile); - savefile->Read(&cstNoClipBackground, sizeof(cstNoClipBackground)); + //#modified-fva; BEGIN + // TODO: why does this have to be read from the savegame anyway, does it change? + if ( session->GetSaveGameVersion() >= 18 ) { + cstAnchor.ReadFromSaveGame(savefile); + cstAnchorTo.ReadFromSaveGame(savefile); + cstAnchorFactor.ReadFromSaveGame(savefile); + savefile->Read(&cstNoClipBackground, sizeof(cstNoClipBackground)); + } // else keep default values, I guess //#modified-fva; END int stringLen; diff --git a/neo/ui/Window.cpp b/neo/ui/Window.cpp index 8a6802b9..5c1196d6 100644 --- a/neo/ui/Window.cpp +++ b/neo/ui/Window.cpp @@ -3782,11 +3782,14 @@ void idWindow::ReadFromSaveGame( idFile *savefile ) { hideCursor = false; } - //#modified-fva; BEGIN // FIXME: savegame version? - cstAnchor.ReadFromSaveGame(savefile); - cstAnchorTo.ReadFromSaveGame(savefile); - cstAnchorFactor.ReadFromSaveGame(savefile); - savefile->Read(&cstNoClipBackground, sizeof(cstNoClipBackground)); + //#modified-fva; BEGIN + // TODO: why does this have to be read from the savegame anyway, does it change? + if ( session->GetSaveGameVersion() >= 18 ) { + cstAnchor.ReadFromSaveGame(savefile); + cstAnchorTo.ReadFromSaveGame(savefile); + cstAnchorFactor.ReadFromSaveGame(savefile); + savefile->Read(&cstNoClipBackground, sizeof(cstNoClipBackground)); + } // else keep default values, I guess //#modified-fva; END // Defined Vars From a97caf08366e438002c6b8373bb798fd4343c6d0 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 21 Jan 2025 03:06:41 +0100 Subject: [PATCH 4/4] Make cst_hudAdjustAspect default to 1 If GUIs with CST anchors are there, they should be displayed correctly. With standard GUIs this doesn't make a difference, so it doesn't hurt. --- neo/ui/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/ui/Window.cpp b/neo/ui/Window.cpp index 5c1196d6..bf900ae8 100644 --- a/neo/ui/Window.cpp +++ b/neo/ui/Window.cpp @@ -55,7 +55,7 @@ bool idWindow::registerIsTemporary[MAX_EXPRESSION_REGISTERS]; // statics to ass idCVar idWindow::gui_debug( "gui_debug", "0", CVAR_GUI | CVAR_BOOL, "" ); idCVar idWindow::gui_edit( "gui_edit", "0", CVAR_GUI | CVAR_BOOL, "" ); //#modified-fva; BEGIN -idCVar cst_hudAdjustAspect("cst_hudAdjustAspect", "0", CVAR_GUI | CVAR_BOOL | CVAR_ARCHIVE, "adjust the HUD's aspect when the screen aspect ratio isn't 4:3"); +idCVar cst_hudAdjustAspect("cst_hudAdjustAspect", "1", CVAR_GUI | CVAR_BOOL | CVAR_ARCHIVE, "adjust the HUD's aspect when the screen aspect ratio isn't 4:3"); //#modified-fva; END extern idCVar r_skipGuiShaders; // 1 = don't render any gui elements on surfaces