From 038ce0f5fdc9af040f78a5bdaf5f95669d5f54c2 Mon Sep 17 00:00:00 2001 From: Martin Gerhardy Date: Thu, 16 May 2024 00:22:15 +0200 Subject: [PATCH] CLIENT: implemented con_scale and reduced code duplication in character rendering used stuff from Con_CheckSize from quake3e --- code/client/cl_console.c | 127 ++++++++++++++++++++++++++------------- code/client/cl_keys.c | 33 +++------- code/client/cl_main.c | 3 + code/client/cl_scrn.c | 91 ++++++++++++---------------- code/client/client.h | 13 +--- code/client/keys.h | 3 +- code/qcommon/q_shared.c | 3 + code/qcommon/q_shared.h | 8 +++ 8 files changed, 148 insertions(+), 133 deletions(-) diff --git a/code/client/cl_console.c b/code/client/cl_console.c index fef9cff2e..20db83c49 100644 --- a/code/client/cl_console.c +++ b/code/client/cl_console.c @@ -24,7 +24,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "client.h" int g_console_field_width = 78; +static fontSize_t fontSize; +#define MAX_CONSOLE_WIDTH 120 #define NUM_CON_TIMES 4 #define CON_TEXTSIZE 32768 @@ -38,6 +40,7 @@ typedef struct { int linewidth; // characters across screen int totallines; // total lines in console scrollback + int viswidth; float xadjust; // for wide aspect screens @@ -51,11 +54,12 @@ typedef struct { vec4_t color; } console_t; -console_t con; +static console_t con; -cvar_t *con_conspeed; -cvar_t *con_autoclear; -cvar_t *con_notifytime; +static cvar_t *con_conspeed; +static cvar_t *con_autoclear; +static cvar_t *con_notifytime; +static cvar_t *con_scale; #define DEFAULT_CONSOLE_WIDTH 78 @@ -156,7 +160,7 @@ static void Con_MessageMode4_f(void) { Con_Clear_f ================ */ -void Con_Clear_f(void) { +static void Con_Clear_f(void) { int i; for (i = 0; i < CON_TEXTSIZE; i++) { @@ -265,54 +269,79 @@ If the line width has changed, reformat the buffer. ================ */ void Con_CheckResize(void) { - int i, j, width, oldwidth, oldtotallines, numlines, numchars; - short tbuf[CON_TEXTSIZE]; + float scale; - width = (SCREEN_WIDTH / SMALLCHAR_WIDTH) - 2; - - if (width == con.linewidth) + if (con.viswidth == cls.glconfig.vidWidth && !con_scale->modified) { return; + } + + scale = con_scale->value; + + con.viswidth = cls.glconfig.vidWidth; - if (width < 1) // video hasn't been initialized yet + fontSize.w = SMALLCHAR_WIDTH * scale; + fontSize.h = SMALLCHAR_HEIGHT * scale; + + if (cls.glconfig.vidWidth == 0) // video hasn't been initialized yet { - width = DEFAULT_CONSOLE_WIDTH; + int width; + g_console_field_width = DEFAULT_CONSOLE_WIDTH; + width = DEFAULT_CONSOLE_WIDTH * scale; con.linewidth = width; con.totallines = CON_TEXTSIZE / con.linewidth; - for (i = 0; i < CON_TEXTSIZE; i++) - con.text[i] = (ColorIndex(COLOR_WHITE) << 8) | ' '; + Con_Clear_f(); } else { + int oldcurrent, oldwidth, oldtotallines; + short tbuf[CON_TEXTSIZE]; + int i, j, width, numlines, numchars; + + width = ((cls.glconfig.vidWidth / fontSize.w) - 2); + + g_console_field_width = width; + g_consoleField.widthInChars = g_console_field_width; + + if (width > MAX_CONSOLE_WIDTH) + width = MAX_CONSOLE_WIDTH; + oldwidth = con.linewidth; - con.linewidth = width; oldtotallines = con.totallines; - con.totallines = CON_TEXTSIZE / con.linewidth; - numlines = oldtotallines; + oldcurrent = con.current; - if (con.totallines < numlines) - numlines = con.totallines; + con.linewidth = width; + con.totallines = CON_TEXTSIZE / con.linewidth; numchars = oldwidth; - - if (con.linewidth < numchars) + if (numchars > con.linewidth) numchars = con.linewidth; + if (oldcurrent > oldtotallines) + numlines = oldtotallines; + else + numlines = oldcurrent + 1; + + if (numlines > con.totallines) + numlines = con.totallines; + Com_Memcpy(tbuf, con.text, CON_TEXTSIZE * sizeof(short)); - for (i = 0; i < CON_TEXTSIZE; i++) + for (i = 0; i < CON_TEXTSIZE; i++) con.text[i] = (ColorIndex(COLOR_WHITE) << 8) | ' '; for (i = 0; i < numlines; i++) { - for (j = 0; j < numchars; j++) { - con.text[(con.totallines - 1 - i) * con.linewidth + j] = - tbuf[((con.current - i + oldtotallines) % oldtotallines) * oldwidth + j]; - } + const short *src = &tbuf[((oldcurrent - i + oldtotallines) % oldtotallines) * oldwidth]; + short *dst = &con.text[(numlines - 1 - i) * con.linewidth]; + for (j = 0; j < numchars; j++) + *dst++ = *src++; } Con_ClearNotify(); + + con.current = numlines - 1; } - con.current = con.totallines - 1; con.display = con.current; + con_scale->modified = qfalse; } /* @@ -337,6 +366,11 @@ void Con_Init(void) { con_notifytime = Cvar_Get("con_notifytime", "-4", 0); con_conspeed = Cvar_Get("scr_conspeed", "3", 0); con_autoclear = Cvar_Get("con_autoclear", "1", CVAR_ARCHIVE); + con_scale = Cvar_Get("con_scale", "1", CVAR_ARCHIVE); + Cvar_CheckRange(con_scale, 1, 4, qtrue); + + fontSize.w = SMALLCHAR_WIDTH * con_scale->value; + fontSize.h = SMALLCHAR_HEIGHT * con_scale->value; Field_Clear(&g_consoleField); g_consoleField.widthInChars = g_console_field_width; @@ -426,8 +460,15 @@ void CL_ConsolePrint(const char *txt) { } if (!con.initialized) { + static cvar_t null_cvar = { 0 }; + fontSize.w = SMALLCHAR_WIDTH; + fontSize.h = SMALLCHAR_HEIGHT; con.color[0] = con.color[1] = con.color[2] = con.color[3] = 1.0f; + con.viswidth = -9999; con.linewidth = -1; + con_scale = &null_cvar; + con_scale->value = 1.0f; + con_scale->modified = qtrue; Con_CheckResize(); con.initialized = qtrue; } @@ -508,13 +549,13 @@ static void Con_DrawInput(void) { return; } - y = con.vislines - (SMALLCHAR_HEIGHT * 2); + y = con.vislines - (fontSize.h * 2); re.SetColor(con.color); - SCR_DrawSmallChar(con.xadjust + 1 * SMALLCHAR_WIDTH, y, ']'); + SCR_DrawChar(con.xadjust + 1 * fontSize.w, y, ']', fontSize); - Field_Draw(&g_consoleField, con.xadjust + 2 * SMALLCHAR_WIDTH, y, SCREEN_WIDTH - 3 * SMALLCHAR_WIDTH, qtrue, qtrue); + Field_Draw(&g_consoleField, con.xadjust + 2 * fontSize.w, y, SCREEN_WIDTH - 3 * fontSize.w, qtrue, qtrue, fontSize); } /* @@ -559,10 +600,10 @@ void Con_DrawNotify(void) { currentColor = ColorIndexForNumber(text[x] >> 8); re.SetColor(g_color_table[currentColor]); } - SCR_DrawSmallChar(cl_conXOffset->integer + con.xadjust + (x + 1) * SMALLCHAR_WIDTH, v, text[x] & 0xff); + SCR_DrawChar(cl_conXOffset->integer + con.xadjust + (x + 1) * fontSize.w, v, text[x] & 0xff, fontSize); } - v += SMALLCHAR_HEIGHT; + v += fontSize.h; } re.SetColor(NULL); @@ -574,14 +615,14 @@ void Con_DrawNotify(void) { // draw the chat line if (Key_GetCatcher() & KEYCATCH_MESSAGE) { if (chat_team) { - SCR_DrawBigString(8, v, "say_team:", 1.0f, qfalse); + SCR_DrawString(8, v, "say_team:", qfalse, FONT_BIG); skip = 10; } else { - SCR_DrawBigString(8, v, "say:", 1.0f, qfalse); + SCR_DrawString(8, v, "say:", qfalse, FONT_BIG); skip = 5; } - Field_BigDraw(&chatField, skip * BIGCHAR_WIDTH, v, SCREEN_WIDTH - (skip + 1) * BIGCHAR_WIDTH, qtrue, qtrue); + Field_Draw(&chatField, skip * FONT_BIG.w, v, SCREEN_WIDTH - (skip + 1) * FONT_BIG.w, qtrue, qtrue, FONT_BIG); } } @@ -635,23 +676,23 @@ static void Con_DrawSolidConsole(float frac) { i = strlen(Q3_VERSION); for (x = 0; x < i; x++) { - SCR_DrawSmallChar(cls.glconfig.vidWidth - (i - x + 1) * SMALLCHAR_WIDTH, lines - SMALLCHAR_HEIGHT, - Q3_VERSION[x]); + SCR_DrawChar(cls.glconfig.vidWidth - (i - x + 1) * fontSize.w, lines - fontSize.h, + Q3_VERSION[x], fontSize); } // draw the text con.vislines = lines; - rows = (lines - SMALLCHAR_HEIGHT) / SMALLCHAR_HEIGHT; // rows of text to draw + rows = (lines - fontSize.h) / fontSize.h; // rows of text to draw - y = lines - (SMALLCHAR_HEIGHT * 3); + y = lines - (fontSize.h * 3); // draw from the bottom up if (con.display != con.current) { // draw arrows to show the buffer is backscrolled re.SetColor(g_color_table[ColorIndex(COLOR_RED)]); for (x = 0; x < con.linewidth; x += 4) - SCR_DrawSmallChar(con.xadjust + (x + 1) * SMALLCHAR_WIDTH, y, '^'); - y -= SMALLCHAR_HEIGHT; + SCR_DrawChar(con.xadjust + (x + 1) * fontSize.w, y, '^', fontSize); + y -= fontSize.h; rows--; } @@ -664,7 +705,7 @@ static void Con_DrawSolidConsole(float frac) { currentColor = 7; re.SetColor(g_color_table[currentColor]); - for (i = 0; i < rows; i++, y -= SMALLCHAR_HEIGHT, row--) { + for (i = 0; i < rows; i++, y -= fontSize.h, row--) { if (row < 0) break; if (con.current - row >= con.totallines) { @@ -683,7 +724,7 @@ static void Con_DrawSolidConsole(float frac) { currentColor = ColorIndexForNumber(text[x] >> 8); re.SetColor(g_color_table[currentColor]); } - SCR_DrawSmallChar(con.xadjust + (x + 1) * SMALLCHAR_WIDTH, y, text[x] & 0xff); + SCR_DrawChar(con.xadjust + (x + 1) * fontSize.w, y, text[x] & 0xff, fontSize); } } diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c index 85925f979..185a60752 100644 --- a/code/client/cl_keys.c +++ b/code/client/cl_keys.c @@ -328,8 +328,11 @@ Handles horizontal scrolling and cursor blinking x, y, and width are in pixels =================== */ -static void Field_VariableSizeDraw(field_t *edit, int x, int y, int width, int size, qboolean showCursor, +static void Field_VariableSizeDraw(field_t *edit, int x, int y, int width, int fontsize, qboolean showCursor, qboolean noColorEscape) { +} + +void Field_Draw(field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape, fontSize_t fontsize) { int len; int drawLen; int prestep; @@ -366,15 +369,7 @@ static void Field_VariableSizeDraw(field_t *edit, int x, int y, int width, int s str[drawLen] = 0; // draw it - if (size == SMALLCHAR_WIDTH) { - float color[4]; - - color[0] = color[1] = color[2] = color[3] = 1.0f; - SCR_DrawSmallStringExt(x, y, str, color, qfalse, noColorEscape); - } else { - // draw big string with drop shadow - SCR_DrawBigString(x, y, str, 1.0f, noColorEscape); - } + SCR_DrawString(x, y, str, noColorEscape, fontsize); // draw the cursor if (showCursor) { @@ -390,24 +385,12 @@ static void Field_VariableSizeDraw(field_t *edit, int x, int y, int width, int s i = drawLen - strlen(str); - if (size == SMALLCHAR_WIDTH) { - SCR_DrawSmallChar(x + (edit->cursor - prestep - i) * size, y, cursorChar); - } else { - str[0] = cursorChar; - str[1] = 0; - SCR_DrawBigString(x + (edit->cursor - prestep - i) * size, y, str, 1.0f, qfalse); - } + str[0] = cursorChar; + str[1] = 0; + SCR_DrawString(x + (edit->cursor - prestep - i) * fontsize.w, y, str, qfalse, fontsize); } } -void Field_Draw(field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape) { - Field_VariableSizeDraw(edit, x, y, width, SMALLCHAR_WIDTH, showCursor, noColorEscape); -} - -void Field_BigDraw(field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape) { - Field_VariableSizeDraw(edit, x, y, width, BIGCHAR_WIDTH, showCursor, noColorEscape); -} - static void Field_CharEvent(field_t *edit, int ch); /* diff --git a/code/client/cl_main.c b/code/client/cl_main.c index 7b978248e..89beaf80f 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -2788,6 +2788,9 @@ static void CL_InitRenderer(void) { cls.charsetShader = re.RegisterShader("fontascii"); cls.whiteShader = re.RegisterShader("white"); cls.consoleShader = re.RegisterShader("console"); + + Con_CheckResize(); + g_console_field_width = cls.glconfig.vidWidth / SMALLCHAR_WIDTH - 2; g_consoleField.widthInChars = g_console_field_width; } diff --git a/code/client/cl_scrn.c b/code/client/cl_scrn.c index 0ab71f893..e6310a59c 100644 --- a/code/client/cl_scrn.c +++ b/code/client/cl_scrn.c @@ -98,7 +98,7 @@ void SCR_DrawPic(float x, float y, float width, float height, qhandle_t hShader) ** SCR_DrawChar ** chars are drawn at 640*480 virtual screen size */ -static void SCR_DrawChar(int x, int y, float size, int ch) { +static void SCR_DrawCharExt(int x, int y, float size, int ch) { int row, col; float frow, fcol; float ax, ay, aw, ah; @@ -129,35 +129,6 @@ static void SCR_DrawChar(int x, int y, float size, int ch) { re.DrawStretchPic(ax, ay, aw, ah, fcol, frow, fcol + size, frow + size, cls.charsetShader); } -/* -** SCR_DrawSmallChar -** small chars are drawn at native screen resolution -*/ -void SCR_DrawSmallChar(int x, int y, int ch) { - int row, col; - float frow, fcol; - float size; - - ch &= 255; - - if (ch == ' ') { - return; - } - - if (y < -SMALLCHAR_HEIGHT) { - return; - } - - row = ch >> 4; - col = ch & 15; - - frow = row * 0.0625f; - fcol = col * 0.0625f; - size = 0.0625f; - - re.DrawStretchPic(x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, fcol, frow, fcol + size, frow + size, cls.charsetShader); -} - /* ================== SCR_DrawBigString[Color] @@ -185,7 +156,7 @@ static void SCR_DrawStringExt(int x, int y, float size, const char *string, floa s += 2; continue; } - SCR_DrawChar(xx + 1, y + 1, size, *s); + SCR_DrawCharExt(xx + 1, y + 1, size, *s); xx += size; s++; } @@ -206,19 +177,40 @@ static void SCR_DrawStringExt(int x, int y, float size, const char *string, floa continue; } } - SCR_DrawChar(xx, y, size, *s); + SCR_DrawCharExt(xx, y, size, *s); xx += size; s++; } re.SetColor(NULL); } -void SCR_DrawBigString(int x, int y, const char *s, float alpha, qboolean noColorEscape) { - float color[4]; +/* +** SCR_DrawSmallChar +** small chars are drawn at native screen resolution +*/ +void SCR_DrawChar(int x, int y, int ch, fontSize_t fsize) { + int row, col; + float frow, fcol; + float size; + + ch &= 255; + + if (ch == ' ') { + return; + } + + if (y < -fsize.h) { + return; + } + + row = ch >> 4; + col = ch & 15; - color[0] = color[1] = color[2] = 1.0f; - color[3] = alpha; - SCR_DrawStringExt(x, y, BIGCHAR_WIDTH, s, color, qfalse, noColorEscape); + frow = row * 0.0625f; + fcol = col * 0.0625f; + size = 0.0625f; + + re.DrawStretchPic(x, y, fsize.h, fsize.h, fcol, frow, fcol + size, frow + size, cls.charsetShader); } /* @@ -229,11 +221,13 @@ Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. ================== */ -void SCR_DrawSmallStringExt(int x, int y, const char *string, float *setColor, qboolean forceColor, - qboolean noColorEscape) { +void SCR_DrawString(int x, int y, const char *string, qboolean noColorEscape, fontSize_t fontsize) { vec4_t color; const char *s; int xx; + vec4_t setColor; + + setColor[0] = setColor[1] = setColor[2] = setColor[3] = 1.0f; // draw the colored text s = string; @@ -241,18 +235,16 @@ void SCR_DrawSmallStringExt(int x, int y, const char *string, float *setColor, q re.SetColor(setColor); while (*s) { if (Q_IsColorString(s)) { - if (!forceColor) { - Com_Memcpy(color, g_color_table[ColorIndex(*(s + 1))], sizeof(color)); - color[3] = setColor[3]; - re.SetColor(color); - } + Com_Memcpy(color, g_color_table[ColorIndex(*(s + 1))], sizeof(color)); + color[3] = setColor[3]; + re.SetColor(color); if (!noColorEscape) { s += 2; continue; } } - SCR_DrawSmallChar(xx, y, *s); - xx += SMALLCHAR_WIDTH; + SCR_DrawChar(xx, y, *s, fontsize); + xx += fontsize.w; s++; } re.SetColor(NULL); @@ -277,13 +269,6 @@ static int SCR_Strlen(const char *str) { return count; } -/* -** SCR_GetBigStringWidth -*/ -int SCR_GetBigStringWidth(const char *str) { - return SCR_Strlen(str) * BIGCHAR_WIDTH; -} - //=============================================================================== /* diff --git a/code/client/client.h b/code/client/client.h index ef8db7568..21cac2867 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -528,12 +528,9 @@ qboolean CL_UpdateVisiblePings_f(int source); // // console // -void Con_DrawCharacter(int cx, int line, int num); - void Con_CheckResize(void); void Con_Init(void); void Con_Shutdown(void); -void Con_Clear_f(void); void Con_ToggleConsole_f(void); void Con_DrawNotify(void); void Con_ClearNotify(void); @@ -551,22 +548,18 @@ void CL_SaveConsoleHistory(void); // // cl_scrn.c // + void SCR_Init(void); void SCR_UpdateScreen(void); void SCR_DebugGraph(float value); -int SCR_GetBigStringWidth(const char *str); // returns in virtual 640x480 coordinates - void SCR_AdjustFrom640(float *x, float *y, float *w, float *h); void SCR_FillRect(float x, float y, float width, float height, const float *color); void SCR_DrawPic(float x, float y, float width, float height, qhandle_t hShader); -void SCR_DrawBigString(int x, int y, const char *s, float alpha, - qboolean noColorEscape); // draws a string with embedded color control characters with fade -void SCR_DrawSmallStringExt(int x, int y, const char *string, float *setColor, qboolean forceColor, - qboolean noColorEscape); -void SCR_DrawSmallChar(int x, int y, int ch); +void SCR_DrawString(int x, int y, const char *string, qboolean noColorEscape, fontSize_t fontsize); +void SCR_DrawChar(int x, int y, int ch, fontSize_t fontsize); // // cl_cin.c diff --git a/code/client/keys.h b/code/client/keys.h index 9354b9a1d..5690320da 100644 --- a/code/client/keys.h +++ b/code/client/keys.h @@ -31,8 +31,7 @@ typedef struct { extern qkey_t keys[MAX_KEYS]; -void Field_Draw(field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape); -void Field_BigDraw(field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape); +void Field_Draw(field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape, fontSize_t fontsize); #define COMMAND_HISTORY 32 extern field_t historyEditLines[COMMAND_HISTORY]; diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c index ece5926ee..662724f46 100644 --- a/code/qcommon/q_shared.c +++ b/code/qcommon/q_shared.c @@ -28,6 +28,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA const int demo_protocols[] = {66, 67, PROTOCOL_LEGACY_VERSION, 69, 70, 71, PROTOCOL_VERSION, 0}; +fontSize_t FONT_SMALL = {SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT}; +fontSize_t FONT_BIG = {BIGCHAR_WIDTH, BIGCHAR_HEIGHT}; + // ^[0-9a-zA-Z] qboolean Q_IsColorString(const char *p) { if (!p) diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index a3dfff9a4..b706af10a 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -401,6 +401,14 @@ extern vec3_t bytedirs[NUMVERTEXNORMALS]; #define GIANTCHAR_WIDTH 32 #define GIANTCHAR_HEIGHT 48 +typedef struct { + int w; + int h; +} fontSize_t; + +extern fontSize_t FONT_SMALL; +extern fontSize_t FONT_BIG; + extern vec4_t colorBlack; extern vec4_t colorRed; extern vec4_t colorGreen;