Skip to content

Commit b13c7f7

Browse files
committed
HUD scaling via triangle API
1 parent e760b9f commit b13c7f7

File tree

8 files changed

+452
-31
lines changed

8 files changed

+452
-31
lines changed

cl_dll/cdll_int.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ void InitInput();
5353
void EV_HookEvents();
5454
void IN_Commands();
5555

56+
void CL_DrawCrosshair();
57+
5658
/*
5759
================================
5860
HUD_GetHullBounds
@@ -208,6 +210,8 @@ int DLLEXPORT HUD_Redraw(float time, int intermission)
208210
{
209211
// RecClHudRedraw(time, intermission);
210212

213+
CL_DrawCrosshair();
214+
211215
gHUD.Redraw(time, 0 != intermission);
212216

213217
return 1;

cl_dll/cl_util.h

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,46 +44,51 @@ inline const char* CVAR_GET_STRING(const char* x) { return gEngfuncs.pfnGetCvarS
4444
inline struct cvar_s* CVAR_CREATE(const char* cv, const char* val, const int flags) { return gEngfuncs.pfnRegisterVariable((char*)cv, (char*)val, flags); }
4545

4646
#define SPR_Load (*gEngfuncs.pfnSPR_Load)
47-
#define SPR_Set (*gEngfuncs.pfnSPR_Set)
47+
void SPR_Set(HSPRITE hPic, int r, int g, int b);
4848
#define SPR_Frames (*gEngfuncs.pfnSPR_Frames)
4949
#define SPR_GetList (*gEngfuncs.pfnSPR_GetList)
5050

5151
// SPR_Draw draws a the current sprite as solid
52-
#define SPR_Draw (*gEngfuncs.pfnSPR_Draw)
52+
void SPR_Draw(int frame, int x, int y, const Rect* prc);
5353
// SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent)
54-
#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles)
54+
void SPR_DrawHoles(int frame, int x, int y, const Rect* prc);
5555
// SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency)
56-
#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive)
56+
void SPR_DrawAdditive(int frame, int x, int y, const Rect* prc);
5757

5858
// SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen.
5959
#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor)
6060
// SPR_DisableScissor disables the clipping rect
6161
#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor)
6262
//
63-
#define FillRGBA (*gEngfuncs.pfnFillRGBA)
63+
void FillRGBA(int x, int y, int width, int height, int r, int g, int b, int a);
6464

6565

66-
// ScreenHeight returns the height of the screen, in pixels
67-
#define ScreenHeight (gHUD.m_scrinfo.iHeight)
68-
// ScreenWidth returns the width of the screen, in pixels
69-
#define ScreenWidth (gHUD.m_scrinfo.iWidth)
66+
// ScreenHeight returns the reference height of the HUD
67+
#define ScreenHeight (gHUD.m_iConHeight)
68+
// ScreenWidth returns the reference width of the HUD
69+
#define ScreenWidth (gHUD.m_iConWidth)
70+
71+
// RealScreenHeight returns the height of the screen, in pixels
72+
#define RealScreenHeight (gHUD.m_scrinfo.iHeight)
73+
// RealScreenWidth returns the width of the screen, in pixels
74+
#define RealScreenWidth (gHUD.m_scrinfo.iWidth)
7075

7176
#define BASE_XRES 640.f
7277

7378
// use this to project world coordinates to screen coordinates
74-
#define XPROJECT(x) ((1.0f + (x)) * ScreenWidth * 0.5f)
75-
#define YPROJECT(y) ((1.0f - (y)) * ScreenHeight * 0.5f)
79+
#define XPROJECT(x) ((1.0f + (x)) * RealScreenWidth * 0.5f)
80+
#define YPROJECT(y) ((1.0f - (y)) * RealScreenHeight * 0.5f)
7681

77-
#define XRES(x) ((x) * ((float)ScreenWidth / 640))
78-
#define YRES(y) ((y) * ((float)ScreenHeight / 480))
79-
#define XRES_HD(x) ((x) * V_max(1, (float)ScreenWidth / 1280))
80-
#define YRES_HD(y) ((y) * V_max(1, (float)ScreenHeight / 720))
82+
#define XRES(x) ((x) * ((float)RealScreenWidth / 640))
83+
#define YRES(y) ((y) * ((float)RealScreenHeight / 480))
84+
#define XRES_HD(x) ((x) * V_max(1, (float)RealScreenWidth / 1280))
85+
#define YRES_HD(y) ((y) * V_max(1, (float)RealScreenHeight / 720))
8186

8287
#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
8388
#define ServerCmd (*gEngfuncs.pfnServerCmd)
8489
#define EngineClientCmd (*gEngfuncs.pfnClientCmd)
8590
#define EngineFilteredClientCmd (*gEngfuncs.pfnFilteredClientCmd)
86-
#define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
91+
void SetCrosshair(HSPRITE hspr, Rect rc, int r, int g, int b);
8792
#define AngleVectors (*gEngfuncs.pfnAngleVectors)
8893

8994

@@ -99,12 +104,20 @@ inline int TextMessageDrawChar(int x, int y, int number, int r, int g, int b)
99104

100105
inline int DrawConsoleString(int x, int y, const char* string)
101106
{
102-
return gEngfuncs.pfnDrawConsoleString(x, y, (char*)string);
107+
const int width = gEngfuncs.pfnDrawConsoleString(
108+
gHUD.m_flOffsetX + gHUD.m_flScaleX * x,
109+
gHUD.m_flOffsetY + gHUD.m_flScaleY * y,
110+
(char*)string);
111+
112+
return (width - gHUD.m_flOffsetX) / gHUD.m_flScaleX;
103113
}
104114

105115
inline void GetConsoleStringSize(const char* string, int* width, int* height)
106116
{
107117
gEngfuncs.pfnDrawConsoleStringLen(string, width, height);
118+
119+
*width = *width / gHUD.m_flScaleX;
120+
*height = *height / gHUD.m_flScaleY;
108121
}
109122

110123
inline int ConsoleStringLen(const char* string)

cl_dll/hud.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
#include "demo_api.h"
3131
#include "vgui_ScorePanel.h"
3232

33+
#include "com_model.h"
34+
#include "r_studioint.h"
35+
36+
extern engine_studio_api_t IEngineStudio;
37+
3338
hud_player_info_t g_PlayerInfoList[MAX_PLAYERS_HUD + 1]; // player info from the engine
3439
extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS_HUD + 1]; // additional player info sent directly to the client dll
3540

@@ -86,6 +91,7 @@ cvar_t* cl_rollangle = nullptr;
8691
cvar_t* cl_rollspeed = nullptr;
8792
cvar_t* cl_bobtilt = nullptr;
8893
cvar_t* r_decals = nullptr;
94+
cvar_t* crosshair = nullptr;
8995

9096
void ShutdownInput();
9197

@@ -336,6 +342,8 @@ void CHud::Init()
336342
cl_rollspeed = CVAR_CREATE("cl_rollspeed", "200", FCVAR_ARCHIVE);
337343
cl_bobtilt = CVAR_CREATE("cl_bobtilt", "0", FCVAR_ARCHIVE);
338344
r_decals = gEngfuncs.pfnGetCvarPointer("r_decals");
345+
m_pCvarScale = CVAR_CREATE("hud_scale", "1", FCVAR_ARCHIVE);
346+
crosshair = gEngfuncs.pfnGetCvarPointer("crosshair");
339347

340348
m_pSpriteList = NULL;
341349

@@ -423,6 +431,10 @@ void CHud::VidInit()
423431
m_scrinfo.iSize = sizeof(m_scrinfo);
424432
GetScreenInfo(&m_scrinfo);
425433

434+
m_bShouldScale = IEngineStudio.IsHardware() && m_pCvarScale->value != 0.0F;
435+
436+
UpdateScreenInfo();
437+
426438
// ----------
427439
// Load Sprites
428440
// ---------
@@ -707,3 +719,59 @@ float CHud::GetSensitivity()
707719
{
708720
return m_flMouseSensitivity;
709721
}
722+
723+
bool CHud::ShouldScale()
724+
{
725+
return m_bShouldScale;
726+
}
727+
728+
void CHud::UpdateScreenInfo()
729+
{
730+
m_iScaleValue = m_pCvarScale->value;
731+
732+
if (!ShouldScale())
733+
{
734+
// default values for functions that may still reference them
735+
736+
m_iConWidth = RealScreenWidth;
737+
m_iConHeight = RealScreenHeight;
738+
739+
m_flScaleX = m_flScaleY = 1.0F;
740+
m_flOffsetX = m_flOffsetY = 0.0F;
741+
742+
return;
743+
}
744+
745+
// hud reference size
746+
m_iConWidth = V_min(640, RealScreenWidth);
747+
m_iConHeight = V_min(480, RealScreenHeight);
748+
749+
// set the scaling factor by using the minor axis
750+
751+
if (RealScreenWidth >= RealScreenHeight)
752+
{
753+
// letterbox or widescreen
754+
755+
m_flScaleX = m_flScaleY = RealScreenHeight / (float)ScreenHeight;
756+
757+
// adapt to the real aspect ratio
758+
m_iConWidth = m_iConHeight * (RealScreenWidth / (float)RealScreenHeight);
759+
}
760+
else
761+
{
762+
// portrait (half-life mobile confirmed?!)
763+
764+
m_flScaleX = m_flScaleY = RealScreenWidth / (float)ScreenWidth;
765+
766+
// adapt to the real aspect ratio
767+
m_iConHeight = m_iConWidth * (RealScreenHeight / (float)RealScreenWidth);
768+
}
769+
770+
// keep the reference sizes even
771+
m_iConWidth = (int)(m_iConWidth / 2) * 2;
772+
m_iConHeight = (int)(m_iConHeight / 2) * 2;
773+
774+
// set the scaling offsets
775+
m_flOffsetX = (RealScreenWidth - ScreenWidth * m_flScaleX) / 2.0;
776+
m_flOffsetY = (RealScreenHeight - ScreenHeight * m_flScaleY) / 2.0;
777+
}

cl_dll/hud.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,19 @@ class CHud
607607
void AddHudElem(CHudBase* p);
608608

609609
float GetSensitivity();
610+
611+
cvar_t* m_pCvarScale;
612+
int m_iScaleValue;
613+
bool m_bShouldScale;
614+
int m_iConWidth;
615+
int m_iConHeight;
616+
float m_flScaleX;
617+
float m_flScaleY;
618+
float m_flOffsetX;
619+
float m_flOffsetY;
620+
621+
bool ShouldScale();
622+
void UpdateScreenInfo();
610623
};
611624

612625
extern CHud gHUD;

cl_dll/hud_redraw.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ void CHud::Think()
4141
m_scrinfo.iSize = sizeof(m_scrinfo);
4242
GetScreenInfo(&m_scrinfo);
4343

44+
if (m_iScaleValue != (int)m_pCvarScale->value)
45+
{
46+
UpdateScreenInfo();
47+
}
48+
4449
int newfov;
4550
HUDLIST* pList = m_pHudList;
4651

@@ -215,7 +220,12 @@ void ScaleColors(int& r, int& g, int& b, int a)
215220

216221
int CHud::DrawHudString(int xpos, int ypos, int iMaxX, const char* szIt, int r, int g, int b)
217222
{
218-
return xpos + gEngfuncs.pfnDrawString(xpos, ypos, szIt, r, g, b);
223+
const int width = gEngfuncs.pfnDrawString(
224+
m_flOffsetX + m_flScaleX * xpos,
225+
m_flOffsetY + m_flScaleY * ypos,
226+
szIt, r, g, b);
227+
228+
return xpos + (width - m_flOffsetX) / m_flScaleX;
219229
}
220230

221231
int CHud::DrawHudNumberString(int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b)
@@ -228,7 +238,12 @@ int CHud::DrawHudNumberString(int xpos, int ypos, int iMinX, int iNumber, int r,
228238
// draws a string from right to left (right-aligned)
229239
int CHud::DrawHudStringReverse(int xpos, int ypos, int iMinX, const char* szString, int r, int g, int b)
230240
{
231-
return xpos - gEngfuncs.pfnDrawStringReverse(xpos, ypos, szString, r, g, b);
241+
const int width = gEngfuncs.pfnDrawStringReverse(
242+
m_flOffsetX + m_flScaleX * xpos,
243+
m_flOffsetY + m_flScaleY * ypos,
244+
szString, r, g, b);
245+
246+
return xpos + (width - m_flOffsetX) / m_flScaleX;
232247
}
233248

234249
int CHud::DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b)

cl_dll/message.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,18 @@ int CHudMessage::XPosition(float x, int width, int totalWidth)
9696

9797
if (x == -1)
9898
{
99-
xPos = (ScreenWidth - width) / 2;
99+
xPos = (RealScreenWidth - width) / 2;
100100
}
101101
else
102102
{
103103
if (x < 0)
104-
xPos = (1.0 + x) * ScreenWidth - totalWidth; // Alight right
104+
xPos = (1.0 + x) * RealScreenWidth - totalWidth; // Alight right
105105
else
106-
xPos = x * ScreenWidth;
106+
xPos = x * RealScreenWidth;
107107
}
108108

109-
if (xPos + width > ScreenWidth)
110-
xPos = ScreenWidth - width;
109+
if (xPos + width > RealScreenWidth)
110+
xPos = RealScreenWidth - width;
111111
else if (xPos < 0)
112112
xPos = 0;
113113

@@ -120,18 +120,18 @@ int CHudMessage::YPosition(float y, int height)
120120
int yPos;
121121

122122
if (y == -1) // Centered?
123-
yPos = (ScreenHeight - height) * 0.5;
123+
yPos = (RealScreenHeight - height) * 0.5;
124124
else
125125
{
126126
// Alight bottom?
127127
if (y < 0)
128-
yPos = (1.0 + y) * ScreenHeight - height; // Alight bottom
128+
yPos = (1.0 + y) * RealScreenHeight - height; // Alight bottom
129129
else // align top
130-
yPos = y * ScreenHeight;
130+
yPos = y * RealScreenHeight;
131131
}
132132

133-
if (yPos + height > ScreenHeight)
134-
yPos = ScreenHeight - height;
133+
if (yPos + height > RealScreenHeight)
134+
yPos = RealScreenHeight - height;
135135
else if (yPos < 0)
136136
yPos = 0;
137137

@@ -196,7 +196,7 @@ void CHudMessage::MessageScanNextChar()
196196

197197
if (m_parms.pMessage->effect == 1 && m_parms.charTime != 0)
198198
{
199-
if (m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[m_parms.text]) <= ScreenWidth)
199+
if (m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[m_parms.text]) <= RealScreenWidth)
200200
TextMessageDrawChar(m_parms.x, m_parms.y, m_parms.text, m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2);
201201
}
202202
}
@@ -305,7 +305,7 @@ void CHudMessage::MessageDrawScan(client_textmessage_t* pMessage, float time)
305305
int next = m_parms.x + gHUD.m_scrinfo.charWidths[m_parms.text];
306306
MessageScanNextChar();
307307

308-
if (m_parms.x >= 0 && m_parms.y >= 0 && next <= ScreenWidth)
308+
if (m_parms.x >= 0 && m_parms.y >= 0 && next <= RealScreenWidth)
309309
TextMessageDrawChar(m_parms.x, m_parms.y, m_parms.text, m_parms.r, m_parms.g, m_parms.b);
310310
m_parms.x = next;
311311
}

0 commit comments

Comments
 (0)