From ccb9827b031ca3e7d68fa293f7c9736c48d05e90 Mon Sep 17 00:00:00 2001
From: myT <>
Date: Tue, 29 Aug 2023 00:43:26 +0200
Subject: [PATCH] added GUI for options and front-end stats
added keycatchgui
added VS2019 project files
renamed r_swapInterval
removed r_speeds
fixed r_mode 1 cursor
fixed device caps
---
code/client/cl_cgame.cpp | 1 +
code/client/cl_console.cpp | 101 +-
code/client/cl_imgui.cpp | 17 +-
code/client/cl_input.cpp | 42 +-
code/client/cl_main.cpp | 729 ++++++++++++-
code/client/cl_scrn.cpp | 128 +--
code/client/cl_ui.cpp | 1 +
code/client/client.h | 2 -
code/client/client_help.h | 6 -
code/client/snd_main.cpp | 18 +-
code/imgui/Sweet16Mono.h | 130 +++
code/qcommon/common.cpp | 55 +-
code/qcommon/cvar.cpp | 211 +++-
code/qcommon/q_shared.h | 34 +-
code/qcommon/qcommon.h | 38 +
code/renderer/rhi_d3d12.cpp | 83 +-
code/renderer/tr_cmds.cpp | 12 +-
code/renderer/tr_gui.cpp | 999 +++++++++++++++++-
code/renderer/tr_help.h | 5 +
code/renderer/tr_init.cpp | 457 ++++++--
code/renderer/tr_local.h | 10 +-
code/renderer/tr_public.h | 5 +-
code/win32/win_glimp.cpp | 2 +-
makefiles/bsd_gmake/cnq3-server.make | 36 -
makefiles/linux_gmake/cnq3-server.make | 36 -
makefiles/premake5.lua | 4 +-
makefiles/windows_vs2019/cnq3-server.vcxproj | 18 -
.../cnq3-server.vcxproj.filters | 60 --
makefiles/windows_vs2019/cnq3.vcxproj | 1 +
makefiles/windows_vs2019/cnq3.vcxproj.filters | 3 +
makefiles/windows_vs2022/botlib.vcxproj.user | 4 +
makefiles/windows_vs2022/cnq3-server.vcxproj | 18 -
.../cnq3-server.vcxproj.filters | 60 --
makefiles/windows_vs2022/cnq3.vcxproj | 1 +
makefiles/windows_vs2022/cnq3.vcxproj.filters | 3 +
35 files changed, 2665 insertions(+), 665 deletions(-)
create mode 100644 code/imgui/Sweet16Mono.h
create mode 100644 makefiles/windows_vs2022/botlib.vcxproj.user
diff --git a/code/client/cl_cgame.cpp b/code/client/cl_cgame.cpp
index 2118476..bd8c5c3 100644
--- a/code/client/cl_cgame.cpp
+++ b/code/client/cl_cgame.cpp
@@ -764,6 +764,7 @@ void CL_InitCGame()
CL_SetMaxFPS( 20 );
VM_Call( cgvm, CG_INIT, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum );
CL_SetMaxFPS( 0 );
+ CL_SetMenuData( qtrue );
// send a usercmd this frame, which will cause the server to send us the first snapshot
cls.state = CA_PRIMED;
diff --git a/code/client/cl_console.cpp b/code/client/cl_console.cpp
index 7e4374e..65d0840 100644
--- a/code/client/cl_console.cpp
+++ b/code/client/cl_console.cpp
@@ -33,22 +33,22 @@ static cvar_t* con_speed;
static cvar_t* con_drawHelp;
#define COLOR_LIST(X) \
- X(BG, "101013F6", qtrue, "RGBA color of the background") \
- X(Border, "4778B2FF", qtrue, "RGBA color of the border") \
- X(Arrow, "4778B2FF", qtrue, "RGBA color of backscroll arrows") \
- X(Shadow, "000000FF", qtrue, "RGBA color of text shadows") \
- X(MkBG, "BFBFBFFF", qtrue, "RGBA color of the mark background") \
- X(MkShadow, "FFFFFF00", qtrue, "RGBA color of the mark text shadows") \
- X(Text, "E2E2E2", qfalse, "RGB color of text") \
- X(MkText, "000000", qfalse, "RGB color of mark text") \
- X(CVar, "4778B2", qfalse, "RGB color of variable names") \
- X(Cmd, "4FA7BD", qfalse, "RGB color of command names") \
- X(Value, "E5BC39", qfalse, "RGB color of variable values") \
- X(Help, "ABC1C6", qfalse, "RGB color of help text") \
- X(Search, "FFFF00", qfalse, "RGB color of search result marker") \
- X(HL, "303033FF", qtrue, help_con_colHL)
+ X(BG, "101013F6", qtrue, "RGBA color of the background", "Console background") \
+ X(Border, "4778B2FF", qtrue, "RGBA color of the border", "Console border") \
+ X(Arrow, "4778B2FF", qtrue, "RGBA color of backscroll arrows", "Console backscroll arrows") \
+ X(Shadow, "000000FF", qtrue, "RGBA color of text shadows", "Console text shadows") \
+ X(MkBG, "BFBFBFFF", qtrue, "RGBA color of the mark background", "Console mark background") \
+ X(MkShadow, "FFFFFF00", qtrue, "RGBA color of the mark text shadows", "Console mark text shadows") \
+ X(Text, "E2E2E2", qfalse, "RGB color of text", "Console text") \
+ X(MkText, "000000", qfalse, "RGB color of mark text", "Console mark text") \
+ X(CVar, "4778B2", qfalse, "RGB color of variable names", "Console variable names") \
+ X(Cmd, "4FA7BD", qfalse, "RGB color of command names", "Console command names") \
+ X(Value, "E5BC39", qfalse, "RGB color of variable values", "Console variable values") \
+ X(Help, "ABC1C6", qfalse, "RGB color of help text", "Console help text") \
+ X(Search, "FFFF00", qfalse, "RGB color of search result marker", "Console search result marker") \
+ X(HL, "303033FF", qtrue, help_con_colHL, "Console completion highlights")
-#define COLOR_LIST_ITEM( Name, Default, HasAlpha, Help ) \
+#define COLOR_LIST_ITEM( Name, Default, HasAlpha, Help, Title ) \
static cvar_t* con_col##Name; \
static vec4_t col##Name;
COLOR_LIST( COLOR_LIST_ITEM )
@@ -146,13 +146,8 @@ static qbool IsValidHexColor( const char* s, qbool hasAlpha )
return *s == '\0';
}
-static void GetFloatColor( float* c, cvar_t* cvar, qbool hasAlpha )
+static void GetFloatColor( float* c, const cvar_t* cvar, qbool hasAlpha )
{
- c[0] = 1.0f;
- c[1] = 1.0f;
- c[2] = 1.0f;
- c[3] = 1.0f;
-
const char* s = cvar->string;
if ( !IsValidHexColor(s, hasAlpha) ) {
s = cvar->resetString;
@@ -160,22 +155,7 @@ static void GetFloatColor( float* c, cvar_t* cvar, qbool hasAlpha )
return;
}
- unsigned int uc[4];
- if ( hasAlpha ) {
- if ( sscanf(s, "%02X%02X%02X%02X", &uc[0], &uc[1], &uc[2], &uc[3]) != 4 )
- return;
- c[0] = uc[0] / 255.0f;
- c[1] = uc[1] / 255.0f;
- c[2] = uc[2] / 255.0f;
- c[3] = uc[3] / 255.0f;
- } else {
- if ( sscanf(s, "%02X%02X%02X", &uc[0], &uc[1], &uc[2]) != 3 )
- return;
- c[0] = uc[0] / 255.0f;
- c[1] = uc[1] / 255.0f;
- c[2] = uc[2] / 255.0f;
- c[3] = 1.0f;
- }
+ Com_ParseHexColor( c, s, hasAlpha );
}
const float* ConsoleColorFromChar( char ccode )
@@ -416,18 +396,49 @@ static void Con_ResizeFont()
static const cvarTableItem_t con_cvars[] =
{
-#define COLOR_LIST_ITEM( Name, Default, HasAlpha, Help ) { &con_col##Name, "con_col" #Name, Default, CVAR_ARCHIVE, CVART_STRING, NULL, NULL, Help },
+#define COLOR_LIST_ITEM( Name, Default, HasAlpha, Help, Title ) \
+ { \
+ &con_col##Name, "con_col" #Name, Default, CVAR_ARCHIVE, HasAlpha ? CVART_COLOR_RGBA : CVART_COLOR_RGB, NULL, NULL, Help, \
+ Title, CVARCAT_CONSOLE, "", "" \
+ },
COLOR_LIST( COLOR_LIST_ITEM )
#undef COLOR_LIST_ITEM
// con_scale:
// bugs in the renderer's overflow handling will cause crashes
// if the console has too many polys/verts because of too small a font
- { &con_noprint, "con_noprint", "0", 0, CVART_BOOL, NULL, NULL, "disables console printing and history writing" },
- { &con_notifytime, "con_notifytime", "-1", CVAR_ARCHIVE, CVART_FLOAT, "-1", "30", help_con_notifytime },
- { &con_scale, "con_scale", "1.2", CVAR_ARCHIVE, CVART_FLOAT, "0.25", "10", "console text scaling factor" },
- { &con_scaleMode, "con_scaleMode", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", help_con_scaleMode },
- { &con_speed, "con_speed", "1000", CVAR_ARCHIVE, CVART_FLOAT, "0.1", "1000", "console opening/closing speed" },
- { &con_drawHelp, "con_drawHelp", "1", CVAR_ARCHIVE, CVART_BITMASK, "0", XSTRING(DRAWHELP_MAX), help_con_drawHelp }
+ {
+ &con_noprint, "con_noprint", "0", 0, CVART_BOOL, NULL, NULL, "disables console printing and history writing",
+ "No console print", CVARCAT_CONSOLE, "Disables console printing and history writing", ""
+ },
+ {
+ &con_notifytime, "con_notifytime", "-1", CVAR_ARCHIVE, CVART_FLOAT, "-1", "30", help_con_notifytime,
+ "Console notify time", CVARCAT_CONSOLE,
+ "Seconds messages stay visible in the notify area\n"
+ "Set to -1 for CPMA to draw the 'Console' SuperHUD element", ""
+ },
+ {
+ &con_scale, "con_scale", "1.2", CVAR_ARCHIVE, CVART_FLOAT, "0.25", "10", "console text scaling factor",
+ "Console text scale", CVARCAT_CONSOLE, "", ""
+ },
+ {
+ &con_scaleMode, "con_scaleMode", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", help_con_scaleMode,
+ "Console text scale mode", CVARCAT_CONSOLE, "", "",
+ CVAR_GUI_VALUE("0", "Doesn't scale with res", "")
+ CVAR_GUI_VALUE("1", "Scales with res", "")
+ CVAR_GUI_VALUE("2", "Fixed 8x12 size", "")
+ },
+ {
+ &con_speed, "con_speed", "1000", CVAR_ARCHIVE, CVART_FLOAT, "0.1", "1000", "console opening/closing speed",
+ "Console open speed", CVARCAT_CONSOLE, "", ""
+ },
+ {
+ &con_drawHelp, "con_drawHelp", "1", CVAR_ARCHIVE, CVART_BITMASK, "0", XSTRING(DRAWHELP_MAX), "draws help text below the console",
+ "Console help panel", CVARCAT_CONSOLE, "Draws a panel below the console", "",
+ CVAR_GUI_VALUE("0", "Enable panel", "Enables the help panel below the console")
+ CVAR_GUI_VALUE("1", "Force draw", "Draws the help panel even if the CVar/cmd has no help text")
+ CVAR_GUI_VALUE("2", "Draw modules", "Draws the list of modules")
+ CVAR_GUI_VALUE("3", "Draw attributes", "Draws the list of attributes (CVars only)")
+ }
};
@@ -943,7 +954,7 @@ void Con_RunConsole()
con.displayFrac = con.finalFrac;
}
-#define COLOR_LIST_ITEM( Name, Default, HasAlpha, Help ) GetFloatColor( col##Name, con_col##Name, HasAlpha );
+#define COLOR_LIST_ITEM( Name, Default, HasAlpha, Help, Title ) GetFloatColor( col##Name, con_col##Name, HasAlpha );
COLOR_LIST( COLOR_LIST_ITEM )
#undef COLOR_LIST_ITEM
}
diff --git a/code/client/cl_imgui.cpp b/code/client/cl_imgui.cpp
index b2a8409..6fb6185 100644
--- a/code/client/cl_imgui.cpp
+++ b/code/client/cl_imgui.cpp
@@ -24,6 +24,7 @@ along with Challenge Quake 3. If not, see .
#include "client.h"
#include "cl_imgui.h"
#include "../imgui/ProggyClean.h"
+#include "../imgui/Sweet16Mono.h"
static int keyMap[256];
@@ -311,10 +312,12 @@ void CL_IMGUI_Init()
io.SetClipboardTextFn = &SetClipboardText;
//io.MouseDrawCursor = true; // just use the operating system's
- ImFontConfig fontConfig;
+ ImFontConfig fontConfig = {};
fontConfig.FontDataOwnedByAtlas = false;
- io.Fonts->AddFontFromMemoryCompressedTTF(
+ Q_strncpyz(fontConfig.Name, "Proggy Clean (13px)", sizeof(fontConfig.Name));
+ io.FontDefault = io.Fonts->AddFontFromMemoryCompressedTTF(
ProggyClean_compressed_data, ProggyClean_compressed_size, 13.0f, &fontConfig);
+ AddSweet16MonoFont();
ImGUI_ApplyTheme();
@@ -388,6 +391,7 @@ void CL_IMGUI_Frame()
int x, y;
Sys_GetCursorPosition(&x, &y);
+ re.ComputeCursorPosition(&x, &y);
ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = (float)((double)elapsedUS / 1000000.0);
@@ -406,9 +410,10 @@ qbool CL_IMGUI_KeyEvent(int key, qbool down, const char* cmd)
{
if(cmd != NULL)
{
- if(!Q_stricmp(cmd, "togglegui") || !Q_stricmp(cmd, "toggleguiinput"))
+ const char* const prefix = "keycatchgui";
+ if(Q_stristr(cmd, prefix) == cmd)
{
- Cbuf_AddText(cmd);
+ Cbuf_AddText(cmd + strlen(prefix));
Cbuf_AddText("\n");
return qtrue;
}
@@ -419,9 +424,9 @@ qbool CL_IMGUI_KeyEvent(int key, qbool down, const char* cmd)
{
if(down && (key == '`' || key == '~'))
{
- Cvar_Set("r_debugUI", "0");
+ // continue displaying the GUI but route input to the console
Cvar_Set("r_debugInput", "0");
- return qtrue;
+ return qfalse;
}
unsigned int imguiKey;
diff --git a/code/client/cl_input.cpp b/code/client/cl_input.cpp
index 5f9d5cd..2a9b5c1 100644
--- a/code/client/cl_input.cpp
+++ b/code/client/cl_input.cpp
@@ -843,16 +843,42 @@ static void IN_Restart_f()
static const cvarTableItem_t cl_cvars[] =
{
- { &m_speed, "m_speed", "2", CVAR_ARCHIVE, CVART_FLOAT, "0", "100", "mouse sensitivity" },
- { &m_accel, "m_accel", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, "mouse acceleration" },
- { &m_accelStyle, "m_accelStyle", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "1", help_m_accelStyle },
- { &m_accelOffset, "m_accelOffset", "5", CVAR_ARCHIVE, CVART_FLOAT, "0.001", "5000", help_m_accelOffset },
- { &m_limit, "m_limit", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, help_m_limit },
- { &m_pitch, "m_pitch", "0.022", CVAR_ARCHIVE, CVART_FLOAT, "-100", "100", "post-accel vertical mouse sens." },
- { &m_yaw, "m_yaw", "0.022", CVAR_ARCHIVE, CVART_FLOAT, "-100", "100", "post-accel horizontal mouse sens." },
+ {
+ &m_speed, "m_speed", "2", CVAR_ARCHIVE, CVART_FLOAT, "0", "100", "mouse sensitivity",
+ "Mouse sensitivity", CVARCAT_INPUT, "", ""
+ },
+ {
+ &m_accel, "m_accel", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "100", "mouse acceleration",
+ "Mouse acceleration", CVARCAT_INPUT, "", ""
+ },
+ {
+ &m_accelStyle, "m_accelStyle", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "1", help_m_accelStyle,
+ "Mouse accel style", CVARCAT_INPUT, "", "",
+ CVAR_GUI_VALUE("0", "Quake 3", "")
+ CVAR_GUI_VALUE("1", "New", "")
+ },
+ {
+ &m_accelOffset, "m_accelOffset", "5", CVAR_ARCHIVE, CVART_FLOAT, "0.001", "5000", help_m_accelOffset,
+ "Mouse accel offset", CVARCAT_INPUT, "Offset for the power function", "For the new accel style only"
+ },
+ {
+ &m_limit, "m_limit", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "100", help_m_limit,
+ "Mouse speed cap", CVARCAT_INPUT, "0 means no cap", "For the Quake 3 accel style only"
+ },
+ {
+ &m_pitch, "m_pitch", "0.022", CVAR_ARCHIVE, CVART_FLOAT, "-100", "100", "post-accel vertical mouse sens.",
+ "Vertical mouse sens", CVARCAT_INPUT, "Post-acceleration sensitivity", ""
+ },
+ {
+ &m_yaw, "m_yaw", "0.022", CVAR_ARCHIVE, CVART_FLOAT, "-100", "100", "post-accel horizontal mouse sens.",
+ "Horizontal mouse sens", CVARCAT_INPUT, "Post-acceleration sensitivity", ""
+ },
{ &m_forward, "m_forward", "0.25", CVAR_ARCHIVE, CVART_FLOAT, "-32767", "32767", help_m_forward },
{ &m_side, "m_side", "0.25", CVAR_ARCHIVE, CVART_FLOAT, "-32767", "32767", help_m_side },
- { &m_filter, "m_filter", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "mouse smoothing" },
+ {
+ &m_filter, "m_filter", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "mouse smoothing",
+ "Mouse smoothing", CVARCAT_INPUT, "", ""
+ },
{ &cl_pitchspeed, "cl_pitchspeed", "140", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, help_cl_pitchspeed },
{ &cl_yawspeed, "cl_yawspeed", "140", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, help_cl_yawspeed },
{ &cl_anglespeedkey, "cl_anglespeedkey", "1.5", 0, CVART_FLOAT },
diff --git a/code/client/cl_main.cpp b/code/client/cl_main.cpp
index a5e68c2..be0b453 100644
--- a/code/client/cl_main.cpp
+++ b/code/client/cl_main.cpp
@@ -51,8 +51,6 @@ cvar_t *cl_escapeAbortsDemo;
cvar_t *net_proxy;
-cvar_t *r_khr_debug;
-
clientActive_t cl;
clientConnection_t clc;
clientStatic_t cls;
@@ -2142,24 +2140,60 @@ static const cvarTableItem_t cl_cvars[] =
{ &cl_showTimeDelta, "cl_showTimeDelta", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "prints delta adjustment values and events" },
{ &rconPassword, "rconPassword", "", CVAR_TEMP, CVART_STRING, NULL, NULL, help_rconPassword },
{ &cl_timedemo, "timedemo", "0", 0, CVART_BOOL, NULL, NULL, "demo benchmarking mode" },
- { &cl_aviFrameRate, "cl_aviFrameRate", "50", CVAR_ARCHIVE, CVART_INTEGER, "24", "250", help_cl_aviFrameRate },
- { &cl_aviMotionJpeg, "cl_aviMotionJpeg", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_cl_aviMotionJpeg },
+ {
+ &cl_aviFrameRate, "cl_aviFrameRate", "50", CVAR_ARCHIVE, CVART_INTEGER, "24", "250", help_cl_aviFrameRate,
+ "AVI video framerate", CVARCAT_DEMO, "", ""
+ },
+ {
+ &cl_aviMotionJpeg, "cl_aviMotionJpeg", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_cl_aviMotionJpeg,
+ "AVI motion JPEG", CVARCAT_DEMO, "", ""
+ },
{ &rconAddress, "rconAddress", "", 0, CVART_STRING, NULL, NULL, help_rconAddress },
- { &cl_maxpackets, "cl_maxpackets", "125", CVAR_ARCHIVE, CVART_INTEGER, "15", "125", "max. packet upload rate" },
- { &cl_packetdup, "cl_packetdup", "1", CVAR_ARCHIVE, CVART_INTEGER, "0", "5", "number of extra transmissions per packet" },
- { &cl_allowDownload, "cl_allowDownload", "1", CVAR_ARCHIVE, CVART_INTEGER, "-1", "1", help_cl_allowDownload },
+ {
+ &cl_maxpackets, "cl_maxpackets", "125", CVAR_ARCHIVE, CVART_INTEGER, "15", "125", "max. packet upload rate",
+ "Max. packets", CVARCAT_NETWORK, "", ""
+ },
+ {
+ &cl_packetdup, "cl_packetdup", "1", CVAR_ARCHIVE, CVART_INTEGER, "0", "5", "number of extra transmissions per packet",
+ "Packet duplication", CVARCAT_NETWORK, "Sets the number of extra copies per packet", "Use if you experience packet loss"
+ },
+ {
+ &cl_allowDownload, "cl_allowDownload", "1", CVAR_ARCHIVE, CVART_INTEGER, "-1", "1", help_cl_allowDownload,
+ "PK3 download mode", CVARCAT_NETWORK, "", "",
+ CVAR_GUI_VALUE("-1", "Quake 3", "Can always find PK3 files\nServer must allow it\nVery slow")
+ CVAR_GUI_VALUE("0", "Disabled", "")
+ CVAR_GUI_VALUE("1", "CNQ3", "Map server may not have the file\nIndependent of server\nFast")
+ },
{ &cl_inGameVideo, "r_inGameVideo", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables roq video playback" },
{ &cl_serverStatusResendTime, "cl_serverStatusResendTime", "750", 0, CVART_INTEGER, "500", "1000", "milli-seconds to wait before resending getstatus" },
{ NULL, "cl_maxPing", "999", CVAR_ARCHIVE, CVART_INTEGER, "80", "999", "max. ping for the server browser" },
- { NULL, "name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE, CVART_STRING, NULL, NULL, "your name" },
- { NULL, "rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE, CVART_INTEGER, "4000", "99999", "network transfer rate" },
+ {
+ NULL, "name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE, CVART_STRING, NULL, NULL, "your name",
+ "Player name", CVARCAT_GENERAL, "", ""
+ },
+ {
+ NULL, "rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE, CVART_INTEGER, "4000", "99999", "network transfer rate",
+ "Transfer rate", CVARCAT_NETWORK, "You'll generally want 25K to 30K", ""
+ },
{ NULL, "snaps", "30", CVAR_USERINFO | CVAR_ARCHIVE, CVART_INTEGER }, // documented by the mod
{ NULL, "password", "", CVAR_USERINFO, CVART_STRING, NULL, NULL, "used by /" S_COLOR_CMD "connect" },
- { &cl_matchAlerts, "cl_matchAlerts", "7", CVAR_ARCHIVE, CVART_BITMASK, "0", XSTRING(MAF_MAX), help_cl_matchAlerts },
+ {
+ &cl_matchAlerts, "cl_matchAlerts", "7", CVAR_ARCHIVE, CVART_BITMASK, "0", XSTRING(MAF_MAX), help_cl_matchAlerts,
+ "Match alerts", CVARCAT_GENERAL, "Lets you know when a match is starting", "",
+ CVAR_GUI_VALUE("0", "When unfocused", "Otherwise only when minimized")
+ CVAR_GUI_VALUE("1", "Flash the task bar", "")
+ CVAR_GUI_VALUE("2", "Beep once", "")
+ CVAR_GUI_VALUE("3", "Unmute", "")
+ },
{ &net_proxy, "net_proxy", "", CVAR_TEMP, CVART_STRING, NULL, NULL, help_net_proxy },
- { &r_khr_debug, "r_khr_debug", "2", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", help_r_khr_debug },
- { &cl_demoPlayer, "cl_demoPlayer", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_cl_demoPlayer },
- { &cl_escapeAbortsDemo, "cl_escapeAbortsDemo", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "pressing escape aborts demo playback" },
+ {
+ &cl_demoPlayer, "cl_demoPlayer", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_cl_demoPlayer,
+ "New demo player", CVARCAT_DEMO, "Enables the new demo player with rewind support", ""
+ },
+ {
+ &cl_escapeAbortsDemo, "cl_escapeAbortsDemo", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "pressing escape aborts demo playback",
+ "Escape aborts demo", CVARCAT_DEMO, "Pressing escape aborts demo playback", ""
+ },
};
@@ -2193,6 +2227,663 @@ static const cmdTableItem_t cl_cmds[] =
};
+struct cvarTableItemCPMA_t {
+ const char* name;
+ cvarType_t type;
+ const char* guiName;
+ int categories;
+ const char* guiDesc;
+ const char* guiHelp;
+ const char* guiValues;
+};
+
+
+static const cvarTableItemCPMA_t cpma_cvars[] =
+{
+ {
+ "cg_damageDraw", CVART_BOOL,
+ "Screen blood", CVARCAT_GRAPHICS, "Draws blood when taking damage", ""
+ },
+ {
+ "cg_deadBodyDarken", CVART_BOOL,
+ "Grey corpses", CVARCAT_GRAPHICS, "Renders dead players in dark grey", ""
+ },
+ {
+ "cg_redTeamColors", CVART_COLOR_CHBLS,
+ "Red player colors", CVARCAT_GRAPHICS, "Red team player colors", ""
+ },
+ {
+ "cg_blueTeamColors", CVART_COLOR_CHBLS,
+ "Blue player colors", CVARCAT_GRAPHICS, "Blue team player colors", ""
+ },
+ {
+ "cg_forceTeamColors", CVART_BITMASK,
+ "Force team player colors", CVARCAT_GRAPHICS, "", "",
+ CVAR_GUI_VALUE("0", "Own team in first-person", "")
+ CVAR_GUI_VALUE("1", "Enemy team in first-person", "")
+ CVAR_GUI_VALUE("2", "Free-float camera", "")
+ CVAR_GUI_VALUE("3", "Only for CTF/NTF/CTFS", "")
+ },
+ {
+ "cg_teamModel", CVART_STRING,
+ "Team model", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_forceTeamModel", CVART_BOOL,
+ "Force team model", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_enemyColors", CVART_COLOR_CHBLS,
+ "Enemy player colors", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_enemyModel", CVART_STRING,
+ "Enemy model", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_fallKick", CVART_BOOL,
+ "Fall kick", CVARCAT_GAMEPLAY, "Makes the camera bounce after a fall", ""
+ },
+ {
+ "cg_forceColors", CVART_BOOL,
+ "Force colors on teammates", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_gunOffset", CVART_STRING,
+ "View weapon position", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_itemFX", CVART_BITMASK,
+ "Item effects", CVARCAT_GRAPHICS, "", "",
+ CVAR_GUI_VALUE("0", "Bob up and down", "")
+ CVAR_GUI_VALUE("1", "Rotate", "Asymmetric items will always rotate")
+ CVAR_GUI_VALUE("2", "Scale up on respawn", "")
+ },
+ {
+ "cg_lagHax", CVART_INTEGER,
+ "Adaptive prediction", CVARCAT_NETWORK, "Also does a bit of lag compensation", "",
+ CVAR_GUI_VALUE("0", "Disabled", "")
+ CVAR_GUI_VALUE("-1", "As much as allowed", "")
+ },
+ {
+ "cg_lightningImpact", CVART_INTEGER,
+ "LG impact style", CVARCAT_GRAPHICS, "", "",
+ CVAR_GUI_VALUE("0", "Nothing", "")
+ CVAR_GUI_VALUE("1", "Impact", "")
+ CVAR_GUI_VALUE("2", "Impact and sparks", "")
+ },
+ {
+ "cg_muzzleFlash", CVART_BOOL,
+ "Muzzle flash", CVARCAT_GRAPHICS, "Draws a muzzle flash when firing the view weapon", ""
+ },
+ {
+ "cg_noAmmoChange", CVART_INTEGER,
+ "No-ammo switch", CVARCAT_GAMEPLAY, "Allows from/to out-of-ammo weapon changes", "",
+ CVAR_GUI_VALUE("0", "Switch, disallow 0 ammo", "Switches to the next weapon. Can't select a weapon with no ammo")
+ CVAR_GUI_VALUE("1", "Switch, allow 0 ammo", "Switches to the next weapon. Can select a weapon with no ammo")
+ CVAR_GUI_VALUE("2", "No switch, allow 0 ammo", "Keeps the current weapon. Can select a weapon with no ammo")
+ },
+ {
+ "cg_noHitBeep", CVART_BOOL,
+ "Hit beeps", CVARCAT_SOUND | CVARCAT_GAMEPLAY, "", "",
+ CVAR_GUI_VALUE("1", "Silence", "")
+ CVAR_GUI_VALUE("0", "Hit beeps", "")
+ },
+ {
+ "cg_nudge", CVART_INTEGER,
+ "Time nudge", CVARCAT_NETWORK, "", ""
+ },
+ {
+ "cg_optimiseBW", CVART_BITMASK,
+ "Bandwidth optimizations", CVARCAT_NETWORK, "", "",
+ CVAR_GUI_VALUE("0", "Server-to-client", "Usually forced by servers")
+ CVAR_GUI_VALUE("1", "Client-to-server", "Only use if your upload rate is dial-up level")
+ },
+ {
+ "cg_railCoreWidth", CVART_INTEGER,
+ "Railgun core width", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_railRingStep", CVART_INTEGER,
+ "Railgun ring step", CVARCAT_GRAPHICS, "Distance between the rail rings", ""
+ },
+ {
+ "cg_railRingWidth", CVART_INTEGER,
+ "Railgun ring width", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_railStyle", CVART_BITMASK,
+ "Railgun trail style", CVARCAT_GRAPHICS, "Visual elements of a railgun trail", "",
+ CVAR_GUI_VALUE("0", "Core", "")
+ CVAR_GUI_VALUE("1", "Spiral", "")
+ CVAR_GUI_VALUE("2", "Rings", "")
+ },
+ {
+ "cg_smoke_SG", CVART_BOOL,
+ "Shotgun smoke", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_smokeRadius_RL", CVART_FLOAT,
+ "Rocket launcher smoke radius", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_smokeRadius_GL", CVART_FLOAT,
+ "Grenade launcher smoke radius", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_xerpClients", CVART_INTEGER,
+ "Extrapolate clients", CVARCAT_NETWORK, "", "",
+ CVAR_GUI_VALUE("-1", "Hacked extrapolation", "Intended for high ping")
+ CVAR_GUI_VALUE("0", "No extrapolation", "Fine for low ping")
+ CVAR_GUI_VALUE("1", "Original Q3 behavior", "Just like the original cg_smoothClients code")
+ },
+ {
+ "cg_trueLightning", CVART_FLOAT,
+ "Lightning gun beam prediction", CVARCAT_GRAPHICS | CVARCAT_NETWORK | CVARCAT_GAMEPLAY, "",
+ "LG beam prediction control\n" \
+ " -1 = Pure client-side (no sway, no beam drawn)\n"
+ " 0 = Pure server-side (sways the most)\n"
+ " 1 = Pure client-side (no sway)\n"
+ "Fractional values: mix between server and client rendering\n"
+ "Negative values: the beam isn't drawn\n"
+ "Negative fractional values still affect impact mark placement."
+ },
+ {
+ "cg_viewAdjustments", CVART_BOOL,
+ "Enable view bobbing", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_fragSound", CVART_STRING,
+ "Kill sound", CVARCAT_SOUND, "", "",
+ CVAR_GUI_VALUE("0", "No sound", "")
+ CVAR_GUI_VALUE("1", "Tonal impact: D", "")
+ CVAR_GUI_VALUE("2", "Tonal impact: E", "")
+ CVAR_GUI_VALUE("3", "Tonal impact: F#", "")
+ CVAR_GUI_VALUE("4", "Tonal impact: G", "")
+ CVAR_GUI_VALUE("5", "Cork pop", "")
+ CVAR_GUI_VALUE("6", "Cash register", "")
+ CVAR_GUI_VALUE("7", "Hook impact", "")
+ },
+ {
+ "cg_newModels", CVART_BOOL,
+ "Better 3D models", CVARCAT_GRAPHICS, "Uses better meshes for items", ""
+ },
+ {
+ "cg_animateChatBalloon", CVART_BOOL,
+ "Animated chat sprite", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_demoMapOverrides", CVART_BOOL,
+ "Override demo maps", CVARCAT_GRAPHICS, "Replaces maps for demo playback",
+ "The override list is loaded from 'cfg-maps/demomaps.txt'.\n"
+ "Each line has the format 'DemoName DisplayName'.\n"
+ "Example: 'cpm3a cpm3b_b1' will display cpm3b_b1 instead of cpm3a."
+ },
+ {
+ "ch_crosshairAlpha", CVART_FLOAT,
+ "Crosshair opacity", CVARCAT_HUD, "", ""
+ },
+ {
+ "ch_crosshairColor", CVART_COLOR_CPMA,
+ "Crosshair color", CVARCAT_HUD, "", ""
+ },
+ {
+ "ch_crosshairPulse", CVART_INTEGER,
+ "Crosshair pulses", CVARCAT_HUD, "Crosshair pulses on events", "",
+ CVAR_GUI_VALUE("0", "Never", "")
+ CVAR_GUI_VALUE("1", "Item pick-ups", "")
+ CVAR_GUI_VALUE("2", "Enemy damage", "")
+ CVAR_GUI_VALUE("3", "Enemy frags", "")
+ },
+ {
+ "ch_crosshairText", CVART_STRING,
+ "Crosshair text", CVARCAT_HUD, "Crosshair uses this text instead of an icon", ""
+ },
+ {
+ "ch_crosshairHitColor", CVART_COLOR_CPMA,
+ "Crosshair hit color", CVARCAT_HUD, "", ""
+ },
+ {
+ "ch_crosshairFragColor", CVART_COLOR_CPMA,
+ "Crosshair kill color", CVARCAT_HUD, "", ""
+ },
+ {
+ "ch_drawWarmup", CVART_BOOL,
+ "Warm-up info", CVARCAT_HUD, "Displays gameplay settings during warm-up", ""
+ },
+ {
+ "ch_file", CVART_STRING,
+ "HUD config file", CVARCAT_HUD, "", ""
+ },
+ {
+ "ch_playerNames", CVART_BOOL,
+ "Draw player names", CVARCAT_DEMO, "Draws names above heads during demo playback", ""
+ },
+ {
+ "ch_recordMessage", CVART_BOOL,
+ "Draw demo recording", CVARCAT_HUD, "Draws a message when recording demos", ""
+ },
+ {
+ "ch_selfOnTeamOverlay", CVART_BOOL,
+ "Team overlay self row", CVARCAT_HUD, "Draw a row for yourself in the team overlays", ""
+ },
+ {
+ "ch_shortNames", CVART_BOOL,
+ "Team overlay nicknames", CVARCAT_HUD, "Team overlays uses nicknames (max. 5 characters) instead of names", ""
+ },
+ {
+ "ch_locations", CVART_BOOL,
+ "Team overlay locations", CVARCAT_HUD, "Draws locations in the team overlays", ""
+ },
+ {
+ "ch_shortScoreboard", CVART_BOOL,
+ "Short scoreboard", CVARCAT_HUD, "Disables stats display in 1v1 scoreboard", ""
+ },
+ {
+ "ch_3waveFont", CVART_BOOL,
+ "Threewave font", CVARCAT_HUD, "Uses the Threewave font in the scoreboard", ""
+ },
+ {
+ "ch_wstatsTime", CVART_INTEGER,
+ "Weapon stats time", CVARCAT_HUD, "Max. +wstats display duration in intermission", ""
+ },
+ {
+ "ch_gauntlet", CVART_BOOL,
+ "Gauntlet in weapon list", CVARCAT_HUD, "Draws the gauntlet in the WeaponList SuperHUD element", ""
+ },
+ {
+ "ch_drawKeys", CVART_BITMASK,
+ "Draw movement keys", CVARCAT_HUD, "Enables the KeyDown_* and KeyUp_* SuperHUD elements", "",
+ CVAR_GUI_VALUE("0", "When playing", "")
+ CVAR_GUI_VALUE("1", "When spectating", "")
+ CVAR_GUI_VALUE("2", "During demo playback", "Won't work with pre-1.50 demos")
+ },
+ {
+ "ch_hiddenElements", CVART_STRING,
+ "Hidden SuperHUD elements", CVARCAT_HUD, "List of hidden SuperHUD elements", "Use /hud_hide and /hud_show to manipulate this list"
+ },
+ {
+ "ch_timersList", CVART_STRING,
+ "Item timers draw list", CVARCAT_HUD, "Space-separated list of item types to draw", "Use /itemtimerlist to see the type list"
+ },
+ {
+ "ch_timersOrderOR", CVART_INTEGER,
+ "Own/red item timers order", CVARCAT_HUD, "", "",
+ CVAR_GUI_VALUE("0", "Flag -> Mid", "")
+ CVAR_GUI_VALUE("1", "Mid -> Flag", "")
+ CVAR_GUI_VALUE("2", "Custom list", "")
+ CVAR_GUI_VALUE("3", "Custom list, inverted", "")
+ },
+ {
+ "ch_timersOrderEB", CVART_INTEGER,
+ "Enemy/blue item timers order", CVARCAT_HUD, "", "",
+ CVAR_GUI_VALUE("0", "Flag -> Mid", "")
+ CVAR_GUI_VALUE("1", "Mid -> Flag", "")
+ CVAR_GUI_VALUE("2", "Custom list", "")
+ CVAR_GUI_VALUE("3", "Custom list, inverted", "")
+ },
+ {
+ "ch_timersOrderTeams", CVART_INTEGER,
+ "Item timers team order", CVARCAT_HUD, "", "",
+ CVAR_GUI_VALUE("0", "Own -> Enemy", "")
+ CVAR_GUI_VALUE("1", "Enemy -> Own", "")
+ CVAR_GUI_VALUE("2", "Red -> Blue", "")
+ CVAR_GUI_VALUE("3", "Blue -> Red", "")
+ },
+ {
+ "ch_timersSync", CVART_BOOL,
+ "Synchronize item timers", CVARCAT_HUD, "Synchronizes all timer updates in the HUD", ""
+ },
+ {
+ "cg_demoSkipPauses", CVART_BOOL,
+ "Skip server pauses", CVARCAT_DEMO, "Skips timeouts and referee pauses",
+ "When not paused, it will skip past server pauses\n"
+ "Only available with CNQ3's new demo player"
+ },
+ {
+ "mvw_DM", CVART_STRING,
+ "Multi-view 1v1 window", CVARCAT_HUD, "PiP window coordinates for the opponent in 1v1", ""
+ },
+ {
+ "mvw_TDM1", CVART_STRING,
+ "Multi-view TDM window #1", CVARCAT_HUD, "PiP window coordinates for teammate #1", ""
+ },
+ {
+ "mvw_TDM2", CVART_STRING,
+ "Multi-view TDM window #2", CVARCAT_HUD, "PiP window coordinates for teammate #2", ""
+ },
+ {
+ "mvw_TDM3", CVART_STRING,
+ "Multi-view TDM window #3", CVARCAT_HUD, "PiP window coordinates for teammate #3", ""
+ },
+ {
+ "mvw_TDM4", CVART_STRING,
+ "Multi-view TDM window #4", CVARCAT_HUD, "PiP window coordinates for teammate #4", ""
+ },
+ {
+ "s_ambient", CVART_BOOL,
+ "Ambient sounds", CVARCAT_SOUND, "Enables the maps' ambient sounds", ""
+ },
+ {
+ "cg_drawBrightSpawns", CVART_BOOL,
+ "Bright spawn points", CVARCAT_GRAPHICS, "Draws spawn points more visibly during warm-up", ""
+ },
+ {
+ "cg_drawBrightWeapons", CVART_BITMASK,
+ "Fullbright weapons", CVARCAT_GRAPHICS, "Enables fullbright weapons", "",
+ CVAR_GUI_VALUE("0", "First-person, your own gun", "")
+ CVAR_GUI_VALUE("1", "First-person, carried by teammates", "")
+ CVAR_GUI_VALUE("2", "First-person, carried by enemies", "")
+ CVAR_GUI_VALUE("3", "Weapons lying on the map", "")
+ CVAR_GUI_VALUE("4", "Freecam, carried by players", "")
+ },
+ {
+ "s_announcer", CVART_STRING,
+ "Announcer", CVARCAT_SOUND, "Announcer sound pack", "",
+ CVAR_GUI_VALUE("feedback", "Q3's male announcer", "")
+ CVAR_GUI_VALUE("hellchick", "CPMA's female announcer", "")
+ },
+ {
+ "ch_consoleLines", CVART_INTEGER,
+ "Max console lines", CVARCAT_HUD, "Maximum number of lines in the 'Console' SuperHUD element", ""
+ },
+ {
+ "ch_eventLines", CVART_INTEGER,
+ "Max event lines", CVARCAT_HUD, "Maximum number of lines in the 'GameEvents' SuperHUD element", ""
+ },
+ {
+ "ch_eventForceColors", CVART_BOOL,
+ "Force event colors", CVARCAT_HUD, "Enables custom team colors in the 'GameEvents' SuperHUD element", ""
+ },
+ {
+ "ch_eventOwnColor", CVART_COLOR_CPMA,
+ "Own team event color", CVARCAT_HUD, "", ""
+ },
+ {
+ "ch_eventEnemyColor", CVART_COLOR_CPMA,
+ "Enemy team event color", CVARCAT_HUD, "", ""
+ },
+ {
+ "ch_chatLines", CVART_INTEGER,
+ "Max chat lines", CVARCAT_HUD, "Maximum number of lines in the 'Chat' SuperHUD element", ""
+ },
+ {
+ "ch_animateScroll", CVART_BOOL,
+ "Scrolling animations", CVARCAT_HUD, "For console, chat, game events and rewards", ""
+ },
+ {
+ "ch_animateRewardIcons", CVART_INTEGER,
+ "Animate reward icons", CVARCAT_HUD, "", "",
+ CVAR_GUI_VALUE("0", "No animation", "")
+ CVAR_GUI_VALUE("1", "Play animation once", "")
+ CVAR_GUI_VALUE("2", "Play looped animation", "")
+ },
+ {
+ "ui_swapMouseButtons", CVART_BOOL,
+ "Swap mouse buttons", CVARCAT_GUI, "Swaps the left and right mouse buttons", ""
+ },
+ {
+ "ui_sensitivity", CVART_FLOAT,
+ "UI mouse sensitivity", CVARCAT_GUI, "Mouse sensitivity in the UI", ""
+ },
+ {
+ "cg_mvSensitivity", CVART_FLOAT,
+ "Coach view mouse sensitivity", CVARCAT_GUI, "Mouse sensitivity in the live coach view UI", ""
+ },
+ {
+ "cg_ammoWarning", CVART_BOOL,
+ "Ammo warning", CVARCAT_SOUND, "Plays a click sound when out of ammo", ""
+ },
+ {
+ "cg_autoswitch", CVART_BOOL,
+ "Weapon auto-switch", CVARCAT_GAMEPLAY, "Auto-switches to the weapon you just picked up", ""
+ },
+ {
+ "com_blood", CVART_INTEGER,
+ "Draw blood", CVARCAT_GRAPHICS, "Draws blood when players are hit", "",
+ CVAR_GUI_VALUE("0", "Disabled", "")
+ CVAR_GUI_VALUE("1", "Old style", "Large, long, slow updates")
+ CVAR_GUI_VALUE("2", "New style", "Small, short, fast updates")
+ },
+ {
+ "cg_drawGun", CVART_INTEGER,
+ "View weapon", CVARCAT_GRAPHICS, "", "",
+ CVAR_GUI_VALUE("0", "No gun", "")
+ CVAR_GUI_VALUE("1", "Gun visible, sways", "")
+ CVAR_GUI_VALUE("2", "Gun visible, doesn't sway", "")
+ },
+ {
+ "cg_zoomfov", CVART_FLOAT,
+ "Zoom FoV", CVARCAT_GRAPHICS | CVARCAT_GAMEPLAY, "Field of view when zoomed in", ""
+ },
+ {
+ "cg_zoomAnimationTime", CVART_INTEGER,
+ "Zoom animation time", CVARCAT_GRAPHICS | CVARCAT_GAMEPLAY, "Zoom in/out animation duration, in milliseconds", ""
+ },
+ {
+ "cg_zoomSensitivity", CVART_FLOAT,
+ "Zoom mouse sensitivity", CVARCAT_GAMEPLAY, "Relative to the main sensitivity", ""
+ },
+ {
+ "cg_fov", CVART_FLOAT,
+ "FoV", CVARCAT_GRAPHICS | CVARCAT_GAMEPLAY, "Field of view", "Enable depth clamping to raise the limit to 150"
+ },
+ {
+ "cg_viewsize", CVART_INTEGER,
+ "Gameplay window size", CVARCAT_HUD, "Percentage scale of the gameplay window", ""
+ },
+ {
+ "cg_shadows", CVART_BOOL,
+ "Blob player shadows", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "cg_gibs", CVART_BOOL,
+ "Giblets", CVARCAT_GRAPHICS, "Enables giblets and the blood spatter effect", ""
+ },
+ {
+ "cg_draw2D", CVART_BOOL,
+ "Enable HUD", CVARCAT_HUD, "", ""
+ },
+ {
+ "cg_draw3dIcons", CVART_BOOL,
+ "3D icons", CVARCAT_HUD, "Draws 3D heads/flags in the HUD", ""
+ },
+ {
+ "cg_drawCrosshair", CVART_INTEGER,
+ "Crosshair icon", CVARCAT_HUD, "", "",
+ CVAR_GUI_VALUE("0", "No crosshair", "")
+ CVAR_GUI_VALUE("1", "Cross", "")
+ CVAR_GUI_VALUE("2", "Exploded cross", "")
+ CVAR_GUI_VALUE("3", "Disk + dot", "")
+ CVAR_GUI_VALUE("4", "Circle + dot", "")
+ CVAR_GUI_VALUE("5", "Big dot", "")
+ CVAR_GUI_VALUE("6", "Circle + cross", "")
+ CVAR_GUI_VALUE("7", "Big exploded cross", "")
+ CVAR_GUI_VALUE("8", "Big exploded cross + dot", "")
+ CVAR_GUI_VALUE("9", "Side curves + dot", "")
+ CVAR_GUI_VALUE("10", "Circle + dot", "")
+ CVAR_GUI_VALUE("11", "Cross with black outline", "")
+ CVAR_GUI_VALUE("12", "Exploded cross with black outline", "")
+ CVAR_GUI_VALUE("13", "Disk + dot with black outline", "")
+ CVAR_GUI_VALUE("14", "Circle + dot with black outline", "")
+ CVAR_GUI_VALUE("15", "Dot with black outline", "")
+ CVAR_GUI_VALUE("16", "Circle + cross with black outline", "")
+ CVAR_GUI_VALUE("17", "Mirrored L with black outline", "")
+ CVAR_GUI_VALUE("18", "Cross + dot with black outlines", "")
+ CVAR_GUI_VALUE("19", "Side curves + dot with black outline", "")
+ CVAR_GUI_VALUE("20", "Circle + exploded cross + dot", "")
+ },
+ {
+ "cg_drawCrosshairNames", CVART_INTEGER,
+ "Draw crosshair names", CVARCAT_HUD, "Draws the name and status of the player under the crosshair",
+ "SuperHUD elements: 'TargetName' and 'TargetStatus'",
+ CVAR_GUI_VALUE("0", "Disabled", "")
+ CVAR_GUI_VALUE("1", "All players", "")
+ CVAR_GUI_VALUE("2", "Teammates only", "")
+ },
+ {
+ "cg_crosshairSize", CVART_STRING,
+ "Crosshair scale", CVARCAT_HUD, "Examples: '26', '26x32'", ""
+ },
+ {
+ "cg_crosshairHealth", CVART_BOOL,
+ "Crosshair health", CVARCAT_HUD, "Sets crosshair color based on your stack", ""
+ },
+ {
+ "cg_crosshairX", CVART_INTEGER,
+ "Crosshair X offset", CVARCAT_HUD, "X-axis offset from screen center", ""
+ },
+ {
+ "cg_crosshairY", CVART_INTEGER,
+ "Crosshair Y offset", CVARCAT_HUD, "Y-axis offset from screen center", ""
+ },
+ {
+ "cg_simpleItems", CVART_BOOL,
+ "Simple items", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Shows items as sprites", ""
+ },
+ {
+ "cg_brassTime", CVART_INTEGER,
+ "Brass lifetime", CVARCAT_GRAPHICS, "MG/SG shell visibility duration, in milliseconds", ""
+ },
+ {
+ "cg_marks", CVART_INTEGER,
+ "Explosion marks lifetime", CVARCAT_GRAPHICS, "Explosion marks visibility duration, in milliseconds", ""
+ },
+ {
+ "cg_railTrailTime", CVART_INTEGER,
+ "Rail trails lifetime", CVARCAT_GRAPHICS, "Rail trails visibility duration, in milliseconds", ""
+ },
+ {
+ "cg_errordecay", CVART_INTEGER,
+ "Prediction error decay", CVARCAT_NETWORK, "Duration for client-side mispredictions smoothing, in milliseconds", ""
+ },
+ {
+ "cg_predict", CVART_INTEGER,
+ "Player movement prediction", CVARCAT_NETWORK, "", "",
+ CVAR_GUI_VALUE("0", "Disabled", "")
+ CVAR_GUI_VALUE("1", "Enabled", "")
+ CVAR_GUI_VALUE("2", "Optimized", "Has errors and performance gains aren't significant")
+ },
+ {
+ "cg_noProjectileTrail", CVART_BOOL,
+ "Projectile trails", CVARCAT_GRAPHICS, "", "",
+ CVAR_GUI_VALUE("1", "None in water", "")
+ CVAR_GUI_VALUE("0", "Everywhere", "")
+ },
+ {
+ "cg_noTaunt", CVART_BOOL,
+ "Taunt sounds", CVARCAT_SOUND, "", "",
+ CVAR_GUI_VALUE("1", "Silence", "")
+ CVAR_GUI_VALUE("0", "Taunt sounds", "")
+ },
+ {
+ "cg_forceModel", CVART_BOOL,
+ "Force model on teammates", CVARCAT_GRAPHICS, "Draws your teammates with the same model as yours", ""
+ },
+ {
+ "cg_predictItems", CVART_BOOL,
+ "Item pick-up prediction", CVARCAT_NETWORK, "Disable if you get false pick-ups", ""
+ },
+ {
+ "cg_deferPlayers", CVART_BOOL,
+ "Delay model loads", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Delays player model loads to avoid hitches", ""
+ },
+ {
+ "cg_drawFriend", CVART_BOOL,
+ "Friend markers", CVARCAT_HUD, "Draws triangles above teammates' heads", ""
+ },
+ {
+ "cg_teamChatsOnly", CVART_BOOL,
+ "Global chat sink", CVARCAT_HUD, "To which SuperHUD element does global chat go?", "Team chat always goes to the 'Chat' SuperHUD element",
+ CVAR_GUI_VALUE("0", "Chat", "")
+ CVAR_GUI_VALUE("1", "Console", "")
+ },
+ {
+ "cg_altLightning", CVART_STRING,
+ "LG beam style", CVARCAT_GRAPHICS, "In order: self, enemies, teammates",
+ "0 = Original (pre-TA) id LG beam\n"
+ "1 = CPMA lightning\n"
+ "2 = Thin lightning\n"
+ "3 = Lightning using 1.44 render"
+ },
+ {
+ "cg_altPlasma", CVART_BOOL,
+ "CPMA plasma projectile", CVARCAT_GRAPHICS, "Enables the CPMA plasma gun projectile", ""
+ },
+ {
+ "cg_autoAction", CVART_BITMASK,
+ "Automated actions", CVARCAT_GENERAL, "", "",
+ CVAR_GUI_VALUE("0", "Save stats to a .txt file", "")
+ CVAR_GUI_VALUE("1", "Take an end-game screenshot", "")
+ CVAR_GUI_VALUE("2", "Record a demo: match start", "Only if present at match start")
+ CVAR_GUI_VALUE("3", "Multi-view the game", "")
+ CVAR_GUI_VALUE("4", "Only if you're playing", "")
+ CVAR_GUI_VALUE("5", "Follow power-up", "")
+ CVAR_GUI_VALUE("6", "Follow killer", "")
+ CVAR_GUI_VALUE("7", "Record a demo: late join", "When not present at match start")
+ },
+ {
+ "cg_customLoc", CVART_BOOL,
+ "Custom map locations", CVARCAT_HUD, "Uses client-local map location names", "The locations are in .cfg files in the 'locs' folder"
+ },
+ {
+ "cg_nochatbeep", CVART_BOOL,
+ "Global chat beeps", CVARCAT_SOUND, "", "",
+ CVAR_GUI_VALUE("0", "Global chat beeps", "")
+ CVAR_GUI_VALUE("1", "Silence", "")
+ },
+ {
+ "cg_nomip", CVART_BITMASK,
+ "Picmip overrides", CVARCAT_GRAPHICS, "Enable to keep specific visuals sharp", "",
+ CVAR_GUI_VALUE("0", "Lightning beams", "")
+ CVAR_GUI_VALUE("1", "Plasma balls", "")
+ CVAR_GUI_VALUE("2", "Rocket and grenade explosions", "")
+ CVAR_GUI_VALUE("3", "Grenade projectiles", "")
+ CVAR_GUI_VALUE("4", "Bullet impact marks", "")
+ CVAR_GUI_VALUE("5", "Railgun impact mark", "")
+ CVAR_GUI_VALUE("6", "BFG explosion", "")
+ CVAR_GUI_VALUE("7", "Blood", "")
+ CVAR_GUI_VALUE("8", "Smoke", "")
+ CVAR_GUI_VALUE("9", "Rocket projectiles", "")
+ },
+ {
+ "cg_noteamchatbeep", CVART_BOOL,
+ "Team chat beeps", CVARCAT_SOUND, "", "",
+ CVAR_GUI_VALUE("1", "Silence", "")
+ CVAR_GUI_VALUE("0", "Team chat beeps", "")
+ },
+ {
+ "cg_oldCTFSounds", CVART_INTEGER,
+ "CTF sounds", CVARCAT_SOUND, "", "",
+ CVAR_GUI_VALUE("0", "Team Arena", "With voice-overs")
+ CVAR_GUI_VALUE("1", "Quake 3 1.17", "Same for both teams")
+ CVAR_GUI_VALUE("2", "Team-specific", "No voice-overs")
+ },
+ {
+ "cg_showPlayerLean", CVART_BOOL,
+ "Player model leaning", CVARCAT_GAMEPLAY, "Enables player model leaning", "Off is more accurate wrt collision models"
+ },
+ {
+ "cg_useScreenShotJPEG", CVART_BOOL,
+ "Automated screenshot format", CVARCAT_GENERAL, "", "",
+ CVAR_GUI_VALUE("0", "TARGA (.tga)", "")
+ CVAR_GUI_VALUE("1", "JPEG (.jpg)", "")
+ },
+ {
+ "color", CVART_COLOR_CHBLS,
+ "Player colors", CVARCAT_GRAPHICS, "", "",
+ },
+ {
+ "model", CVART_STRING,
+ "Player model", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ "nick", CVART_STRING,
+ "Nickname", CVARCAT_GENERAL, "Short name (max. 5 chars) for team overlays", ""
+ }
+};
+
+
void CL_Init()
{
//QSUBSYSTEM_INIT_START( "Client" );
@@ -2270,3 +2961,15 @@ void CL_Shutdown()
Com_Printf( "-----------------------\n" );
}
+
+
+void CL_SetMenuData( qboolean typeOnly )
+{
+ for ( int i = 0; i < ARRAY_LEN( cpma_cvars ); ++i ) {
+ const cvarTableItemCPMA_t* const cvar = &cpma_cvars[i];
+ Cvar_SetDataType( cvar->name, cvar->type );
+ if ( !typeOnly ) {
+ Cvar_SetMenuData( cvar->name, cvar->categories, cvar->guiName, cvar->guiDesc, cvar->guiHelp, cvar->guiValues );
+ }
+ }
+}
diff --git a/code/client/cl_scrn.cpp b/code/client/cl_scrn.cpp
index 5972e7c..b00f5ef 100644
--- a/code/client/cl_scrn.cpp
+++ b/code/client/cl_scrn.cpp
@@ -34,40 +34,6 @@ static cvar_t* cl_graphscale;
static cvar_t* cl_graphshift;
-struct intStats_t {
- int samples[200];
- int sampleCount;
- int writeIndex;
- int median;
- int percentile99;
-};
-
-
-static int QDECL CompareSamples( const void* a, const void* b )
-{
- return *(const int*)b - *(const int*)a;
-}
-
-
-static void PushSample( intStats_t* stats, int sample )
-{
- stats->samples[stats->writeIndex] = sample;
- stats->sampleCount = min(stats->sampleCount + 1, (int)ARRAY_LEN(stats->samples));
- stats->writeIndex = (stats->writeIndex + 1) % ARRAY_LEN(stats->samples);
- if ( stats->sampleCount < ARRAY_LEN(stats->samples) ) {
- stats->median = 0;
- stats->percentile99 = 0;
- return;
- }
-
- static intStats_t temp;
- memcpy( temp.samples, stats->samples, stats->sampleCount * sizeof(int) );
- qsort( temp.samples, stats->sampleCount, sizeof(int), &CompareSamples );
- stats->median = temp.samples[stats->sampleCount / 2];
- stats->percentile99 = temp.samples[stats->sampleCount / 10];
-}
-
-
// adjust for resolution and screen aspect ratio
void SCR_AdjustFrom640( float *x, float *y, float *w, float *h )
@@ -337,72 +303,6 @@ static void SCR_DrawScreenField( stereoFrame_t stereoFrame )
}
-static int pcFE[RF_STATS_MAX];
-static int pc2D[RB_STATS_MAX];
-static int pc3D[RB_STATS_MAX];
-static intStats_t usecFE;
-static intStats_t usec3D;
-static intStats_t usecBS;
-static intStats_t usecGPU;
-
-
-static void SCR_PerformanceCounters()
-{
- extern qbool Sys_V_IsVSynced();
-
- float x, y, cw = 8, ch = 12;
- SCR_AdjustFrom640( 0, 0, &cw, &ch );
-
- x = 0, y = 240;
- SCR_AdjustFrom640( &x, &y, 0, 0 );
- SCR_DrawString( x, y, cw, ch, va("FE: %.2fms (99th: %.2fms)", usecFE.median / 1000.0f, usecFE.percentile99 / 1000.0f ), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Leaf/Area: %i %i", pcFE[RF_LEAF_CLUSTER], pcFE[RF_LEAF_AREA]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("FrusLeafs: %i", pcFE[RF_LEAFS]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("MD3 Cull S: %i %i %i", pcFE[RF_MD3_CULL_S_IN], pcFE[RF_MD3_CULL_S_CLIP], pcFE[RF_MD3_CULL_S_OUT]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("MD3 Cull B: %i %i %i", pcFE[RF_MD3_CULL_B_IN], pcFE[RF_MD3_CULL_B_CLIP], pcFE[RF_MD3_CULL_B_OUT]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Bez Cull S: %i %i %i", pcFE[RF_BEZ_CULL_S_IN], pcFE[RF_BEZ_CULL_S_CLIP], pcFE[RF_BEZ_CULL_S_OUT]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Bez Cull B: %i %i %i", pcFE[RF_BEZ_CULL_B_IN], pcFE[RF_BEZ_CULL_B_CLIP], pcFE[RF_BEZ_CULL_B_OUT]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Light Cull: %i %i", pcFE[RF_LIGHT_CULL_IN], pcFE[RF_LIGHT_CULL_OUT]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Lit Leafs: %i", pcFE[RF_LIT_LEAFS]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Lit Surfs: %i %i", pcFE[RF_LIT_SURFS], pcFE[RF_LIT_CULLS]), qfalse ); y += ch;
-
- x = 240, y = 240;
- SCR_AdjustFrom640( &x, &y, 0, 0 );
- SCR_DrawString( x, y, cw, ch, va("3D: %.2fms (99th: %.2fms)", usec3D.median / 1000.0f, usec3D.percentile99 / 1000.0f ), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("End: %.2fms (99th: %.2fms)", usecBS.median / 1000.0f, usecBS.percentile99 / 1000.0f ), qfalse ); y += ch;
- if ( usecGPU.sampleCount > 0 ) {
- SCR_DrawString( x, y, cw, ch, va("GPU: %.2fms (99th: %.2fms)", usecGPU.median / 1000.0f, usecGPU.percentile99 / 1000.0f ), qfalse ); y += ch;
- }
- SCR_DrawString( x, y, cw, ch, va("Base Verts: %i", pc3D[RB_VERTICES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Base Tris: %i", pc3D[RB_INDICES] / 3), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Base Surfs: %i", pc3D[RB_SURFACES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("B Batches: %i", pc3D[RB_BATCHES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Shdr Chges: %i", pc3D[RB_SHADER_CHANGES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Draw Calls: %i", pc3D[RB_DRAW_CALLS]), qfalse ); y += ch;
-
- SCR_DrawString( x, y, cw, ch, va("Lit Verts: %i", pc3D[RB_LIT_VERTICES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Lit Tris: %i", pc3D[RB_LIT_INDICES] / 3), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Lit Surfs: %i", pc3D[RB_LIT_SURFACES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("L Batches: %i", pc3D[RB_LIT_BATCHES]), qfalse ); y += ch;
-
- SCR_DrawString( x, y, cw, ch, va("L LateCullT: %i", pc3D[RB_LIT_VERTICES_LATECULLTEST]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("L LateCullI: %i %i", pc3D[RB_LIT_INDICES_LATECULL_IN], pc3D[RB_LIT_INDICES_LATECULL_OUT]), qfalse ); y += ch;
-
- x = 480, y = 240;
- SCR_AdjustFrom640( &x, &y, 0, 0 );
- SCR_DrawString( x, y, cw, ch, "2D", qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Vertices: %i", pc2D[RB_VERTICES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Indices: %i", pc2D[RB_INDICES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Surfaces: %i", pc2D[RB_SURFACES]), qfalse ); y += ch;
- SCR_DrawString( x, y, cw, ch, va("Batches: %i", pc2D[RB_BATCHES]), qfalse ); y += ch;
-
- x = 0, y = 480 - ch;
- SCR_AdjustFrom640( &x, &y, 0, 0 );
- SCR_DrawString( x, y, cw, ch, va("Back-end: %s", Cvar_VariableString("r_backend")), qfalse ); y -= ch;
- SCR_DrawString( x, y, cw, ch, va("V-Sync : %s", Sys_V_IsVSynced() ? "ON" : "OFF"), qfalse ); y -= ch;
-}
-
-
void CL_AbortFrame()
{
scr_updateActive = qfalse;
@@ -436,16 +336,8 @@ void SCR_UpdateScreen()
// function (or any function for that matter) is not always reached.
scr_updateActive = qtrue;
- PushSample( &usecFE, pcFE[RF_USEC] );
- PushSample( &usec3D, pc3D[RB_USEC] );
- PushSample( &usecBS, pc3D[RB_USEC_END] );
- if ( pc3D[RB_USEC_GPU] > 0 )
- PushSample( &usecGPU, pc3D[RB_USEC_GPU] );
- else
- usecGPU.sampleCount = 0;
-
if ( scr_frameBegun ) {
- re.EndFrame( NULL, NULL, NULL, qfalse );
+ re.EndFrame( qfalse );
scr_frameBegun = qfalse;
}
@@ -454,22 +346,8 @@ void SCR_UpdateScreen()
SCR_DrawScreenField( STEREO_CENTER );
const qbool drawFrame = CL_VideoRecording() || !Sys_IsMinimized();
- if ( com_speeds->integer ) {
- re.EndFrame( pcFE, pc2D, pc3D, drawFrame );
- scr_frameBegun = qfalse;
- time_frontend = pcFE[RF_USEC];
- time_backend = pc3D[RB_USEC];
- } else if ( Cvar_VariableIntegerValue("r_speeds") ) {
- // counters are actually the previous frame's, because EndFrame will clear them
- // and we need to submit the calls to show them before that
- if ( re.Registered() )
- SCR_PerformanceCounters();
- re.EndFrame( pcFE, pc2D, pc3D, drawFrame );
- scr_frameBegun = qfalse;
- } else {
- re.EndFrame( NULL, NULL, NULL, drawFrame );
- scr_frameBegun = qfalse;
- }
+ re.EndFrame( drawFrame );
+ scr_frameBegun = qfalse;
if ( cls.maxFPS > 0 )
cls.nextFrameTimeMS = Sys_Milliseconds() + 1000 / cls.maxFPS;
diff --git a/code/client/cl_ui.cpp b/code/client/cl_ui.cpp
index 9999cb0..a65c92c 100644
--- a/code/client/cl_ui.cpp
+++ b/code/client/cl_ui.cpp
@@ -1188,6 +1188,7 @@ void CL_InitUI()
// init for this gamestate
VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE) );
+ CL_SetMenuData( qfalse );
}
diff --git a/code/client/client.h b/code/client/client.h
index 49ec342..a0d87ba 100644
--- a/code/client/client.h
+++ b/code/client/client.h
@@ -379,8 +379,6 @@ extern cvar_t *cl_matchAlerts; // bit mask, see the MAF_* constants
extern cvar_t *cl_demoPlayer;
extern cvar_t *cl_escapeAbortsDemo;
-extern cvar_t *r_khr_debug;
-
extern cvar_t *s_autoMute;
//=================================================
diff --git a/code/client/client_help.h b/code/client/client_help.h
index 30638c8..7c50d43 100644
--- a/code/client/client_help.h
+++ b/code/client/client_help.h
@@ -124,12 +124,6 @@ S_COLOR_VAL " 2 " S_COLOR_HELP "= Draws the help panel even if the cvar/cmd h
S_COLOR_VAL " 4 " S_COLOR_HELP "= Draws the list of modules\n" \
S_COLOR_VAL " 8 " S_COLOR_HELP "= Draws the list of attributes (cvars only)"
-#define help_r_khr_debug \
-"enables an OpenGL debug context\n" \
-S_COLOR_VAL " 0 " S_COLOR_HELP "= Forced off\n" \
-S_COLOR_VAL " 1 " S_COLOR_HELP "= Forced on\n" \
-S_COLOR_VAL " 2 " S_COLOR_HELP "= On in debug builds only"
-
#define help_net_proxy \
"proxy server address\n" \
"Set this CVar before connecting to a server to join through a proxy.\n" \
diff --git a/code/client/snd_main.cpp b/code/client/snd_main.cpp
index 78c62f9..540ffc5 100644
--- a/code/client/snd_main.cpp
+++ b/code/client/snd_main.cpp
@@ -235,10 +235,22 @@ static void S_Music_f( void )
static const cvarTableItem_t cl_cvars[] =
{
- { &s_volume, "s_volume", "0.2", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "global sound volume" },
- { &s_musicVolume, "s_musicvolume", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "16", "music volume" },
+ {
+ &s_volume, "s_volume", "0.2", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "global sound volume",
+ "Sound volume", CVARCAT_SOUND, "", ""
+ },
+ {
+ &s_musicVolume, "s_musicvolume", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "16", "music volume",
+ "Music volume", CVARCAT_SOUND, "", ""
+ },
{ &s_initsound, "s_initsound", "1", 0, CVART_BOOL, NULL, NULL, "enables the audio system" },
- { &s_autoMute, "s_autoMute", "1", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", help_s_autoMute }
+ {
+ &s_autoMute, "s_autoMute", "1", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", help_s_autoMute,
+ "Auto-mute", CVARCAT_SOUND, "Pick scenarios where audio output should be disabled", "",
+ CVAR_GUI_VALUE("0", "Never", "")
+ CVAR_GUI_VALUE("1", "Window is not focused", "")
+ CVAR_GUI_VALUE("2", "Window is minimized", "")
+ }
};
diff --git a/code/imgui/Sweet16Mono.h b/code/imgui/Sweet16Mono.h
new file mode 100644
index 0000000..b4b6c13
--- /dev/null
+++ b/code/imgui/Sweet16Mono.h
@@ -0,0 +1,130 @@
+// File: 'Sweet16mono.ttf' (35096 bytes)
+// Exported using binary_to_compressed_c.cpp
+static const char Sweet16mono_compressed_data_base85[14165+1] =
+ "7])#######p6:o*'/###[),##0rC$#Q6>##T@;*>7+[-*rFB`N9g>11gZn42MfO4H:.>>#I&g<6aNV=B^-9V+41+>00FKrO7Z*3W%WgJe$sCbA#5Yn0#.UufLJ7$##g(EX()`^>$4FCB#PPj)#b9w0#I)###R?3L#2gES7.ALe$"
+ "UG:;$d?%;Q(2###OC@2TUIx],.:$$$dIOe#=;2U2*VFgLC,9;-87c`NZx)oCM-m.Lo[WiKX3n0#0Dde$.Un7RvOXW>P[0h7?>#XO@'MQU;;$(l9B#O'###Xpo(NTC-##$,n.LQ172L"
+ "D9nw'M,Lk+,]F+=x5+7cw0#54cA#4lJe$g,7N#T-:M#Il62Ls:3_]/fkA#/o8gLaRwA-.]jfLq5]0#+rbA#)]F^g#.-f%v;)e=75+ZwgM#bOx0#@#CxpJBCn+k'#(/d%N#"
+ "NqB.$AJ31#O[YZp8.$d+?>#r%9;--G5-Mm8#/2TkL*L>gLPX6##MwQ0#P)n,v0t&019>)4#'.Y:vvo64vqk'hMMk;Z#+J,W-UTah#)V'B#U1FcMF=6##7DbA#8xg)3&5>##,AP##"
+ "0Mc##4Yu##8f1$#+#n[P+#rhc+#vtu+#$+2,#(7D,#,CV,#0Oi,#4[%-#8h7-#vO6#F8u6#JJ:7#@(1/#D6o-#?;.6/=E24#-HwqLpQV/#8TGs-t^ovL>'crLJ:$##050sL'Dpr-:S^sLNpr-0#('v/6(*o,?(GSYJ(GV+gen-+Y-v;+gQ)D+fV8M+76ot+J(%d+q`Qo+<_#$,p$V0,QfHW,?>/I,x^7T,7]__,cl)l,pLa9-'3Z(-/;j1-"
+ "0-)<-;K2D-;SAM-JkcV-[c4b-kgw1.@(ew-T/H,.6-D8.`1(C.sA'j.XW>Z.sFSe.@Q7p.(I3&/OrVL/s&2T>?0KLoe0w>%T0%x'_0L,bi0"
+ "f$3t0M_6%1H&tI1bT/:1B+JE15CAM1xaJU1nP5_1iCvg1naSq10,2%2?[x.2a.=:2a6LC2OB1K2Rx3U2.p8'3[0&m2Lt9$3`Y<.3w^v83Vt@E3kvMT3=5nd3WC7t3SNq(4HGn14B+F:4"
+ "M)nD4_.'N4JtgV4Y53a4XRgj4osDt4&L`)573QS59$]E5.OKR5&@``50t5o5U%###AU`mLw^;b$&6>##`$At[:^/@66RG##Pui/%Iq8;]`>(C&Okk2$7U$Z$AGs8].#KxtA:u+MaAoO("
+ "FaKZ-F3qa#hZ9B#(qgb$d1&)9%dh-?v<pV-(h%1#LvAxtQBa+MpC$##+SUV$9*:5eHp.[k=G)>uu)uY<-0C(&O0:K/L&YsfL#@GGMd1]guM%72Lq&f8&XC3#.jmwVQ5_clhCH-P#jE-C5T;-rmj'/(+)W-w$i-QWL#H308D#6Ym-UMMG7BM"
+ "%;>GMQ==R-)rY<-6RPHM)5pr-.J&GMQ?M.ML.->#Xa0OO+l'hL-Ndh-J4-mOVN#,28YR]4_*%##Tlvk0K5&@T4sx9)Xc?l+ko0:)xH-^#r4+Au;F5F%Q;1S*u%+GMaed##)0OcM2-g(N"
+ "h^02'%/5##I-%'#&0fX-x)tb.0dic)4sN;MfJ)^%w_@#6-Q8c$S]6g)L@#l$0,fA#=v3=Uao^&Ork]c$%F[oG4O4UKMC&uc^Y#%gv>R)>rB#[55?%)OP,MFiVV$YUg%OxF%'MnNwq7"
+ "eS9N(BDjc))3D^61F5gL%r8R]u)=@^$vCF]u+rbA##r#Z$p'NW-#9o'/f%rHH>Yd-H"
+ "?i2.HK;>(Anr5<-qsG%.+G/cMGp-A-1O%:.)JW-$FvK=-OYQt.P3G>#sNHh,&(#F@tun+MBJZY#_fdw'[WdA#sc&@'5lo-Hc-p0#wuIfLZZux7`wq?BL1^;.gbYt&kv[DN@ibl8eZTx9"
+ "R=IHg)*p*O=Y*&7*+ji.L$>G##Ni./LjsiqL_U;;$nX&`]_WOO_Ei-wD3LYM/Qs.-t1/$[q:a4M8V']E5N+M72#HMm1]guC+_;%(_:lF"
+ "=8`B#5ak;-O(m<-H+AuaR1HMpFMkCA$8D2w-dbF:Pbni_3=2vao7VmZ-d:jEv$8aR'C-c;@+P2YX-$c6/U`#dRn[L]u;.t-$Avo/?^=cGM;X`QMx;`B#475GM)*,DN"
+ "7#^GMs$&0u0),F@')h>P/f;>MpA%n&EIRZ%.F5gLoHp;-.YP*8RJ>?I_Uup74$=&'VxpHd?<^E[c?EfM+jG<-DNMJ)&YrB8'E%&u49J^dw9H]%YV4?IJ:?>#xbmM(CYd5/TKE/LkX(J:"
+ "O-q#$&2w.LR$Rn8$ut?0HCTfLvFkc%&R82L.U3W-]3bW8hrc598AK.$#lXK%%1NP/)m-ESWm[+2#E$q[d68J>P(JCJ_s-"
+ "&YsfLSw?R8r-L/)g7)n8'=pa#AFip.&df=#x$*9BH,7v8tPvqV9%1N(tB<#PwcxF/$>G##FBE`WKjeb%udO"
+ "fp;VST94S&f3W&H@Xto&G/G>#'tOo$o$mgL@[+5S_$Z9%S.:-MR^8+MD>Qu7[n^dkxwp`$$*.'1#bl9lOpAFENV_$:&]DN]uq;OJ?]/i>e%o>x%Vgx685Lo%u"
+ "'pv>RkD7N'f=)78)mbA#W[R$PN5KL8B8Q.QY[;Q8oFrBS7L2I-4n4K39VxC'mT/ZPt_ps$Ji:R*_5GgMCjQ293,I@B+_J=-AoO58>LT5qVV&nNe6u8MoEZY#S/lW-lgc'A+E_#$x+*L#"
+ "ItE2L5+S0+CuLQ8OA@2LTcq@-$sfl-No;G%'AhfM0(Eb$3Jw0#ba8F@,n%*NgY(3>68"
+ "L]?boZg]m8F&Nj;6.v<-Dt]v$Z)@#-lov-;*Gu`4SLe/:0Kc_-Q31p&fYHXfG*s+;b)'Z-/5T;-6<%/&8=6L,tHAe$O%;-F?XHM9pYmtLR1hmU"
+ "RhVV$-lJ,M,sxjO)43N(pgF=-bY*v%F),##:[U#$pkWw9C7dq73XbA#hM-f=ghavNuCh%%s9'=(kVfQW8B*NSvql%e+6/MULl2a-$N1@2L"
+ "r9aM-i^,%.i4B58/8K&Zs=RA-]@qhMF6fO:,%25.Cl8J<+KN%X?^8crQZ$OH_V$'jZ#R/;R#'N[C,M.k7I-&TgoL%v@%=aA@kt$%8g)s`$]-M'D#nDV4l8Hn3ltMBf68dg7?7uBW3&"
+ "mR)<-_b-q$Xn.HX9.(58V.uJaX2A/&x@Ixe+-tV$H5;U2F`pE@QbmJjEOas;uJ6Z$Go.F.BIX_JEFWpB5>EC*oXVj9X]$Z$>]>Eu(IqT:16-Rall-O=4_E<-%h.k<@OkM(Sw.)Q$@b4T"
+ "cRk;MA@GGMwgpr-lF^58[KRL*AR$m8_v#e4;GZ6)OwR<-NbUq7,Owct.n`^%lPlJ:d7buf,N=h#@x'4b6+Uk+NPUV$%2w.L8KfF@^ru299@<9BL=?>#NSU@-52eq$rVi.LVW_>>MVNh#"
+ "XwriLXe;f:b`//HfuDREg.xY-O1&rD$6.iGK;G##v>4Kj_st-8E]C_&I>6j9ET#:;m^,1#QYu##'n,tLd?Os'5i18.bw9hL]btV$JOi;-QXG-M.qVe$#m3(vG=LP8(?m;%Ju_C$:4#HM"
+ "0qS+MY@)$-@Fg%uN/aO&Kt:Stwjkm+'6)J9LT&T2kKP5GIkt'-,F%BI8QCFY4P8e=&BH'M#<-9EMm$[va6EwF=Au13P']`rKi9dp5q92X_E'](;<-s.I@AA-GjD/Piq%)lkA#H->W%"
+ ">m$w[05Fv/3S###);G##ZmL:)r5>T.@2<)#D(sf'S:jd;0C2^mX,Yv-pD?/:Yr:nsNxT)N@8Y[&V+2<-b7:1MAA:L&c,gm8c`rS&@gI#$tO?'OSt%V%TGl2`vF+Z%OHqKGcQXO9&UF]u"
+ "=e__&-MbwR[GVv;LXO=iqA&,q+9.&df=#,g6m9MAa&HBLf;%.aG%PWd?q&[va)N3A(-/&8P>#(ho2DEnGD'N6QZ>DTu9)JbKEurcc2:pH]4r&iJ+M92QX$Mxfxuw0Z,MT?Bk&vIF"
+ "#73<-u>On-YS&eZ?1NpBVFR#'O8l-$[26g:G*t-$(FvcM`N(]$)b3-v'Y3'-6/KV-dcNb&NYbA#85dW&fHt$';1?v$s:(eMt9si-,AkE[Ir5HMhxZi$Aw$Z$3e4thh;Il:b#fJjJNwq7"
+ "RE%`?Z=Db(>l_$@^(1H'48^l8QoiMiWiB1&)n]2LO*,##h4K#$7v+(QT,SjLr]nM.-SUV$LV23Vjos;&8nSg:kAs+l9[pk$=.%g:AHx?7E[L&OPRKC-I<.I-#5T;-gJ$i$ofx;%ph(j9"
+ "9--qpWg-U&$aY29VG/^dRnr(<^x$w%OYFo$TSl>Rac7?8fB[@B*m*^#A*Jp7ZBRaH.EF:.8/>`%$((%>:>^&vX6^7&^2(T.$DP##01g,Mmn;J:geO>?Pk-&@r'8qn$0uVnC,MK'AKu"
+ "n37kt0_<<-MHMWqC;0S[QZYSvv6'dfJQCZLLm8^9Y"
+ "xPhKcuA4.MlA*N&x?OK3aL_p$pSINs=7]V%`FZ=LH^Z^n.F5gL4is.L(#:p7Qh/I$s8D'SfLS9'1>G&9WHu`4_rwFROhV)N8%qgCIp1N;bw=W%B=e,=7)?T%gGXNBjg,g)o+Q68Fig)5Kx'29&AZ;%OI(@'>X7_A._L_A8?@`AiKo/:4M&'Hxx8;-cToc((u/I?@>h;-U0hET@6diQ5;VCY:?uSRH8n>'eGhW&%`sIL"
+ "m_JrDIil;D1wGQS:ItV$B;u;-x`DqP(v2G+mECWA65U1TO^2Q(7sN-O5gAvPU$hE9PHrc@8Qa;%w9[58aki>R1:>H&/3kM(&Me'%M9?)'9:,'vNAuwMLFo>-b2_[/+Sl##'DW-$Kt[-D"
+ "mp;;9*g1h$raj;-?@S3'572NBe)DdcfDA$9334K3RUx;%XcqQ8lEF]uKf,hLSqU]M^s5YT7,sY$l-)'-fu`Y8O5j(A%f-q78aaxBoX=K*UMWE-(>i;BTC?v$#NIojB#68#lo(h3g9V"
+ "O5alAe2M_Augfe$KcLH@pXmYPLFduY:?uSRjUUu?ko3AB1XWdXH'>[$6tjnb_'.hsDS1`fLo$39H3u5VVCC290R5F%"
+ "gFe39R0#]S&FPGMa'BT,$=4h:Ww?-+4QX-$.ZsH?cmk?%.3QD-h1aY8r7j(AKGL39U=tXC+2DiMci<(&kZ8,Nu;$++cNj&v92]:&.F5F@1h(G@JW+<-Jld,B]eGF%ci`sTZ6jJ:Z=72L"
+ "@jD$T]nb?.Y+MA&hW4XA86ea$/GM<-V4Z`%RA/^#kv-AuK_%/,h#@UMCF5gLRF1q7KdB#$rd`w'JvXp7jh@vnXA9s7C/AR3O0jp7J:]`tmQ.9CWVw3;u-8jiU^gw76FKQ_V(V#**L*q7"
+ "p$CmX#_)/+A&;.ON2oo%K;g[Ptn3+(LeG$>Is'^#EgB2LQd0#>RrvV%)>n]IZ&JjLpirr$LxKU@eW^p9%&%i$_OfV'=DvpLV9Xc%,^h$'AmQGE'JT;.v8=p7>RG+@uEqweuOWILLT`iL"
+ "h_ks9Uv6BR;i@R&^I?hLZpw1Btg,$C9S_^OM#@#'.aBNs7`+)'kC1W]T9.ZSvxI>'Bim-H`jf'dQ=ArLLF/RM2?*C+(&rn1HMq6wQ%MFN<-1&vlM[sA,M90*j$,5k.+I'h,&.Rw;-2P:U;1MUwKFe/Y-`Vq$'SpK<-S&M]$P?p1:nd%*dLC]k*esap7u:Lk+?#b0H0A-_OKhXw&l=?s%7oe3mP5&Hvxv.ZqYG-6(]`@$(I90#(8^;%x^TvG2Z#:;9#8X1p0TTqaMnY%>nM?._D0A,-V6<-?.xY+p_DR8&?q.?EKBS8INQ&m(mWZ%nkx3)cB2gCW'F-=YuEs9"
+ "Wo*P='Y@S<+reS3bZPWe+)9vK>F@$uoE@JPjfLdecW%k=k3='-,F%APqM9Z1?v$;#c;-RxQx-ZLOgLGZtH$G0h>eR1Ae%M=[<-9_x+%iG0F.^cTLP6_368,W31#%3c'&-=?v$,f+Au"
+ "I+,C&?.oBJGgB@0L^x;-Z?^<(m:o:9w@aJ%5rrG;*Qd;%k$?KCJt%<;%4rDNBu]S)F8'W]M>#IGSkh><"
+ "&Rj.dcor)<3(J`tF#;P2*TvD-a22^'bbmAO5<#gLDOTN-'iu8.&=)0u'uE$^lLa5_adTd%B=+CJ%nWp7>4?v$XeMrF>Iq0,Yx^,M:D+`RcupP)Xt(Ks"
+ "*`xc&ccu<-sh.a$Cu^;%tr)BH<>#Y=W[pE@@j=^OF+WrQ)`uGMv2%>N,fFi[`[rGDi'Q&Q-H;B'H:@WSrXF%8gxpqF&c2=-Mu>u=EfQLG-24mJOtAfHL,3mJbUH9iWIZ)N4bVV$^xh-D"
+ "jsPQq)B'S%siIfLr[ko&Usg;-lap_-OMp9;jPKd4APMq%SUPC-A*QVCXo^d4jrd+9VE+Aun:ZFe*NC_&If#F@C_f1:279/bg3'D&Ro8$>T'Tv/W+7R,*%E^H'X[j)6r2O9sa0^#EF['&"
+ "t0E4;^[`Z=q2](o,(JsQgv5i8Hqo)?C#BX=#j/Zh_u0G:>fkM(m]S50,'k>PbJL9&lEfm82H-X/$]]D:Ykqkb:UnM(mhbMTp+L^=__-Lc=)=P)'/G+Z>VPTZJ"
+ "W6d=,gk#_@.h:dMFx,C_m]N7))lgv>HvaX]kj6p-:.Vs'DJmpL]`sILN'Q`t+%YRv+0?NNef&BC]b[&fWh>YhB+ZVn)$#8MTp9vsf0'Q1cv>2[vU7=ss-$-?g;-udm-&5FN<-)J=b*Z?#.;*>vV%"
+ "?,@r7B=0/HuN.HM=)@l*ZMtDNiQ8o'HnnM(xp3gC7b`Fn4;+^#4`QvPe]=4NKcb4%-M(0C@Qu`4m;ZH;'2J`t*K.?7^RE$'bF2<-fC0%%GP649hC-?$$,n.Lw1OHKS%@g.K[sv7As>:;x<2uU1>:oWSP)V7ZNlBATFCu?[?CwIM7-##cSGW-W]s-Z5VJU)ksop7w&wU73(Ol=4.r(]9fZ-ZKE0xBPmT<-$Tg*?$<<$o;iN#(3BN=C"
+ "Fmkb*HMXT@`(u_fAmFEN%fao:httPrD;6j--[H#$[v+$PT_G_d.%,cM]T]F-km<1=Z+'/+2Aim&GL,U`%8Nn3/g;:;0Fcc<,.vgb$:u=#>30p7`M&^d:)d-(YGQ)c3utO8nIvV%>_-q@f1jg=gbm##%=F=-]c/s&xuANW?t;R+UD*(=$#I:T"
+ "7hQ=P-:iSe[6F,'ma>KWT9@'(Cu3X:s7I<-B/kiFYkWY/iug41%sn8e^&vL;8La+YO%LRMuB7Z+<'.uJ8`X4)*%ficb*?Bp;QoE<#PHmg%%hxdH;@3Mj;*c+)'Du>j<2#dT%jVm)V(]L@qsS;.NZ)wuIfL%p_k*AMmT.>uv9.PqEr$1#E''$1m;%ouMp^X[<4-mn>n)Hh5@(&Aj34ij_q;KbspBfET@'HxNd;;s@%>oiYb@1sao7v,$>8LAbK&AY8K4"
+ "/i*NNseup'iK?jV_uP(dd[S*3sGVtQE3R1K^/;Z[8f&gL(oS+MOGK5P&:Lwa*]^O<-OIFR-O((p$"
+ "xh_dMs'^fLBE;U%.W[3r@GlDRenI+'(Wit%u=bxu0R>,VBNco&+^8(JurbvYEAcHUU::mW'O$n.gQBpRLUA[9r69E#?9T8%ik'tRdew'8H5bp'D3sf:7^;:M#`gjKQ,?e6qB&I$fr>Q'"
+ "(:D>#0Pw0#sft:Q+fbA#E2GVn01L^#xYa@t1:h#$W=/8@2C-?$8$;VZ3LHZ$lLm=l4Udv$:UE5&GwuA#ko$@'WQo-$*fbA#`v?Ji01L^#raP.q/.U#$B?cBo/C-?$%hh%O3LHZ$YI%Da"
+ "NGP#%-N;fq+/G]FcgXoIT1PcDH]4GDcM8;-YqTiB+D-F%Xm>G27]nx42rD_&I$v1B^iF>HY8NDF,vOa=B2s.C%&w9)fl65&6[pfD]aYMCRA+#H/(=2CZfbYH5:=2CCde]G3(]PBALl`F"
+ "SJF>HDm*#H5FtiCF5B;I%aZMC*lm.6YBDP8DX=gG&>.FHMeZ<0,Beh2Jxwf;*DqoDka)SCl&ONEgcitB%dOVC6*TMF*'FG--xR+HE'^iF,j]>BL(3,N8rJfL_Y`/#,*B;-Q[lO-dF%U."
+ "/&iEHTS,<-`.%I-:QP8.oBvLFgnbP9J)F>HCdw]GLJ^*RPZ^f16Vs>-vw*bn50Z>-*i>#H.bfNbb)`_/i5xM17Pl-$%H)H2GxtLFkG6fGB0E,31-s]5m?.I-dt?a.w?vsBBfRU.F/#C5"
+ "I#+8QXv=ON**k#.QmXoLOwXrLTR=RMi2oiLkoUH-a(T,MmhHY>->hoDQ9eJ28*7L2m_=X(jodp'O/V#8ba0^#t1TV-]8[Bf_Ri2M*DTV-C%;I$_^m`*Xn..&D=P>#uOD4#-G31#xX#3#"
+ "=N<1#=lj1#kv%5#Rfa1#,#av&2#CYN1#rj#V#s1m3#o@/=#eG8=#t8J5#`+78#4uI-#m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#"
+ "mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#TmD<#<[(?#6f:?#:rL?#>(`?#B4r?#F@.@#JL@@#NXR@#Ree@#Vqw@#Z'4A#_3FA#"
+ "c?XA#gKkA#kW'B#od9B#spKB#w&_B#%3qB#)?-C#-K?C#1WQC#5ddC#9pvC#=&3D#A2ED#E>WD#IJjD#MV&E#Qc8E#UoJE#Y%^E#^1pE#b=,F#fI>F#jUPF#nbcF#rnuF#v$2G#$1DG#"
+ "(=VG#,IiG#0U%H#4b7H#8nIH#<$]H#@0oH#D<+I#HH=I#LTOI#PabI#TmtI#X#1J#]/CJ#a;UJ#eGhJ#iS$K#m`6K#qlHK#uxZK##/nK#';*L#+GW-wlHF%"
+ "?*+.NYt2.N?\?ZY%6:]/G$kse3^2>)4_;YD4`Du`4aM:&5pJ=44/O3INYq;INZwDIN['NIN,KdD-WKdD-WKdD-WKdD-WKdD-XT)a-m+wb%Y.wb%Xt%d3Xt%d3Xt%d3Xt%d3Xt%d3Xt%d3"
+ "Xt%d3Z-J)4Xc,<-l[uDNY4aINY4aINY4aINY4aINY4aINY4aINY4aINY**M2Yd&g2>;ge?Zphe?Zphe?Zphe?Zphe?Zphe?Zphe?Zphe?3[3INYq;IN,KdD-[KdD-[KdD-[KdD-[KdD-"
+ "[KdD-[KdD-]T)a-q+wb%Y.wb%]B=&5]B=&5]B=&5]B=&5]B=&5]B=&5]B=&5_QbA5Xc,<-l[uDN^L/JN^L/JN^L/JN^L/JN^L/JN^L/JN]Cj.NWqdL2Xc,<-kRY)NVndL2WqiG3TQ)a-"
+ "gW_e?.Fn-NVndL2WqiG3TQ)a-h^he?-I3INYq;IN,KdD-UKdD-UKdD-UKdD-UKdD-UKdD-UKdD-VT)a-k+wb%Y.wb%VbD,3vgu2MlkiU8Vs]G3gP#<-$D7F%=Ht2M[)E.3vgu2MlkiU8"
+ "Vs]G3gP#<-$D7F%=Ht2MlkiU8Vs]G3gP#<-$D7F%=Ht2MlkiU8Vs]G3gP#<-$D7F%=Ht2MlkiU8Vs]G3gP#<-$D7F%=Ht2M^;&f3vgu2MlkiU8Vs]G3jlu8.h@8(#xb9B#%;cY#/o8gL"
+ "vlsIhj]o'M6qlR*0x4:ZP+q3#";
+
+static ImFont *AddSweet16MonoFont()
+{
+ static const ImWchar Sweet16mono_ranges[] =
+ {
+ 0x0020, 0x017F, // Basic Latin + Latin supplement + Latin extended A
+ 0,
+ };
+
+ ImFontConfig config;
+ config.OversampleH = 1;
+ config.OversampleV = 1;
+ config.PixelSnapH = true;
+ config.SizePixels = 16;
+
+ // copy font name manually to avoid warnings
+ const char *name = "Sweet16 Mono (16px)";
+ char *dst = config.Name;
+
+ while (*name)
+ *dst++ = *name++;
+ *dst = '\0';
+
+ return ImGui::GetIO().Fonts->AddFontFromMemoryCompressedBase85TTF(Sweet16mono_compressed_data_base85, config.SizePixels, &config, Sweet16mono_ranges);
+}
diff --git a/code/qcommon/common.cpp b/code/qcommon/common.cpp
index 7200680..2db95af 100644
--- a/code/qcommon/common.cpp
+++ b/code/qcommon/common.cpp
@@ -93,10 +93,7 @@ cvar_t *com_noErrorInterrupt;
static cvar_t *con_completionStyle; // 0 = legacy, 1 = ET-style
static cvar_t *con_history;
-// com_speeds times
-int time_game;
-int time_frontend; // renderer frontend time
-int time_backend; // renderer backend time
+int time_game; // for com_speeds
int com_frameTime;
int com_frameNumber;
@@ -2189,7 +2186,10 @@ static const cmdTableItem_t com_cmds[] =
static const cvarTableItem_t com_cvars[] =
{
- { &com_maxfps, "com_maxfps", "125", CVAR_ARCHIVE, CVART_INTEGER, "60", "250", help_com_maxfps },
+ {
+ &com_maxfps, "com_maxfps", "125", CVAR_ARCHIVE, CVART_INTEGER, "60", "250", help_com_maxfps,
+ "Framerate cap", CVARCAT_DISPLAY, "If you see 'connection interrupted' online, lower the cap", ""
+ },
{ &com_developer, "developer", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "enables detailed logging" },
{ &com_logfile, "logfile", "0", CVAR_TEMP, CVART_INTEGER, "0", "2", help_com_logfile },
{ &com_timescale, "timescale", "1", CVAR_CHEAT | CVAR_SYSTEMINFO, CVART_FLOAT, "0", "100", "game time to real time ratio" },
@@ -2207,8 +2207,16 @@ static const cvarTableItem_t com_cvars[] =
#if defined(_WIN32) && defined(_DEBUG)
{ &com_noErrorInterrupt, "com_noErrorInterrupt", "0", 0, CVART_BOOL },
#endif
- { &con_completionStyle, "con_completionStyle", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_con_completionStyle },
- { &con_history, "con_history", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "writes the command history to a file on exit" }
+ {
+ &con_completionStyle, "con_completionStyle", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_con_completionStyle,
+ "Console completion style", CVARCAT_CONSOLE, "", "",
+ CVAR_GUI_VALUE("0", "Quake 3", "Always prints all results")
+ CVAR_GUI_VALUE("1", "Enemy Territory", "Prints once then cycles")
+ },
+ {
+ &con_history, "con_history", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "writes the command history to a file on exit",
+ "Save console history", CVARCAT_CONSOLE, "save the command history to a file on exit", ""
+ }
};
@@ -2621,9 +2629,7 @@ void Com_Frame( qbool demoPlayback )
int all = timeAfter - timeBeforeServer;
int sv = timeBeforeEvents - timeBeforeServer - time_game;
int ev = timeBeforeServer - timeBeforeFirstEvents + timeBeforeClient - timeBeforeEvents;
- int cl = timeAfter - timeBeforeClient - (time_frontend + time_backend);
- Com_Printf( "frame:%i all:%3i sv:%3i ev:%3i cl:%3i gm:%3i rf:%3i bk:%3i\n",
- com_frameNumber, all, sv, ev, cl, time_game, time_frontend, time_backend );
+ Com_Printf( "frame:%i all:%3i sv:%3i ev:%3i gm:%3i\n", com_frameNumber, all, sv, ev, time_game );
}
//
@@ -3527,12 +3533,13 @@ printHelpResult_t Com_PrintHelp( const char* name, printf_t print, qbool printNo
if ( !desc ) {
if ( printNotFound )
print( "no help text found for %s %s%s\n",
- isCvar ? "cvar" : "command", isCvar ? S_COLOR_CVAR : S_COLOR_CMD, name );
+ isCvar ? "cvar" : "command", isCvar ? S_COLOR_CVAR : S_COLOR_CMD, name );
return PHR_NOHELP;
}
const char firstLetter = toupper( *desc );
print( S_COLOR_HELP "%c%s" S_COLOR_HELP ".\n", firstLetter, desc + 1 );
+
if ( help )
print( S_COLOR_HELP "%s\n", help );
@@ -3690,3 +3697,29 @@ void Com_StatsFromArray( const float* input, int numSamples, float* temp, stats_
{
StatsFromArray( input, numSamples, &SortFloatDescending, temp, stats );
}
+
+
+void Com_ParseHexColor( float* c, const char* text, qbool hasAlpha )
+{
+ c[0] = 1.0f;
+ c[1] = 1.0f;
+ c[2] = 1.0f;
+ c[3] = 1.0f;
+
+ unsigned int uc[4];
+ if ( hasAlpha ) {
+ if ( sscanf(text, "%02X%02X%02X%02X", &uc[0], &uc[1], &uc[2], &uc[3]) != 4 )
+ return;
+ c[0] = uc[0] / 255.0f;
+ c[1] = uc[1] / 255.0f;
+ c[2] = uc[2] / 255.0f;
+ c[3] = uc[3] / 255.0f;
+ } else {
+ if ( sscanf(text, "%02X%02X%02X", &uc[0], &uc[1], &uc[2]) != 3 )
+ return;
+ c[0] = uc[0] / 255.0f;
+ c[1] = uc[1] / 255.0f;
+ c[2] = uc[2] / 255.0f;
+ c[3] = 1.0f;
+ }
+}
diff --git a/code/qcommon/cvar.cpp b/code/qcommon/cvar.cpp
index 76495bc..0934763 100644
--- a/code/qcommon/cvar.cpp
+++ b/code/qcommon/cvar.cpp
@@ -183,33 +183,27 @@ void Cvar_EnumHelp( search_callback_t callback, const char* pattern )
}
-static qbool Cvar_IsValidValuePrintNothing( cvar_t *var, const char *value )
+static qbool IsHexChar( char c )
{
- if ( var->type == CVART_STRING )
- return qtrue;
-
- if ( var->type == CVART_FLOAT ) {
- float f;
- if ( sscanf(value, "%f", &f) != 1 ||
- !isfinite(f) ||
- f < var->validator.f.min ||
- f > var->validator.f.max)
- return qfalse;
- } else {
- int i;
- if ( sscanf(value, "%d", &i) != 1 ||
- i < var->validator.i.min ||
- i > var->validator.i.max)
- return qfalse;
- }
-
- return qtrue;
+ return
+ ( c >= 'a' && c <= 'f' ) ||
+ ( c >= 'A' && c <= 'F' ) ||
+ ( c >= '0' && c <= '9' );
}
-static qbool Cvar_IsValidValuePrintWarnings( cvar_t *var, const char *value )
+static qbool IsCPMAColorCode( char c )
{
-#define WARNING( Message ) { Com_Printf( "^3%s: " Message "\n", var->name ); return qfalse; }
+ return
+ ( c >= 'a' && c <= 'z' ) ||
+ ( c >= 'A' && c <= 'Z' ) ||
+ ( c >= '0' && c <= '9' );
+}
+
+
+static qbool Cvar_IsValidValue( cvar_t *var, const char *value, qboolean printWarnings )
+{
+#define WARNING( Message ) { if ( printWarnings ) Com_Printf( "^3%s: " Message "\n", var->name ); return qfalse; }
if ( var->type == CVART_STRING )
return qtrue;
@@ -222,7 +216,7 @@ static qbool Cvar_IsValidValuePrintWarnings( cvar_t *var, const char *value )
WARNING( "float value too low" )
if( f > var->validator.f.max )
WARNING( "float value too high" )
- } else {
+ } else if ( var->type == CVART_INTEGER || var->type == CVART_BITMASK ) {
int i;
if ( sscanf(value, "%d", &i) != 1 )
WARNING( "not a whole number (integer)" )
@@ -230,6 +224,39 @@ static qbool Cvar_IsValidValuePrintWarnings( cvar_t *var, const char *value )
WARNING( "integer value too low" )
if( i > var->validator.i.max )
WARNING( "integer value too high" )
+ } else if ( var->type == CVART_BOOL ) {
+ if ( strlen(value) != 1 )
+ WARNING( "must be a single char" );
+ if ( value[0] != '0' && value[0] != '1' )
+ WARNING( "must be 0 or 1" );
+ } else if ( var->type == CVART_COLOR_RGB ) {
+ if ( strlen(value) != 6 )
+ WARNING( "must be 6 hex chars" );
+ for ( int i = 0; i < 6; ++i ) {
+ if ( !IsHexChar(value[i]) )
+ WARNING( "must be 6 hex chars" );
+ }
+ } else if ( var->type == CVART_COLOR_RGBA ) {
+ if ( strlen(value) != 8 )
+ WARNING( "must be 8 hex chars" );
+ for ( int i = 0; i < 8; ++i ) {
+ if ( !IsHexChar(value[i]) )
+ WARNING( "must be 8 hex chars" );
+ }
+ } else if ( var->type == CVART_COLOR_CPMA ) {
+ if ( strlen(value) != 1 )
+ WARNING( "must be a single char" );
+ if ( !IsCPMAColorCode(value[0]) )
+ WARNING( "invalid color code, must be [a-zA-Z0-9]" );
+ } else if ( var->type == CVART_COLOR_CHBLS ) {
+ if ( strlen(value) != 5 )
+ WARNING( "must be 5 chars" );
+ for ( int i = 0; i < 5; ++i ) {
+ if ( !IsCPMAColorCode(value[i]) )
+ WARNING( "must be 5 color codes [a-zA-Z0-9]" );
+ }
+ } else {
+ Q_assert( !"Unsupported CVar type" );
}
return qtrue;
@@ -238,14 +265,6 @@ static qbool Cvar_IsValidValuePrintWarnings( cvar_t *var, const char *value )
}
-static qbool Cvar_IsValidValue( cvar_t *var, const char *value, qbool printWarnings )
-{
- return printWarnings ?
- Cvar_IsValidValuePrintWarnings( var, value ) :
- Cvar_IsValidValuePrintNothing( var, value );
-}
-
-
static void Cvar_PrintDeprecationWarning( int i )
{
Com_Printf( "^3WARNING: " S_COLOR_CVAR "%s^7 was replaced by " S_COLOR_CVAR "%s\n",
@@ -280,19 +299,15 @@ void Cvar_PrintDeprecationWarnings()
}
-static cvar_t* Cvar_Set2( const char *var_name, const char *value, qbool force )
+cvar_t* Cvar_Set2( const char *var_name, const char *value, int cvarSetFlags )
{
-// Com_DPrintf( "Cvar_Set2: %s %s\n", var_name, value );
+ const qbool force = (cvarSetFlags & CVARSET_BYPASSLATCH_BIT) != 0;
if ( !Cvar_ValidateString( var_name ) ) {
Com_Printf( "invalid cvar name string: %s\n", var_name );
var_name = "BADNAME";
}
- if ( !Q_stricmp( var_name, "r_swapInterval" ) ) {
- force = qfalse;
- }
-
cvar_t* var = Cvar_FindVar(var_name);
if (!var) {
if ( !value )
@@ -446,7 +461,7 @@ cvar_t* Cvar_Get( const char *var_name, const char *var_value, int flags )
if ( var->latchedString ) {
char* s = var->latchedString;
var->latchedString = NULL; // otherwise cvar_set2 would free it
- Cvar_Set2( var_name, s, qtrue );
+ Cvar_Set2( var_name, s, CVARSET_BYPASSLATCH_BIT );
Z_Free( s );
}
@@ -469,7 +484,7 @@ myT: we don't care about other mods and keeping it broken is not acceptable at a
*/
// CVAR_ROM always overrides
if (flags & CVAR_ROM) {
- Cvar_Set2( var_name, var_value, qtrue );
+ Cvar_Set2( var_name, var_value, CVARSET_BYPASSLATCH_BIT );
}
return var;
@@ -615,6 +630,93 @@ void Cvar_SetRange( const char *var_name, cvarType_t type, const char *minStr, c
}
+void Cvar_SetDataType( const char* cvarName, cvarType_t type )
+{
+ cvar_t* const cvar = Cvar_FindVar( cvarName );
+ if ( cvar == NULL )
+ return;
+
+#if defined(_DEBUG)
+ if ( cvar->type == CVART_STRING ) {
+ Q_assert(
+ type == CVART_STRING ||
+ type == CVART_COLOR_CPMA ||
+ type == CVART_COLOR_CHBLS ||
+ type == CVART_COLOR_RGB ||
+ type == CVART_COLOR_RGBA );
+ } else {
+ Q_assert( type == cvar->type );
+ }
+#endif
+ cvar->type = type;
+}
+
+
+void Cvar_SetMenuData( const char* cvarName, int categories, const char* title, const char* desc, const char* help, const char* values )
+{
+ cvar_t* const cvar = Cvar_FindVar( cvarName );
+ if ( cvar == NULL )
+ return;
+
+ cvarGui_t* const gui = &cvar->gui;
+ gui->categories = categories;
+ gui->title = title != NULL ? CopyString( title ) : NULL;
+ gui->desc = desc != NULL ? CopyString( desc ) : NULL;
+ gui->help = help != NULL ? CopyString( help ) : NULL;
+
+ if ( values == NULL )
+ return;
+
+ const char* const allStrings = values;
+ const char* string = NULL;
+ int maxLength = 0;
+ int numValues = 0;
+
+ string = allStrings;
+ for ( ; string[0] != '\0'; numValues++ ) {
+ int length = strlen( string );
+ maxLength = max( maxLength, length );
+ string += length + 1;
+ length = strlen( string );
+ string += length + 1;
+ length = strlen( string );
+ string += length + 1;
+ }
+
+#if defined(_DEBUG)
+ // make sure we have 1 set of strings for each possible value
+ if ( cvar->type == CVART_INTEGER ) {
+ Q_assert( numValues == cvar->validator.i.max - cvar->validator.i.min + 1 );
+ } else if ( cvar->type == CVART_BITMASK ) {
+ int numBits = 0;
+ int test = cvar->validator.i.max + 1;
+ while ( test >>= 1 ) {
+ numBits++;
+ }
+ Q_assert( numValues == numBits );
+ }
+#endif
+
+ gui->maxValueLength = maxLength;
+ gui->numValues = numValues;
+ gui->values = (cvarGuiValue_t*)S_Malloc( numValues * (int)sizeof( cvarGuiValue_t ) );
+
+ string = allStrings;
+ for ( int i = 0; string[0] != '\0'; i++ ) {
+ int length = strlen( string );
+ gui->values[i].valueLength = length;
+ gui->values[i].value = CopyString( string );
+ string += length + 1;
+ length = strlen( string );
+ gui->values[i].title = CopyString( string );
+ string += length + 1;
+ length = strlen( string );
+ gui->values[i].desc = CopyString( string );
+ string += length + 1;
+ }
+}
+
+
void Cvar_RegisterTable( const cvarTableItem_t* cvars, int count, module_t module )
{
for ( int i = 0; i < count; ++i ) {
@@ -630,10 +732,11 @@ void Cvar_RegisterTable( const cvarTableItem_t* cvars, int count, module_t modul
if ( item->min ||
item->max ||
- item->type == CVART_BITMASK ||
- item->type == CVART_BOOL )
+ item->type != CVART_STRING )
Cvar_SetRange( item->name, item->type, item->min, item->max );
+ Cvar_SetMenuData( item->name, item->categories, item->guiName, item->guiDesc, item->guiHelp, item->guiValues );
+
Cvar_SetModule( item->name, module );
}
}
@@ -720,6 +823,14 @@ void Cvar_PrintTypeAndRange( const char *var_name, printf_t print )
const char* max = maxV == INT_MAX ? "+inf" : va( "%d", maxV );
print( S_COLOR_VAL "%s ^7to " S_COLOR_VAL "%s", min, max );
}
+ } else if ( var->type == CVART_COLOR_RGB ) {
+ print( "RGB" );
+ } else if ( var->type == CVART_COLOR_RGBA ) {
+ print( "RGBA" );
+ } else if ( var->type == CVART_COLOR_CPMA ) {
+ print( "color_code" );
+ } else if ( var->type == CVART_COLOR_CHBLS ) {
+ print( "color_CHBLS" );
} else {
print( "string" );
}
@@ -789,7 +900,7 @@ void Cvar_PrintFlags( const char *var_name, printf_t print )
void Cvar_Set( const char *var_name, const char *value )
{
- Cvar_Set2( var_name, value, qtrue );
+ Cvar_Set2( var_name, value, CVARSET_BYPASSLATCH_BIT );
}
@@ -805,7 +916,7 @@ void Cvar_SetValue( const char *var_name, float value )
void Cvar_Reset( const char *var_name )
{
- Cvar_Set2( var_name, NULL, qfalse );
+ Cvar_Set2( var_name, NULL, 0 );
}
@@ -850,7 +961,7 @@ qbool Cvar_Command()
}
// set the value if forcing isn't required
- Cvar_Set2( v->name, Cmd_Args(), qfalse );
+ Cvar_Set2( v->name, Cmd_Args(), 0 );
return qtrue;
}
@@ -879,7 +990,7 @@ static void Cvar_Toggle_f( void )
if ( argc == 2 ) {
const int v = !Cvar_VariableIntegerValue( name );
- Cvar_Set2( name, va("%i", v), qfalse );
+ Cvar_Set2( name, va("%i", v), 0 );
return;
}
@@ -897,7 +1008,7 @@ static void Cvar_Toggle_f( void )
if ( index < 0 )
index = 0;
- Cvar_Set2( name, Cmd_Argv(index + valueOffset), qfalse );
+ Cvar_Set2( name, Cmd_Argv(index + valueOffset), 0 );
}
@@ -1084,7 +1195,7 @@ static void Cvar_Set_f( void )
l += len;
}
- Cvar_Set2( Cmd_Argv(1), combined, qfalse );
+ Cvar_Set2( Cmd_Argv(1), combined, 0 );
}
@@ -1371,3 +1482,9 @@ void Cvar_Init()
Cmd_RegisterArray( cl_cmds, MODULE_COMMON );
}
+
+
+cvar_t* Cvar_GetFirst()
+{
+ return cvar_vars;
+}
diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h
index 9f4e92b..558e9be 100644
--- a/code/qcommon/q_shared.h
+++ b/code/qcommon/q_shared.h
@@ -672,13 +672,35 @@ default values.
#define MAX_CVAR_VALUE_STRING 256
+#define CVAR_GUI_VALUE( Value, Title, Desc ) Value "\0" Title "\0" Desc "\0"
+
+// CVar categories
+#define CVARCAT_GENERAL 1
+#define CVARCAT_GAMEPLAY 2
+#define CVARCAT_NETWORK 4
+#define CVARCAT_DISPLAY 8
+#define CVARCAT_GRAPHICS 16
+#define CVARCAT_SOUND 32
+#define CVARCAT_CONSOLE 64
+#define CVARCAT_HUD 128
+#define CVARCAT_GUI 256
+#define CVARCAT_PERFORMANCE 512
+#define CVARCAT_DEBUGGING 1024
+#define CVARCAT_INPUT 2048
+#define CVARCAT_DEMO 4096
+
typedef enum {
- CVART_STRING, // no validation
- CVART_FLOAT, // uses floating-point min/max bounds
- CVART_INTEGER, // uses integer min/max bounds
- CVART_BITMASK, // uses integer min/max bounds
- CVART_BOOL, // uses integer min/max bounds, min=0 and max=1
- CVART_COUNT // always last in the enum
+ CVART_STRING, // no validation
+ CVART_FLOAT, // uses floating-point min/max bounds
+ CVART_INTEGER, // uses integer min/max bounds
+ CVART_BITMASK, // uses integer min/max bounds
+ CVART_BOOL, // uses integer min/max bounds, min=0 and max=1
+ // extended data types (not currently used by the CPMA QVMs)
+ CVART_COLOR_CPMA, // CPMA color code (0-9 A-Z a-z)
+ CVART_COLOR_CHBLS, // CPMA color codes: rail Core, Head, Body, Legs, rail Spiral
+ CVART_COLOR_RGB, // as hex, e.g. FF00FF
+ CVART_COLOR_RGBA, // as hex, e.g. FF00FF00
+ CVART_COUNT // always last in the enum
} cvarType_t;
typedef int cvarHandle_t;
diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h
index 82e6489..48439ca 100644
--- a/code/qcommon/qcommon.h
+++ b/code/qcommon/qcommon.h
@@ -469,6 +469,23 @@ typedef union {
floatValidator_s f;
} cvarValidator_t;
+struct cvarGuiValue_t {
+ const char* value;
+ const char* title;
+ const char* desc;
+ int valueLength;
+};
+
+struct cvarGui_t {
+ const char* title;
+ const char* desc;
+ const char* help;
+ cvarGuiValue_t* values;
+ int categories;
+ int numValues;
+ int maxValueLength;
+};
+
// nothing outside the Cvar_*() functions should modify these fields!
typedef struct cvar_s {
char *name;
@@ -487,6 +504,7 @@ typedef struct cvar_s {
int integer; // atoi( string )
qbool mismatchPrinted; // have we already notified of mismatching initial values?
cvarValidator_t validator;
+ cvarGui_t gui;
struct cvar_s *next;
struct cvar_s *hashNext;
} cvar_t;
@@ -500,8 +518,15 @@ typedef struct cvarTableItem_s {
const char* min;
const char* max;
const char* help;
+ const char* guiName;
+ int categories;
+ const char* guiDesc;
+ const char* guiHelp;
+ const char* guiValues;
} cvarTableItem_t;
+#define CVARSET_BYPASSLATCH_BIT 1
+
typedef void ( QDECL *printf_t )( PRINTF_FORMAT_STRING const char* fmt, ... );
cvar_t *Cvar_Get( const char *var_name, const char *value, int flags );
@@ -519,6 +544,9 @@ qbool Cvar_GetHelp( const char **desc, const char **help, const char* var_name )
void Cvar_SetRange( const char *var_name, cvarType_t type, const char *min, const char *max );
+void Cvar_SetDataType( const char* cvarName, cvarType_t type );
+void Cvar_SetMenuData( const char* cvarName, int categories, const char* title, const char* desc, const char* help, const char* values );
+
void Cvar_RegisterTable( const cvarTableItem_t* cvars, int count, module_t module );
#define Cvar_RegisterArray(a, m) Cvar_RegisterTable( a, ARRAY_LEN(a), m )
@@ -540,6 +568,9 @@ void Cvar_Update( vmCvar_t *vmCvar );
void Cvar_Set( const char *var_name, const char *value );
// will create the variable with no flags if it doesn't exist
+cvar_t* Cvar_Set2( const char *var_name, const char *value, int cvarSetFlags );
+// will create the variable with no flags if it doesn't exist
+
void Cvar_SetValue( const char *var_name, float value );
// expands value to a string and calls Cvar_Set
@@ -582,6 +613,8 @@ const char* Cvar_InfoString_Big( int bit );
// in their flags ( CVAR_USERINFO, CVAR_SERVERINFO, CVAR_SYSTEMINFO, etc )
void Cvar_InfoStringBuffer( int bit, char *buff, int buffsize );
+cvar_t* Cvar_GetFirst();
+
extern int cvar_modifiedFlags;
// whenever a cvar is modifed, its flags will be OR'd into this, so
// a single check can determine if any CVAR_USERINFO, CVAR_SERVERINFO,
@@ -876,6 +909,8 @@ void Com_StartupVariable( const char *match );
// if match is NULL, all set commands will be executed, otherwise
// only a set with the exact name. Only used during startup.
+void Com_ParseHexColor( float* color, const char* text, qbool hasAlpha );
+
extern cvar_t *com_developer;
extern cvar_t *com_dedicated;
@@ -1046,6 +1081,9 @@ void CL_DisableFramerateLimiter();
// which would leave the FPS limit enabled until the next successful map load
// this should therefore always be called by Com_Error
+void CL_SetMenuData( qboolean typeOnly );
+// sets GUI data for CVars registered by ui.qvm and cgame.qvm
+
void Key_KeyNameCompletion( void (*callback)(const char *s) );
// for /bind and /unbind auto-completion
diff --git a/code/renderer/rhi_d3d12.cpp b/code/renderer/rhi_d3d12.cpp
index 093020c..967e0f3 100644
--- a/code/renderer/rhi_d3d12.cpp
+++ b/code/renderer/rhi_d3d12.cpp
@@ -27,21 +27,8 @@ to do:
- use ID3D12DebugCommandList::AssertResourceState
- git cherry-pick 693415a6e2f2f3789215ec037b15d505c5132fd4
- git cherry-pick c75b2b27fa936854d27dadf458e3ec3b03829561
-- Intel 12th gen handling
- https://www.intel.com/content/www/us/en/developer/articles/guide/12th-gen-intel-core-processor-gamedev-guide.html
- https://github.com/GameTechDev/HybridDetect
- - use GetSystemCpuSetInformation for info
- - graph GetCurrentProcessorNumber to see where we're executing
- - use SetThreadSelectedCpuSets
- https://asawicki.info/news_1758_an_idea_for_visualization_of_frame_times
- GPU resident vertex data for models: load on demand based on submitted { surface, shader } pairs
-- tool: live shader override editing
-- tool: shader trace with the pointed pixel being traced
- render opaque to shader ID render target
- render transparent to fragment buffer but only output for traced pixel
- index texture not needed
- only output depth and shader ID
- run compute shader to load shader ID linked list into an array, sort it and write it out
- reloading a map can lead to a TDR timeout
could it be related to the copy queue?
use PIX to capture and replay the bad command list?
@@ -58,8 +45,6 @@ to do:
draw opaques, locate the light stage and add the light buffer data to the light stage result
- r_depthFade
- r_dynamiclight
-- CMAA 2 integration?
-- SMAA S2x support?
- when creating the root signature, validate that neither of the tables have any gap
- use root signature 1.1 to use the hints that help the drivers optimize out static resources
- is it possible to force Resource Binding Tier 2 somehow? are we supposed to run on old HW to test? :(
@@ -73,31 +58,7 @@ to do:
- share structs between HLSL and C++ with .hlsli files -> change cbuffer to ConstantBuffer
- share texture and sampler array sizes between HLSL and C++ with .hlsli files
- what's the actual fog curve used by Q3?
-- depth pre-pass: world entities can reference world surfaces
- -> must ignore or figure out which surfaces are referenced by entities...
- roq video textures support?
-X CG_INIT sets r_swapinterval to speed up the load, but it doesn't work anymore
- -> just as fast, still fixes the issue for older clients
-X committed resources: depth buffer, render targets, static geometry - optional: large textures
-X figure out brightness/gamma differences between D3D12 & D3D11
- -> UI uses CGEN_VERTEX / AGEN_VERTEX
- -> tr.identityLight usage is missing
-
-rejected:
-- NvAPI_D3D_GetLatency to get (simulated) input to display latency
- -> nope, it doesn't say when the frame gets displayed or even queued for display
-- NvAPI_D3D_IsGSyncCapable / NvAPI_D3D_IsGSyncActive for diagnostics
- -> nope, that's for D3D9-11
-- textures on cache-coherent UMA:
- 1. create with undefined layout and CPU access (custom heap)
- 2. upload data in 1 step with WriteToSubresource
- -> nope, render times are worse (map loads were faster, but the render time hit was not small)
-- simplify by using the direct queue for everything
- -> it makes almost no difference to either the code or map load performance
-- IDXGISwapChain::SetFullScreenState(TRUE) with the borderless window taking up the entire screen
- and ALLOW_TEARING set on both the flip mode swap chain and Present() flags
- will enable true immediate independent flip mode and give us the lowest latency possible
- -> not using SetFullScreenState is perfectly fine
*/
/*
@@ -1312,7 +1273,7 @@ namespace RHI
{
UINT flags;
UINT swapInterval;
- if(r_swapInterval->integer)
+ if(r_vsync->integer)
{
swapInterval = 1;
flags = 0;
@@ -1363,7 +1324,7 @@ namespace RHI
else if(presentError == PE_DEVICE_RESET)
{
ri.Printf(PRINT_ERROR, "Direct3D device was reset! Restarting the video system...");
- Cmd_ExecuteString("vid_restart;");
+ Cbuf_AddText("vid_restart\n");
}
}
@@ -1843,7 +1804,7 @@ namespace RHI
const Buffer& buffer = rhi.buffers.Get(hbuffer);
#if defined(D3D_DEBUG)
- if(r_swapInterval->integer)
+ if(r_vsync->integer)
{
Q_assert(rhi.frameIndex == 0);
Q_assert(frameIndex == 0);
@@ -1936,7 +1897,7 @@ namespace RHI
rhie.monitorFrameDurationMS = 0.0f;
}
- if(r_swapInterval->integer == 0)
+ if(r_vsync->integer == 0)
{
const float maxFPS = ri.Cvar_Get("com_maxfps", "125", CVAR_ARCHIVE)->value;
rhie.targetFrameDurationMS = 1000.0f / maxFPS;
@@ -2039,7 +2000,7 @@ namespace RHI
static UINT GetSwapChainFlags()
{
UINT flags = 0;
- if(r_swapInterval->integer)
+ if(r_vsync->integer)
{
flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
}
@@ -2067,7 +2028,7 @@ namespace RHI
{
if(rhi.frameLatencyWaitableObject != NULL && rhi.frameLatencyWaitNeeded)
{
- Q_assert(r_swapInterval->integer != 0);
+ Q_assert(r_vsync->integer != 0);
WaitForSingleObjectEx(rhi.frameLatencyWaitableObject, INFINITE, TRUE);
rhi.frameLatencyWaitNeeded = false;
}
@@ -2167,8 +2128,8 @@ namespace RHI
const char* version = "Unknown";
switch(root0.HighestVersion)
{
- case D3D_ROOT_SIGNATURE_VERSION_1_0: version = "1.0";
- case D3D_ROOT_SIGNATURE_VERSION_1_1: version = "1.1";
+ case D3D_ROOT_SIGNATURE_VERSION_1_0: version = "1.0"; break;
+ case D3D_ROOT_SIGNATURE_VERSION_1_1: version = "1.1"; break;
default: break;
}
TableRow(2, "Root signature version", version);
@@ -2180,9 +2141,9 @@ namespace RHI
const char* tier = "Unknown";
switch(options5.RenderPassesTier)
{
- case D3D12_RENDER_PASS_TIER_0: tier = "0";
- case D3D12_RENDER_PASS_TIER_1: tier = "1";
- case D3D12_RENDER_PASS_TIER_2: tier = "2";
+ case D3D12_RENDER_PASS_TIER_0: tier = "0"; break;
+ case D3D12_RENDER_PASS_TIER_1: tier = "1"; break;
+ case D3D12_RENDER_PASS_TIER_2: tier = "2"; break;
default: break;
}
TableRow(2, "Render passes tier", tier);
@@ -2190,9 +2151,9 @@ namespace RHI
tier = "Unknown";
switch(options5.RaytracingTier)
{
- case D3D12_RAYTRACING_TIER_NOT_SUPPORTED: tier = "Not supported";
- case D3D12_RAYTRACING_TIER_1_0: tier = "1.0";
- case D3D12_RAYTRACING_TIER_1_1: tier = "1.1";
+ case D3D12_RAYTRACING_TIER_NOT_SUPPORTED: tier = "Not supported"; break;
+ case D3D12_RAYTRACING_TIER_1_0: tier = "1.0"; break;
+ case D3D12_RAYTRACING_TIER_1_1: tier = "1.1"; break;
default: break;
}
TableRow(2, "Raytracing (DXR) tier", tier);
@@ -2204,12 +2165,12 @@ namespace RHI
const char* tier = "Unknown";
switch(options6.VariableShadingRateTier)
{
- case D3D12_VARIABLE_SHADING_RATE_TIER_NOT_SUPPORTED: tier = "N/A";
- case D3D12_VARIABLE_SHADING_RATE_TIER_1: tier = "1";
- case D3D12_VARIABLE_SHADING_RATE_TIER_2: tier = "2";
+ case D3D12_VARIABLE_SHADING_RATE_TIER_NOT_SUPPORTED: tier = "N/A"; break;
+ case D3D12_VARIABLE_SHADING_RATE_TIER_1: tier = "1"; break;
+ case D3D12_VARIABLE_SHADING_RATE_TIER_2: tier = "2"; break;
default: break;
}
- TableRow(2, "Variable shading rate (VRS) tier", tier);
+ TableRow(2, "Variable-rate shading (VRS) tier", tier);
TableRow(2, "VRS: 2x4, 4x2, 4x4 support", options6.AdditionalShadingRatesSupported ? "YES" : "NO");
}
@@ -2340,7 +2301,7 @@ namespace RHI
// V-Sync toggles require changing the swap chain flags,
// which means ResizeBuffers can't be used
- const bool vsync = r_swapInterval->integer != 0;
+ const bool vsync = r_vsync->integer != 0;
rhi.renderFrameCount = vsync ? 1 : 2;
if(glInfo.winWidth != desc.BufferDesc.Width ||
@@ -2601,7 +2562,7 @@ namespace RHI
rhi.isTearingSupported = IsTearingSupported();
rhi.swapChainBufferCount = 2;
- rhi.renderFrameCount = r_swapInterval->integer ? 1 : 2;
+ rhi.renderFrameCount = r_vsync->integer ? 1 : 2;
{
const UINT flags = GetSwapChainFlags();
@@ -2624,13 +2585,13 @@ namespace RHI
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.Windowed = TRUE;
D3D(rhi.factory->CreateSwapChain(rhi.mainCommandQueue, &swapChainDesc, &dxgiSwapChain));
- rhi.vsync = r_swapInterval->integer != 0;
+ rhi.vsync = r_vsync->integer != 0;
D3D(dxgiSwapChain->QueryInterface(IID_PPV_ARGS(&rhi.swapChain)));
rhi.swapChainBufferIndex = rhi.swapChain->GetCurrentBackBufferIndex();
COM_RELEASE(dxgiSwapChain);
- if(r_swapInterval->integer)
+ if(r_vsync->integer)
{
rhi.frameLatencyWaitableObject = rhi.swapChain->GetFrameLatencyWaitableObject();
rhi.frameLatencyWaitNeeded = true;
diff --git a/code/renderer/tr_cmds.cpp b/code/renderer/tr_cmds.cpp
index ba300f3..7b62cb5 100644
--- a/code/renderer/tr_cmds.cpp
+++ b/code/renderer/tr_cmds.cpp
@@ -325,7 +325,7 @@ void RE_BeginFrame( stereoFrame_t stereoFrame )
}
-void RE_EndFrame( int* pcFE, int* pc2D, int* pc3D, qbool render )
+void RE_EndFrame( qbool render )
{
if (!tr.registered)
return;
@@ -349,7 +349,6 @@ void RE_EndFrame( int* pcFE, int* pc2D, int* pc3D, qbool render )
}
}
- // @TODO:
backEnd.renderFrame = render;
End2D( qtrue );
@@ -369,15 +368,6 @@ void RE_EndFrame( int* pcFE, int* pc2D, int* pc3D, qbool render )
R_ClearFrame();
- if (pcFE)
- Com_Memcpy( pcFE, &tr.pc, sizeof( tr.pc ) );
-
- if (pc2D)
- Com_Memcpy( pc2D, &backEnd.pc2D, sizeof( backEnd.pc2D ) );
-
- if (pc3D)
- Com_Memcpy( pc3D, &backEnd.pc3D, sizeof( backEnd.pc3D ) );
-
Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
Com_Memset( &backEnd.pc2D, 0, sizeof( backEnd.pc2D ) );
Com_Memset( &backEnd.pc3D, 0, sizeof( backEnd.pc3D ) );
diff --git a/code/renderer/tr_gui.cpp b/code/renderer/tr_gui.cpp
index bbd023c..3da9258 100644
--- a/code/renderer/tr_gui.cpp
+++ b/code/renderer/tr_gui.cpp
@@ -81,6 +81,7 @@ static ShaderWindow shaderWindow;
static ShaderReplacements shaderReplacements;
static ImageReplacements imageReplacements;
static ShaderEditWindow shaderEditWindow;
+static char cvarFilter[256];
static const char* mipNames[16] =
{
@@ -118,6 +119,47 @@ static const ImageFlag imageFlags[] =
{ IMG_NOAF, "no AF" }
};
+// RGB triplets for ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
+static const float cpmaColorCodes[] =
+{
+ 1.000000f, 0.000000f, 0.000000f,
+ 1.000000f, 0.267949f, 0.000000f,
+ 1.000000f, 0.500000f, 0.000000f,
+ 1.000000f, 0.732051f, 0.000000f,
+ 1.000000f, 1.000000f, 0.000000f,
+ 0.732051f, 1.000000f, 0.000000f,
+ 0.500000f, 1.000000f, 0.000000f,
+ 0.267949f, 1.000000f, 0.000000f,
+ 0.000000f, 1.000000f, 0.000000f,
+ 0.000000f, 1.000000f, 0.267949f,
+ 0.000000f, 1.000000f, 0.500000f,
+ 0.000000f, 1.000000f, 0.732051f,
+ 0.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.732051f, 1.000000f,
+ 0.000000f, 0.500000f, 1.000000f,
+ 0.000000f, 0.267949f, 1.000000f,
+ 0.000000f, 0.000000f, 1.000000f,
+ 0.267949f, 0.000000f, 1.000000f,
+ 0.500000f, 0.000000f, 1.000000f,
+ 0.732051f, 0.000000f, 1.000000f,
+ 1.000000f, 0.000000f, 1.000000f,
+ 1.000000f, 0.000000f, 0.732051f,
+ 1.000000f, 0.000000f, 0.500000f,
+ 1.000000f, 0.000000f, 0.267949f,
+ 0.250000f, 0.250000f, 0.250000f,
+ 0.500000f, 0.500000f, 0.500000f,
+ 0.000000f, 0.000000f, 0.000000f,
+ 1.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 1.000000f, 0.000000f,
+ 1.000000f, 1.000000f, 0.000000f,
+ 0.200000f, 0.200000f, 1.000000f,
+ 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 0.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f,
+ 0.750000f, 0.750000f, 0.750000f,
+ 0.600000f, 0.600000f, 1.000000f
+};
+
#if 0
static void SelectableText(const char* text)
@@ -133,6 +175,136 @@ static void SelectableText(const char* text)
}
#endif
+static bool IsNullOrEmpty(const char* string)
+{
+ return string == NULL || string[0] == '\0';
+}
+
+static bool IsNonEmpty(const char* string)
+{
+ return string != NULL && string[0] != '\0';
+}
+
+static void SetTooltipIfValid(const char* text)
+{
+ if(IsNonEmpty(text) && ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal))
+ {
+ ImGui::SetTooltip(text);
+ }
+}
+
+static ImVec4 GetColorFromCPMACode(char colorCode)
+{
+ int colorIndex = 0;
+ if(colorCode >= 'A' && colorCode <= 'Z')
+ {
+ colorIndex = colorCode - 'A';
+ }
+ else if(colorCode >= 'a' && colorCode <= 'z')
+ {
+ colorIndex = colorCode - 'a';
+ }
+ else if(colorCode >= '0' && colorCode <= '9')
+ {
+ colorIndex = 26 + (colorCode - '0');
+ }
+
+ const float* colorPointer = cpmaColorCodes + colorIndex * 3;
+ const ImVec4 color(colorPointer[0], colorPointer[1], colorPointer[2], 1.0f);
+
+ return color;
+}
+
+static float InverseToneMap(float x)
+{
+ return powf(x / r_brightness->value, r_gamma->value);
+}
+
+static bool CPMAColorCodeButton(const char* title, const char* id, char& currentColor)
+{
+ const char* const popupId = va("##color_popup_%s", id);
+ const ImGuiColorEditFlags previewFlags = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_NoAlpha;
+ bool clicked = false;
+
+ ImGui::Text(va("%c", currentColor));
+ ImGui::SameLine();
+
+ if(ImGui::ColorButton(va("##%s", id), GetColorFromCPMACode(currentColor), previewFlags))
+ {
+ ImGui::OpenPopup(popupId);
+ }
+
+ if(ImGui::BeginPopup(popupId))
+ {
+ if(title != NULL && title[0] != '\0')
+ {
+ ImGui::Text(title);
+ }
+
+ const char* rows[] =
+ {
+ "ABCDEF",
+ "GHIJKL",
+ "MNOPQR",
+ "STUVWX",
+ "YZ0123",
+ "456789"
+ };
+ for(int y = 0; y < ARRAY_LEN(rows); ++y)
+ {
+ const char* row = rows[y];
+ for(int x = 0; row[x] != '\0'; ++x)
+ {
+ if(x > 0)
+ {
+ ImGui::SameLine();
+ }
+
+ const char colorCode = row[x];
+ const ImGuiColorEditFlags buttonFlags = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_NoAlpha;
+ ImVec4 color = GetColorFromCPMACode(colorCode);
+ color.x = InverseToneMap(color.x);
+ color.y = InverseToneMap(color.y);
+ color.z = InverseToneMap(color.z);
+ if(ImGui::ColorButton(va("%c", colorCode), color, buttonFlags))
+ {
+ currentColor = colorCode;
+ clicked = true;
+ }
+ }
+ }
+
+ ImGui::EndPopup();
+ }
+
+ return clicked;
+}
+
+static const char* RemoveColorCodes(const char* text)
+{
+ static char buffer[1024];
+ Q_strncpyz(buffer, text, sizeof(buffer));
+
+ char* d = buffer;
+ char* s = buffer;
+ int c;
+ while((c = *s) != 0)
+ {
+ if(Q_IsColorString(s))
+ {
+ s++;
+ }
+ else
+ {
+ *d++ = c;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return buffer;
+}
+
static void FormatShaderCode(char* dest, int destSize, const shader_t* shader)
{
#define Append(Text) Q_strcat(dest, destSize, Text)
@@ -424,14 +596,17 @@ static void DrawImageList()
ClearImageReplacements();
}
- static char filter[256];
- DrawFilter(filter, sizeof(filter));
+ static char rawFilter[256];
+ DrawFilter(rawFilter, sizeof(rawFilter));
if(BeginTable("Images", 1))
{
for(int i = 0; i < tr.numImages; ++i)
{
const image_t* image = tr.images[i];
+
+ char filter[256];
+ Com_sprintf(filter, sizeof(filter), rawFilter[0] == '*' ? "%s" : "*%s", rawFilter);
if(filter[0] != '\0' && !Com_Filter(filter, image->name))
{
continue;
@@ -598,14 +773,17 @@ static void DrawShaderList()
}
}
- static char filter[256];
- DrawFilter(filter, sizeof(filter));
+ static char rawFilter[256];
+ DrawFilter(rawFilter, sizeof(rawFilter));
if(BeginTable("Shaders", 1))
{
for(int s = 0; s < tr.numShaders; ++s)
{
shader_t* shader = tr.shaders[s];
+
+ char filter[256];
+ Com_sprintf(filter, sizeof(filter), rawFilter[0] == '*' ? "%s" : "*%s", rawFilter);
if(filter[0] != '\0' && !Com_Filter(filter, shader->name))
{
continue;
@@ -845,6 +1023,817 @@ static void DrawShaderEdit()
}
}
+static void DrawFrontEndStats()
+{
+ static bool active = false;
+ GUI_AddMainMenuItem(GUI_MainMenu::Perf, "Front-end stats", "", &active);
+ if(active)
+ {
+ if(ImGui::Begin("Front-end stats", &active, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ if(BeginTable("General stats", 2))
+ {
+ struct Item
+ {
+ int index;
+ const char* title;
+ };
+ const Item items[] =
+ {
+ { RF_LEAF_CLUSTER, "PVS cluster" },
+ { RF_LEAF_AREA, "PVS area" },
+ { RF_LEAFS, "Leaves" },
+ { RF_LIT_LEAFS, "Lit leaves" },
+ { RF_LIT_SURFS, "Lit surfaces" },
+ { RF_LIT_CULLS, "Lit surfaces culled" },
+ { RF_LIGHT_CULL_IN, "Lights kept" },
+ { RF_LIGHT_CULL_OUT, "Lights rejected" }
+ };
+
+ for(int i = 0; i < ARRAY_LEN(items); ++i)
+ {
+ const Item& item = items[i];
+ TableRow(2, item.title, va("%d", tr.pc[item.index]));
+ }
+
+ ImGui::EndTable();
+ }
+
+ if(BeginTable("Culling stats", 4))
+ {
+ struct Item
+ {
+ int indexIn;
+ int indexClip;
+ int indexOut;
+ const char* title;
+ };
+ const Item items[] =
+ {
+ { RF_MD3_CULL_S_IN, RF_MD3_CULL_S_CLIP, RF_MD3_CULL_S_OUT, "MD3 vs sphere" },
+ { RF_MD3_CULL_B_IN, RF_MD3_CULL_B_CLIP, RF_MD3_CULL_B_OUT, "MD3 vs box" },
+ { RF_BEZ_CULL_S_IN, RF_BEZ_CULL_S_CLIP, RF_BEZ_CULL_S_OUT, "Grid vs sphere" },
+ { RF_BEZ_CULL_B_IN, RF_BEZ_CULL_B_CLIP, RF_BEZ_CULL_B_OUT, "Grid vs box" }
+ };
+
+ ImGui::TableSetupColumn("Surface");
+ ImGui::TableSetupColumn("In", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFont()->FontSize * 4.0f);
+ ImGui::TableSetupColumn("Clip", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFont()->FontSize * 4.0f);
+ ImGui::TableSetupColumn("Out", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFont()->FontSize * 4.0f);
+ ImGui::TableHeadersRow();
+ for(int i = 0; i < ARRAY_LEN(items); ++i)
+ {
+ const Item& item = items[i];
+ TableRow(4, item.title,
+ va("%d", tr.pc[item.indexIn]),
+ va("%d", tr.pc[item.indexClip]),
+ va("%d", tr.pc[item.indexOut]));
+ }
+
+ ImGui::EndTable();
+ }
+ }
+
+ ImGui::End();
+ }
+}
+
+static ImVec4 ParseHexRGB(const char* text)
+{
+ float c[4];
+ Com_ParseHexColor(c, text, qfalse);
+
+ return ImVec4(c[0], c[1], c[2], 1.0f);
+}
+
+static ImVec4 ParseHexRGBA(const char* text)
+{
+ float c[4];
+ Com_ParseHexColor(c, text, qtrue);
+
+ return ImVec4(c[0], c[1], c[2], c[3]);
+}
+
+static float GetVerticalFov(float hfov)
+{
+ const float w = 1.0f;
+ const float h = (float)glConfig.vidHeight / (float)glConfig.vidWidth;
+ const float adj = w / tanf(DEG2RAD(0.5f * hfov));
+ const float vfov = 2.0f * RAD2DEG(atanf(h / adj));
+
+ return vfov;
+}
+
+static float GetHorizontalFov(float vfov)
+{
+ const float w = 1.0f;
+ const float h = (float)glConfig.vidHeight / (float)glConfig.vidWidth;
+ const float adj = h / tanf(DEG2RAD(0.5f * vfov));
+ const float hfov = 2.0f * RAD2DEG(atanf(w / adj));
+
+ return hfov;
+}
+
+static void DrawCVarValue(cvar_t* cvar)
+{
+ if(cvar->flags & (CVAR_ROM | CVAR_INIT))
+ {
+ ImGui::Text(cvar->string);
+ return;
+ }
+
+ if(cvar->type == CVART_COLOR_RGB)
+ {
+ const char* const id = cvar->name;
+ const char* const oldValue = cvar->latchedString != NULL ? cvar->latchedString : cvar->string;
+ const ImVec4 color = ParseHexRGB(oldValue);
+ const ImGuiColorEditFlags flags =
+ ImGuiColorEditFlags_NoLabel |
+ ImGuiColorEditFlags_NoInputs |
+ ImGuiColorEditFlags_InputRGB |
+ ImGuiColorEditFlags_NoAlpha |
+ ImGuiColorEditFlags_PickerHueWheel;
+ float outColor[4] = { color.x, color.y, color.z, 1.0f };
+
+ if(ImGui::ColorEdit3(va("%s##picker_%s", cvar->gui.title, id), outColor, flags))
+ {
+ const unsigned int r = outColor[0] * 255.0f;
+ const unsigned int g = outColor[1] * 255.0f;
+ const unsigned int b = outColor[2] * 255.0f;
+ Cvar_Set2(cvar->name, va("%02X%02X%02X", r, g, b), 0);
+ }
+ }
+ else if(cvar->type == CVART_COLOR_RGBA)
+ {
+ const char* const id = cvar->name;
+ const char* const oldValue = cvar->latchedString != NULL ? cvar->latchedString : cvar->string;
+ const ImVec4 color = ParseHexRGBA(oldValue);
+ const ImGuiColorEditFlags flags =
+ ImGuiColorEditFlags_NoLabel |
+ ImGuiColorEditFlags_NoInputs |
+ ImGuiColorEditFlags_InputRGB |
+ ImGuiColorEditFlags_AlphaPreview |
+ ImGuiColorEditFlags_AlphaBar |
+ ImGuiColorEditFlags_PickerHueWheel;
+ float outColor[4] = { color.x, color.y, color.z, color.w };
+
+ if(ImGui::ColorEdit4(va("%s##picker_%s", cvar->gui.title, id), outColor, flags))
+ {
+ const unsigned int r = outColor[0] * 255.0f;
+ const unsigned int g = outColor[1] * 255.0f;
+ const unsigned int b = outColor[2] * 255.0f;
+ const unsigned int a = outColor[3] * 255.0f;
+ Cvar_Set2(cvar->name, va("%02X%02X%02X%02X", r, g, b, a), 0);
+ }
+ }
+ else if(cvar->type == CVART_COLOR_CPMA || !Q_stricmp(cvar->name, "ch_eventOwnColor") || !Q_stricmp(cvar->name, "ch_eventEnemyColor"))
+ {
+ const char* const oldValue = cvar->latchedString != NULL ? cvar->latchedString : cvar->string;
+ char colorCode = oldValue[0];
+ if(CPMAColorCodeButton(NULL, cvar->name, colorCode))
+ {
+ Cvar_Set2(cvar->name, va("%c", colorCode), 0);
+ }
+ }
+ else if(cvar->type == CVART_COLOR_CHBLS || !Q_stricmp(cvar->name, "color"))
+ {
+ const char* titles[5] =
+ {
+ "Rail core",
+ "Head / helmet / visor",
+ "Body / shirt",
+ "Legs",
+ "Rail spiral"
+ };
+
+ const char* const oldValue = cvar->latchedString != NULL ? cvar->latchedString : cvar->string;
+ char colorCodes[6] = { '7', '7', '7', '7', '7', '\0' };
+ for(int i = 0; i < 5; ++i)
+ {
+ if(oldValue[i] == '\0')
+ {
+ break;
+ }
+ colorCodes[i] = (char)toupper(oldValue[i]);
+ }
+
+ bool clicked = false;
+ for(int i = 0; i < 5; ++i)
+ {
+ if(CPMAColorCodeButton(titles[i], va("%s_%d", cvar->name, i), colorCodes[i]))
+ {
+ clicked = true;
+ }
+ ImGui::SameLine();
+ ImGui::Text(titles[i]);
+ }
+ Cvar_Set2(cvar->name, colorCodes, 0);
+ }
+ else if(cvar->gui.numValues > 0 && cvar->type == CVART_BITMASK)
+ {
+ const int oldValue = cvar->latchedString != NULL ? atoi(cvar->latchedString) : cvar->integer;
+ for(int i = 0; i < cvar->gui.numValues; ++i)
+ {
+ cvarGuiValue_t* const value = &cvar->gui.values[i];
+ const int bitIndex = atoi(value->value);
+ const int bitMask = 1 << bitIndex;
+ bool bitValue = (oldValue & bitMask) != 0;
+ if(ImGui::Checkbox(value->title, &bitValue))
+ {
+ int newValue = oldValue;
+ if(bitValue)
+ {
+ newValue |= bitMask;
+ }
+ else
+ {
+ newValue &= ~bitMask;
+ }
+ Cvar_Set2(cvar->name, va("%d", newValue), 0);
+ }
+ SetTooltipIfValid(value->desc);
+ }
+ }
+ else if(cvar->gui.numValues == 2 && cvar->type == CVART_BOOL)
+ {
+ // keep the value order: the value for 1 can come before the value for 0
+ // this is on purpose because there are CVars phrased as a negative
+ const bool oldValue = cvar->latchedString ? (atoi(cvar->latchedString) != 0) : (cvar->integer != 0);
+ const cvarGuiValue_t* const values = cvar->gui.values;
+ const int i0 = atoi(values[0].value);
+ const int i1 = atoi(values[1].value);
+ const cvarGuiValue_t* const value0 = &values[0];
+ const cvarGuiValue_t* const value1 = &values[1];
+ int currValue = oldValue ? 1 : 0;
+
+ if(ImGui::RadioButton(value0->title, &currValue, i0))
+ {
+ Cvar_Set2(cvar->name, values[0].value, 0);
+ }
+ SetTooltipIfValid(value0->desc);
+
+ ImGui::SameLine();
+
+ if(ImGui::RadioButton(value1->title, &currValue, i1))
+ {
+ Cvar_Set2(cvar->name, values[1].value, 0);
+ }
+ SetTooltipIfValid(value1->desc);
+ }
+ else if(cvar->gui.numValues == 2 && cvar->type == CVART_INTEGER &&
+ cvar->validator.i.max == cvar->validator.i.min + 1)
+ {
+ const int oldValue = cvar->latchedString ? atoi(cvar->latchedString) : cvar->integer;
+ const cvarGuiValue_t* const values = cvar->gui.values;
+ const cvarGuiValue_t* const value0 = &values[0];
+ const cvarGuiValue_t* const value1 = &values[1];
+ const int i0 = atoi(value0->value);
+ const int i1 = atoi(value1->value);
+ int currValue = oldValue;
+
+ if(ImGui::RadioButton(value0->title, &currValue, i0))
+ {
+ Cvar_Set2(cvar->name, value0->value, 0);
+ }
+ SetTooltipIfValid(value0->desc);
+
+ ImGui::SameLine();
+
+ if(ImGui::RadioButton(value1->title, &currValue, i1))
+ {
+ Cvar_Set2(cvar->name, value1->value, 0);
+ }
+ SetTooltipIfValid(value1->desc);
+ }
+ else if(cvar->gui.numValues > 0)
+ {
+ const char* const oldValue = cvar->latchedString != NULL ? cvar->latchedString : cvar->string;
+ const char* previewString = NULL;
+ for(int i = 0; i < cvar->gui.numValues; ++i)
+ {
+ cvarGuiValue_t* const value = &cvar->gui.values[i];
+ if(strcmp(oldValue, value->value) == 0)
+ {
+ previewString = value->title;
+ break;
+ }
+ }
+ if(previewString == NULL)
+ {
+ previewString = oldValue;
+ }
+
+ ImGui::SetNextItemWidth(ImGui::GetIO().FontDefault->FontSize * 15.0f);
+ if(ImGui::BeginCombo(va("##%s", cvar->name), previewString, ImGuiComboFlags_None))
+ {
+ for(int i = 0; i < cvar->gui.numValues; ++i)
+ {
+ cvarGuiValue_t* const value = &cvar->gui.values[i];
+ bool selected = false;
+ if(ImGui::Selectable(value->title, &selected, ImGuiSelectableFlags_None))
+ {
+ Cvar_Set2(cvar->name, value->value, 0);
+ }
+ SetTooltipIfValid(value->desc);
+ }
+
+ ImGui::EndCombo();
+ }
+ }
+ else if(cvar->type == CVART_STRING)
+ {
+ if(!Q_stricmp(cvar->name, "mvw_DM") ||
+ !Q_stricmp(cvar->name, "mvw_TDM1") ||
+ !Q_stricmp(cvar->name, "mvw_TDM2") ||
+ !Q_stricmp(cvar->name, "mvw_TDM3") ||
+ !Q_stricmp(cvar->name, "mvw_TDM4"))
+ {
+ int v[4] = {};
+ const char* const oldValue = cvar->latchedString != NULL ? cvar->latchedString : cvar->string;
+ sscanf(oldValue, "%d %d %d %d", &v[0], &v[1], &v[2], &v[3]);
+ if(ImGui::SliderInt4(va("##%s", cvar->name), v, 0, 640, "%d", ImGuiSliderFlags_AlwaysClamp))
+ {
+ Cvar_Set2(cvar->name, va("%d %d %d %d", v[0], v[1], v[2], v[3]), 0);
+ }
+ }
+ else
+ {
+ static char text[256];
+ Q_strncpyz(text, cvar->string, sizeof(text));
+ if(ImGui::InputText(va("##%s", cvar->name), text, sizeof(text)))
+ {
+ Cvar_Set2(cvar->name, text, 0);
+ }
+ }
+ }
+ else if(cvar->type == CVART_BOOL)
+ {
+ const bool oldValue = cvar->latchedString ? (atoi(cvar->latchedString) != 0) : (cvar->integer != 0);
+ bool curValue = oldValue;
+ ImGui::Checkbox(va("##%s", cvar->name), &curValue);
+ if(curValue != oldValue)
+ {
+ Cvar_Set2(cvar->name, va("%d", (int)curValue), 0);
+ }
+ }
+ else if(cvar->type == CVART_INTEGER || cvar->type == CVART_BITMASK)
+ {
+ const int oldValue = cvar->latchedString ? atoi(cvar->latchedString) : cvar->integer;
+ int curValue = oldValue;
+ int min = cvar->validator.i.min;
+ int max = cvar->validator.i.max;
+ min = (min == INT32_MIN) ? -(1 << 20) : min;
+ max = (max == INT32_MAX) ? (1 << 20) : max;
+ ImGui::SetNextItemWidth(ImGui::GetIO().FontDefault->FontSize * 15.0f);
+ ImGui::SliderInt(va("##%s", cvar->name), &curValue, min, max,
+ "%d", ImGuiSliderFlags_AlwaysClamp);
+ if(curValue != oldValue)
+ {
+ Cvar_Set2(cvar->name, va("%d", curValue), 0);
+ }
+ }
+ else if(cvar->type == CVART_FLOAT && (!Q_stricmp(cvar->name, "cg_fov") || !Q_stricmp(cvar->name, "cg_zoomFov")))
+ {
+ const float oldValue = cvar->latchedString ? atof(cvar->latchedString) : cvar->value;
+ const float hMin = cvar->validator.f.min;
+ const float hMax = cvar->validator.f.max;
+ const float vMin = GetVerticalFov(hMin);
+ const float vMax = GetVerticalFov(hMax);
+ float curValue = oldValue;
+ ImGui::SetNextItemWidth(ImGui::GetIO().FontDefault->FontSize * 10.0f);
+ const bool hChange = ImGui::SliderFloat(va("Horizontal##%s", cvar->name), &curValue, hMin, hMax,
+ "%g", ImGuiSliderFlags_AlwaysClamp);
+ curValue = GetVerticalFov(curValue);
+ ImGui::SetNextItemWidth(ImGui::GetIO().FontDefault->FontSize * 10.0f);
+ const bool vChange = ImGui::SliderFloat(va("Vertical##%s", cvar->name), &curValue, vMin, vMax,
+ "%g", ImGuiSliderFlags_AlwaysClamp);
+ curValue = GetHorizontalFov(curValue);
+ if(hChange || vChange)
+ {
+ Cvar_Set2(cvar->name, va("%g", curValue), 0);
+ }
+ }
+ else if(cvar->type == CVART_FLOAT)
+ {
+ const float oldValue = cvar->latchedString ? atof(cvar->latchedString) : cvar->value;
+ float curValue = oldValue;
+ float min = cvar->validator.f.min;
+ float max = cvar->validator.f.max;
+ min = (min == -FLT_MAX) ? -1048576.0f : min;
+ max = (max == FLT_MAX) ? 1048576.0f : max;
+ ImGui::SetNextItemWidth(ImGui::GetIO().FontDefault->FontSize * 15.0f);
+ ImGui::SliderFloat(va("##%s", cvar->name), &curValue, min, max,
+ "%g", ImGuiSliderFlags_AlwaysClamp);
+ if(curValue != oldValue)
+ {
+ Cvar_Set2(cvar->name, va("%g", curValue), 0);
+ }
+ }
+}
+
+static void DrawCVarToolTip(cvar_t* cvar)
+{
+ if(!ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal))
+ {
+ return;
+ }
+
+ const char* const tooltipTextRaw = IsNonEmpty(cvar->gui.help) ? cvar->gui.help : "";
+ const char* const tooltipTextClean = RemoveColorCodes(tooltipTextRaw);
+ char help[1024];
+ if(IsNullOrEmpty(tooltipTextClean))
+ {
+ Com_sprintf(help, sizeof(help), "CVar: %s", cvar->name);
+ }
+ else
+ {
+ Com_sprintf(help, sizeof(help), "CVar: %s\n\n%s", cvar->name, tooltipTextClean);
+ }
+
+ ImGui::SetTooltip(help);
+}
+
+static void DrawCVarNoValue(cvar_t* cvar)
+{
+ Q_assert(cvar != NULL);
+ Q_assert(IsNonEmpty(cvar->gui.title));
+
+ ImGui::TableNextRow();
+ ImGui::TableSetColumnIndex(0);
+ ImGui::Text(cvar->gui.title);
+ DrawCVarToolTip(cvar);
+ if((cvar->flags & (CVAR_ROM | CVAR_INIT)) == 0)
+ {
+ ImGui::TableSetColumnIndex(2);
+ if(ImGui::Button(va("R##%s", cvar->name)))
+ {
+ Cvar_Set2(cvar->name, cvar->resetString, 0);
+ }
+ }
+ ImGui::TableSetColumnIndex(3);
+ ImGui::Text(cvar->latchedString != NULL ? cvar->latchedString : "");
+ ImGui::TableSetColumnIndex(4);
+ const char* const desc = IsNonEmpty(cvar->gui.desc) ? cvar->gui.desc : "";
+ ImGui::TextWrapped(RemoveColorCodes(desc));
+ DrawCVarToolTip(cvar);
+}
+
+static void DrawCVar(const char* cvarName)
+{
+ cvar_t* cvar = Cvar_FindVar(cvarName);
+ if(cvar == NULL)
+ {
+ return;
+ }
+
+ DrawCVarNoValue(cvar);
+ ImGui::TableSetColumnIndex(1);
+ DrawCVarValue(cvar);
+}
+
+static void DrawCVarValueCombo(const char* cvarName, int count, ...)
+{
+ cvar_t* cvar = Cvar_FindVar(cvarName);
+ if(cvar == NULL)
+ {
+ return;
+ }
+
+ Q_assert(count == cvar->validator.i.max - cvar->validator.i.min + 1);
+
+ const int oldValue = cvar->latchedString != NULL ? atoi(cvar->latchedString) : cvar->integer;
+
+ const char* previewString = NULL;
+ va_list args;
+ va_start(args, count);
+ for(int i = 0; i < count; ++i)
+ {
+ const char* value = va_arg(args, const char*);
+ if(oldValue == cvar->validator.i.min + i)
+ {
+ previewString = value;
+ break;
+ }
+ }
+ va_end(args);
+ Q_assert(previewString != NULL);
+
+ ImGui::SetNextItemWidth(ImGui::GetIO().FontDefault->FontSize * 15.0f);
+ if(ImGui::BeginCombo(va("##%s", cvar->name), previewString, ImGuiComboFlags_None))
+ {
+ va_start(args, count);
+ for(int i = 0; i < count; ++i)
+ {
+ const char* value = va_arg(args, const char*);
+ bool selected;
+ if(ImGui::Selectable(value, &selected, ImGuiSelectableFlags_None))
+ {
+ Cvar_Set2(cvar->name, va("%d", cvar->validator.i.min + i), 0);
+ }
+ }
+ va_end(args);
+
+ ImGui::EndCombo();
+ }
+}
+
+#if 0
+static void DrawCVarValueStringCombo(const char* cvarName, int count, ...)
+{
+ cvar_t* cvar = Cvar_FindVar(cvarName);
+ if(cvar == NULL)
+ {
+ return;
+ }
+
+ const char* const currValue = cvar->latchedString != NULL ? cvar->latchedString : cvar->string;
+
+ const char* previewString = NULL;
+ va_list args;
+ va_start(args, count);
+ for(int i = 0; i < count; ++i)
+ {
+ const char* value = va_arg(args, const char*);
+ const char* title = va_arg(args, const char*);
+ if(strcmp(currValue, value) == 0)
+ {
+ previewString = title;
+ break;
+ }
+ }
+ va_end(args);
+
+ if(previewString == NULL)
+ {
+ previewString = "???";
+ }
+
+ ImGui::SetNextItemWidth(ImGui::GetIO().FontDefault->FontSize * 15.0f);
+ if(ImGui::BeginCombo(va("##%s", cvar->name), previewString, ImGuiComboFlags_None))
+ {
+ va_start(args, count);
+ for(int i = 0; i < count; ++i)
+ {
+ const char* value = va_arg(args, const char*);
+ const char* title = va_arg(args, const char*);
+ bool selected;
+ if(ImGui::Selectable(title, &selected, ImGuiSelectableFlags_None))
+ {
+ Cvar_Set2(cvar->name, value, 0);
+ }
+ }
+ va_end(args);
+
+ ImGui::EndCombo();
+ }
+}
+
+static void DrawCVarValueBitmask(const char* cvarName, int count, ...)
+{
+ cvar_t* cvar = Cvar_FindVar(cvarName);
+ if(cvar == NULL)
+ {
+ return;
+ }
+
+ Q_assert(cvar->validator.i.min == 0);
+ Q_assert(IsPowerOfTwo(cvar->validator.i.max + 1));
+ Q_assert(count == log2(cvar->validator.i.max + 1));
+
+ ImGui::TableSetColumnIndex(1);
+
+ const int oldValue = cvar->latchedString != NULL ? atoi(cvar->latchedString) : cvar->integer;
+
+ va_list args;
+ va_start(args, count);
+ for(int i = 0; i < count; ++i)
+ {
+ const char* title = va_arg(args, const char*);
+ bool bitValue = (oldValue & (1 << i)) != 0;
+ if(ImGui::Checkbox(title, &bitValue))
+ {
+ int newValue = oldValue;
+ if(bitValue)
+ {
+ newValue |= (1 << i);
+ }
+ else
+ {
+ newValue &= ~(1 << i);
+ }
+ Cvar_Set2(cvar->name, va("%d", newValue), 0);
+ }
+ }
+ va_end(args);
+}
+#endif
+
+static void DrawFontSelection()
+{
+#if 0
+ ImGuiIO& io = ImGui::GetIO();
+ ImFont* currentFont = ImGui::GetFont();
+ if(ImGui::BeginCombo("Font Selection", currentFont->GetDebugName()))
+ {
+ for(int i = 0; i < io.Fonts->Fonts.Size; ++i)
+ {
+ ImFont* font = io.Fonts->Fonts[i];
+ ImGui::PushID((void*)font);
+ if(ImGui::Selectable(font->GetDebugName(), font == currentFont))
+ {
+ io.FontDefault = font;
+ }
+ ImGui::PopID();
+ }
+
+ ImGui::EndCombo();
+ }
+#endif
+
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("Font");
+ ImGui::SameLine();
+ DrawCVarValueCombo("r_guiFont", 2, "Proggy Clean (13px)", "Sweet16 Mono (16px)");
+ const int fontIndex = Cvar_VariableIntegerValue("r_guiFont");
+ ImGuiIO& io = ImGui::GetIO();
+ if(fontIndex >= 0 && fontIndex < io.Fonts->Fonts.Size)
+ {
+ io.FontDefault = io.Fonts->Fonts[fontIndex];
+ }
+}
+
+static void SetTableColumns()
+{
+ ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFont()->FontSize * 16.0f);
+ ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFont()->FontSize * 20.0f);
+ ImGui::TableSetupColumn("Reset");
+ ImGui::TableSetupColumn("Latched");
+ ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFont()->FontSize * 32.0f);
+ ImGui::TableHeadersRow();
+}
+
+static void DrawVideoRestart(bool restartNeeded)
+{
+ if(ImGui::Button("Video restart"))
+ {
+ Cbuf_AddText("vid_restart\n");
+ }
+ if(restartNeeded)
+ {
+ ImGui::SameLine();
+ ImGui::Text("Some pending changes need a restart to take effect.");
+ }
+}
+
+static bool DrawCVarTable(bool* restartNeeded, const char* title, int categoryMask)
+{
+ if(BeginTable(title, 5))
+ {
+ SetTableColumns();
+
+ for(cvar_t* var = Cvar_GetFirst(); var != NULL; var = var->next)
+ {
+ if(var->gui.categories & CVARCAT_DEBUGGING)
+ {
+ continue;
+ }
+
+ if(var->gui.categories & categoryMask)
+ {
+ if(cvarFilter[0] != '\0')
+ {
+ char filter[256];
+ Com_sprintf(filter, sizeof(filter), cvarFilter[0] == '*' ? "%s" : "*%s", cvarFilter);
+ const cvarGui_t* const gui = &var->gui;
+ const bool matchName = !!Com_Filter(filter, var->name);
+ const bool matchTitle = gui->title != NULL && !!Com_Filter(filter, gui->title);
+ const bool matchDesc = gui->desc != NULL && !!Com_Filter(filter, gui->desc);
+ const bool matchHelp = gui->help != NULL && !!Com_Filter(filter, gui->help);
+ bool matchValues = false;
+ for(int v = 0; v < gui->numValues; ++v)
+ {
+ const cvarGuiValue_t* const value = &gui->values[v];
+ if(!!Com_Filter(filter, value->title) ||
+ !!Com_Filter(filter, value->desc))
+ {
+ matchValues = true;
+ break;
+ }
+ }
+ if(!matchName && !matchTitle && !matchDesc && !matchHelp && !matchValues)
+ {
+ continue;
+ }
+ }
+
+ DrawCVar(var->name);
+ if(var->latchedString != NULL)
+ {
+ *restartNeeded = true;
+ }
+ }
+ }
+
+ ImGui::EndTable();
+ }
+
+ return restartNeeded;
+}
+
+static void DrawSettings()
+{
+ static float opacity = 1.0f;
+ ImVec4 bgColor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
+ bgColor.w *= opacity;
+ ImGui::PushStyleColor(ImGuiCol_WindowBg, bgColor);
+
+ static bool active = false;
+ static bool restartNeeded = false;
+ ToggleBooleanWithShortcut(active, ImGuiKey_O);
+ GUI_AddMainMenuItem(GUI_MainMenu::Tools, "Client Settings", "Ctrl+O", &active);
+ if(active)
+ {
+ const ImGuiWindowFlags flags =
+ ImGuiWindowFlags_AlwaysAutoResize |
+ (restartNeeded ? ImGuiWindowFlags_UnsavedDocument : 0);
+ restartNeeded = false;
+ if(ImGui::Begin("Client Settings", &active, flags))
+ {
+ DrawFontSelection();
+ ImGui::SliderFloat("Dialog opacity", &opacity, 0.5f, 1.0f, "%g", ImGuiSliderFlags_AlwaysClamp);
+
+ ImGui::NewLine();
+ DrawFilter(cvarFilter, sizeof(cvarFilter));
+ ImGui::NewLine();
+
+ ImGui::BeginTabBar("Tabs#ClientSettings");
+ if(ImGui::BeginTabItem("All"))
+ {
+ DrawCVarTable(&restartNeeded, "All settings", -1 & (~CVARCAT_DEBUGGING));
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("General"))
+ {
+ DrawCVarTable(&restartNeeded, "General settings", CVARCAT_GENERAL);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Gameplay"))
+ {
+ DrawCVarTable(&restartNeeded, "Gameplay settings", CVARCAT_GAMEPLAY);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("HUD"))
+ {
+ DrawCVarTable(&restartNeeded, "HUD settings", CVARCAT_HUD);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Video"))
+ {
+ DrawCVarTable(&restartNeeded, "Display settings", CVARCAT_DISPLAY);
+ DrawCVarTable(&restartNeeded, "Graphics settings", CVARCAT_GRAPHICS);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Audio"))
+ {
+ DrawCVarTable(&restartNeeded, "Sound settings", CVARCAT_SOUND);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Input"))
+ {
+ DrawCVarTable(&restartNeeded, "Input settings", CVARCAT_INPUT);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Network"))
+ {
+ DrawCVarTable(&restartNeeded, "Network and client-side prediction settings", CVARCAT_NETWORK);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Console"))
+ {
+ DrawCVarTable(&restartNeeded, "Console settings", CVARCAT_CONSOLE);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Demo"))
+ {
+ DrawCVarTable(&restartNeeded, "Demo playback settings", CVARCAT_DEMO);
+ ImGui::EndTabItem();
+ }
+ if(ImGui::BeginTabItem("Performance"))
+ {
+ DrawCVarTable(&restartNeeded, "Performance settings", CVARCAT_PERFORMANCE);
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+
+ DrawVideoRestart(restartNeeded);
+ }
+
+ ImGui::End();
+ }
+
+ ImGui::PopStyleColor(1);
+}
+
void R_DrawGUI()
{
DrawImageList();
@@ -852,6 +1841,8 @@ void R_DrawGUI()
DrawShaderList();
DrawShaderWindow();
DrawShaderEdit();
+ DrawFrontEndStats();
+ DrawSettings();
}
void R_ShutDownGUI()
diff --git a/code/renderer/tr_help.h b/code/renderer/tr_help.h
index 08fc37b..960d54b 100644
--- a/code/renderer/tr_help.h
+++ b/code/renderer/tr_help.h
@@ -159,6 +159,11 @@ S_COLOR_VAL " 6 " S_COLOR_HELP "= 4x4 (extended mode)\n" \
"with thin horizontal lines, which become an aliased mess when\n" \
"vertically subsampled."
+#define help_r_guiFont \
+"font for CNQ3's GUI\n" \
+S_COLOR_VAL " 0 " S_COLOR_HELP "= Proggy Clean (13px)\n" \
+S_COLOR_VAL " 1 " S_COLOR_HELP "= Sweet16 Mono (16px)"
+
#define help_r_ignoreShaderSortKey \
"ignores the shader sort key of transparent surfaces\n" \
"Instead, it sorts by depth and original registration order only.\n" \
diff --git a/code/renderer/tr_init.cpp b/code/renderer/tr_init.cpp
index e0c946c..9afca89 100644
--- a/code/renderer/tr_init.cpp
+++ b/code/renderer/tr_init.cpp
@@ -31,8 +31,6 @@ screenshotCommand_t r_delayedScreenshot;
qbool r_delayedScreenshotPending = qfalse;
int r_delayedScreenshotFrame = 0;
-cvar_t *r_verbose;
-
cvar_t *r_displayRefresh;
cvar_t *r_detailTextures;
@@ -52,7 +50,6 @@ cvar_t *r_lodscale;
cvar_t *r_norefresh;
cvar_t *r_drawentities;
cvar_t *r_drawworld;
-cvar_t *r_speeds;
cvar_t *r_fullbright;
cvar_t *r_lightmap;
cvar_t *r_lightmapGreyscale;
@@ -61,6 +58,7 @@ cvar_t *r_mapGreyscaleCTF;
cvar_t *r_teleporterFlash;
cvar_t *r_sleepThreshold;
cvar_t *r_shadingRate;
+cvar_t *r_guiFont;
cvar_t *r_novis;
cvar_t *r_nocull;
cvar_t *r_nocurves;
@@ -91,7 +89,7 @@ cvar_t *r_showsky;
cvar_t *r_showtris;
cvar_t *r_shownormals;
cvar_t *r_clear;
-cvar_t *r_swapInterval;
+cvar_t *r_vsync;
cvar_t *r_lego;
cvar_t *r_lockpvs;
cvar_t *r_noportals;
@@ -102,7 +100,6 @@ cvar_t *r_lodCurveError;
cvar_t *r_width;
cvar_t *r_height;
-cvar_t *r_customaspect;
cvar_t *r_brightness;
cvar_t *r_mapBrightness;
@@ -337,92 +334,353 @@ static const cvarTableItem_t r_cvars[] =
//
// latched and archived variables
//
- { &r_mipGenFilter, "r_mipGenFilter", "L4", CVAR_ARCHIVE | CVAR_LATCH, CVART_STRING, NULL, NULL, help_r_mipGenFilter },
- { &r_mipGenGamma, "r_mipGenGamma", "1.8", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1.0", "3.0", help_r_mipGenGamma },
- { &r_ext_max_anisotropy, "r_ext_max_anisotropy", "16", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", help_r_ext_max_anisotropy },
- { &r_roundImagesDown, "r_roundImagesDown", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_roundImagesDown },
- { &r_colorMipLevels, "r_colorMipLevels", "0", CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_colorMipLevels },
- { &r_detailTextures, "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "enables detail textures shader stages" },
- { &r_mode, "r_mode", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(VIDEOMODE_MAX), help_r_mode },
- { &r_brightness, "r_brightness", "2", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0.25", "32", "overall brightness" },
- // should be called r_lightmapBrightness
- { &r_mapBrightness, "r_mapBrightness", "2", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0.25", "32", "brightness of lightmap textures" },
- // should be called r_textureBrightness
- { &r_intensity, "r_intensity", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1", NULL, "brightness of non-lightmap map textures" },
- { &r_fullscreen, "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "full-screen mode" },
- { &r_width, "r_width", "1280", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "320", "65535", "custom window/render width" },
- { &r_height, "r_height", "720", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "240", "65535", "custom window/render height" },
- { &r_customaspect, "r_customaspect", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0.1", "10", "custom pixel aspect ratio" },
- { &r_vertexLight, "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "disables lightmap texture blending" },
- // note that r_subdivisions > 64 will create rendering artefacts because you'll see the other side of a curved surface when against it
- { &r_subdivisions, "r_subdivisions", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1", "64", help_r_subdivisions },
- { &r_fullbright, "r_fullbright", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_fullbright },
- { &r_lightmap, "r_lightmap", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_lightmap },
- { &r_lightmapGreyscale, "r_lightmapGreyscale", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0", "1", "how desaturated the lightmap looks" },
- { &r_depthFade, "r_depthFade", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_depthFade },
- { &r_dither, "r_dither", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_dither },
- { &r_rtColorFormat, "r_rtColorFormat", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(RTCF_MAX), help_r_rtColorFormat },
- { &r_depthClamp, "r_depthClamp", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_depthClamp },
- { &r_gpuPreference, "r_gpuPreference", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(GPUPREF_MAX), help_r_gpuPreference},
- { &r_swapInterval, "r_swapInterval", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "enables v-sync" },
+ {
+ &r_mipGenFilter, "r_mipGenFilter", "L4", CVAR_ARCHIVE | CVAR_LATCH, CVART_STRING, NULL, NULL, "mip-map generation filter",
+ "Mip-map filter", CVARCAT_GRAPHICS, "Texture sharpness in the distance", "",
+ CVAR_GUI_VALUE("L4", "Lanczos 4", "Very sharp, 4-pixel radius")
+ CVAR_GUI_VALUE("L3", "Lanczos 3", "Very sharp, 3-pixel radius")
+ CVAR_GUI_VALUE("BL", "Bi-linear", "Blurry, 1-pixel radius")
+ CVAR_GUI_VALUE("MN2", "Mitchell-Netravali 2", "Balanced, 2-pixel radius")
+ CVAR_GUI_VALUE("BH4", "3-term Blackman-Harris 4", "Balanced, 4-pixel radius")
+ CVAR_GUI_VALUE("BH3", "3-term Blackman-Harris 3", "Balanced, 3-pixel radius")
+ CVAR_GUI_VALUE("BH2", "3-term Blackman-Harris 2", "Balanced, 2-pixel radius")
+ CVAR_GUI_VALUE("T2", "Tent 2 (1/3 2/3)", "Blurry, 2-pixel radius")
+ },
+ {
+ &r_mipGenGamma, "r_mipGenGamma", "1.8", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1.0", "3.0", help_r_mipGenGamma,
+ "Mip-map gamma", CVARCAT_GRAPHICS, "Texture contrast in the distance", ""
+ },
+ {
+ &r_ext_max_anisotropy, "r_ext_max_anisotropy", "16", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", help_r_ext_max_anisotropy,
+ "Texture anisotropy", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Texture sharpness at oblique angles", ""
+ },
+ {
+ &r_roundImagesDown, "r_roundImagesDown", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_roundImagesDown,
+ "Low-resolution resampling", CVARCAT_GRAPHICS, "Lowers the resolution of non-power of two textures"
+ },
+ {
+ &r_colorMipLevels, "r_colorMipLevels", "0", CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_colorMipLevels,
+ "Colorize texture mips", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_detailTextures, "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "enables detail textures shader stages",
+ "Enable detail textures", CVARCAT_GRAPHICS, "It also toggles decals on some maps", ""
+ },
+ {
+ &r_mode, "r_mode", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(VIDEOMODE_MAX), help_r_mode,
+ "Full-screen video mode", CVARCAT_DISPLAY, "", "",
+ CVAR_GUI_VALUE("0", "Native res", "Same resolution as on the desktop")
+ CVAR_GUI_VALUE("1", "Custom res/upscale", "Custom resolution, upsampled by CNQ3")
+ CVAR_GUI_VALUE("2", "Video mode change", "Custom resolution, upsampled by the system\n\n"
+ "Only use this on monitors that can reach higher refresh rates at lower resolutions.\n"
+ "It makes alt-tabbing slow.")
+ },
+ {
+ &r_brightness, "r_brightness", "2", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0.25", "32", "overall brightness",
+ "Screen brightness", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ // should be called r_lightmapBrightness
+ &r_mapBrightness, "r_mapBrightness", "2", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0.25", "32", "brightness of lightmap textures",
+ "Lightmap brightness", CVARCAT_GRAPHICS, "Applies to lightmap textures only", ""
+ },
+ {
+ // should be called r_textureBrightness
+ &r_intensity, "r_intensity", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1", "32", "brightness of non-lightmap map textures",
+ "Texture brightness", CVARCAT_GRAPHICS, "Applies to non-lightmap textures only", ""
+ },
+ {
+ &r_fullscreen, "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "full-screen mode",
+ "Fullscreen", CVARCAT_DISPLAY, "", "",
+ CVAR_GUI_VALUE("0", "Windowed", "")
+ CVAR_GUI_VALUE("1", "Fullscreen", "")
+ },
+ {
+ &r_width, "r_width", "1280", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "320", "65535", "custom window/render width",
+ "Window/render width", CVARCAT_DISPLAY, "Used in windowed mode and non-native full-screen", ""
+ },
+ {
+ &r_height, "r_height", "720", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "240", "65535", "custom window/render height",
+ "Window/render height", CVARCAT_DISPLAY, "Used in windowed mode and non-native full-screen", ""
+ },
+ {
+ &r_vertexLight, "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "disables lightmap texture blending",
+ "Vertex lighting", CVARCAT_GRAPHICS, "Uses per-vertex lighting data instead of lightmaps", ""
+ },
+ {
+ // note that r_subdivisions > 64 will create rendering artefacts because you'll see the other side of a curved surface when against it
+ &r_subdivisions, "r_subdivisions", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1", "64", help_r_subdivisions,
+ "Patch tessellation step size", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Lower values produce smoother curves", ""
+ },
+ {
+ &r_fullbright, "r_fullbright", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_fullbright,
+ "Fullbright lighting", CVARCAT_GRAPHICS, "Lightmap textures get replaced by white/grey images", ""
+ },
+ {
+ &r_lightmap, "r_lightmap", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_lightmap,
+ "Draw lightmaps", CVARCAT_GRAPHICS, "Draws lightmap data only when available", ""
+ },
+ {
+ &r_lightmapGreyscale, "r_lightmapGreyscale", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "0", "1", "how desaturated the lightmap looks",
+ "Lightmap desaturation", CVARCAT_GRAPHICS, "Desaturates the lightmap data", ""
+ },
+ // @TODO:
+ //{
+ //&r_depthFade, "r_depthFade", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_depthFade,
+ //"", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "", ""
+ //},
+ {
+ &r_dither, "r_dither", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_dither,
+ "Dither", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Adds noise to fight color banding artifacts", ""
+ },
+ {
+ &r_rtColorFormat, "r_rtColorFormat", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(RTCF_MAX), help_r_rtColorFormat,
+ "Render target format", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Controls the number of bits per pixel for the RGBA channels", "",
+ CVAR_GUI_VALUE("0", "R8G8B8A8", "High perf, standard quality")
+ CVAR_GUI_VALUE("1", "R10G10B10A2", "High perf, better colors, worse alpha")
+ CVAR_GUI_VALUE("2", "R16G16B16A16", "Low perf, better colors and alpha")
+ },
+ {
+ &r_depthClamp, "r_depthClamp", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_depthClamp,
+ "Depth clamping", CVARCAT_GRAPHICS, "Enable if you want a horizontal FOV larger than 130", ""
+ },
+ {
+ &r_gpuPreference, "r_gpuPreference", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(GPUPREF_MAX), help_r_gpuPreference,
+ "GPU selection", CVARCAT_DISPLAY | CVARCAT_PERFORMANCE, "Choose between low-power and high-performance devices", "",
+ CVAR_GUI_VALUE("0", "High performance", "")
+ CVAR_GUI_VALUE("1", "Low power", "")
+ CVAR_GUI_VALUE("2", "None", "")
+ },
+ {
+ &r_vsync, "r_vsync", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "enables v-sync",
+ "V-Sync", CVARCAT_DISPLAY | CVARCAT_PERFORMANCE, "Enabling locks the framerate to the monitor's refresh rate", ""
+ CVAR_GUI_VALUE("0", "Frame cap", "The framerate is capped by CNQ3's own limiter")
+ CVAR_GUI_VALUE("1", "V-Sync", "The framerate matches the monitor's refresh rate")
+ },
//
// latched variables that can only change over a restart
//
- { &r_displayRefresh, "r_displayRefresh", "0", CVAR_LATCH, CVART_INTEGER, "0", "480", S_COLOR_VAL "0 " S_COLOR_HELP "lets the driver decide" },
- { &r_singleShader, "r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH },
+ {
+ &r_displayRefresh, "r_displayRefresh", "0", CVAR_LATCH, CVART_INTEGER, "0", "480", S_COLOR_VAL "0 " S_COLOR_HELP "lets the driver decide",
+ "Refresh rate", CVARCAT_DISPLAY, "0 to let the driver decide", "Only available in fullscreen with video mode change"
+ },
+ {
+ &r_singleShader, "r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH, CVART_BOOL, NULL, NULL, "forces the default shader on all world surfaces except the sky",
+ "Force default shader", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "Forces it on all world surfaces except the sky", ""
+ },
//
// archived variables that can change at any time
//
- { &r_smaa, "r_smaa", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "4", help_r_smaa },
- { &r_picmip, "r_picmip", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "16", help_r_picmip },
- { &r_blitMode, "r_blitMode", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", XSTRING(BLITMODE_MAX), help_r_blitMode },
- { &r_lodbias, "r_lodbias", "-2", CVAR_ARCHIVE, CVART_INTEGER, "-16", "16", help_r_lodbias },
- { &r_ignoreShaderSortKey, "r_ignoreShaderSortKey", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_ignoreShaderSortKey },
- { &r_fastsky, "r_fastsky", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_fastsky },
- { &r_noportals, "r_noportals", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_noportals },
- { &r_dynamiclight, "r_dynamiclight", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables dynamic lights" },
- { &r_lego, "r_lego", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "LEGO(R) texture filtering" },
- { &r_gamma, "r_gamma", "1.2", CVAR_ARCHIVE, CVART_FLOAT, "0.5", "3", help_r_gamma },
- { &r_greyscale, "r_greyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "how desaturated the final image looks" },
- { &r_ditherStrength, "r_ditherStrength", "1.0", CVAR_ARCHIVE, CVART_FLOAT, "0.125", "8.0", help_r_ditherStrength },
- { &r_transpSort, "r_transpSort", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_transpSort },
- { &r_lodCurveError, "r_lodCurveError", "2000", CVAR_ARCHIVE, CVART_FLOAT, "250", "10000", "curved surfaces LOD scale" },
- { &r_mapGreyscale, "r_mapGreyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "how desaturated the map looks" },
- { &r_mapGreyscaleCTF, "r_mapGreyscaleCTF", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", help_r_mapGreyscaleCTF },
- { &r_teleporterFlash, "r_teleporterFlash", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "draws bright colors when being teleported" },
- { &r_sleepThreshold, "r_sleepThreshold", "2500", CVAR_ARCHIVE, CVART_INTEGER, "2000", "4000", help_r_sleepThreshold },
- { &r_shadingRate, "r_shadingRate", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "6", help_r_shadingRate },
+ {
+ &r_smaa, "r_smaa", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "4", help_r_smaa,
+ "SMAA", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Enhanced sub-pixel morphological anti-aliasing", "",
+ CVAR_GUI_VALUE("0", "Disabled", "")
+ CVAR_GUI_VALUE("1", "Low quality", "")
+ CVAR_GUI_VALUE("2", "Medium quality", "")
+ CVAR_GUI_VALUE("3", "High quality", "")
+ CVAR_GUI_VALUE("4", "Ultra quality", "")
+ },
+ {
+ &r_picmip, "r_picmip", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "16", help_r_picmip,
+ "Picmip", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Higher numbers make for blurrier textures", ""
+ },
+ {
+ &r_blitMode, "r_blitMode", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", XSTRING(BLITMODE_MAX), help_r_blitMode,
+ "Fullscreen blit mode", CVARCAT_DISPLAY, "Dictates how the image gets upsampled", "",
+ CVAR_GUI_VALUE("0", "Scaled to fit", "Preserves aspect ratio -> black bars")
+ CVAR_GUI_VALUE("1", "Centered", "No scaling at all")
+ CVAR_GUI_VALUE("2", "Stretched", "Takes the entire screen -> no black bars")
+ },
+ {
+ &r_lodbias, "r_lodbias", "-2", CVAR_ARCHIVE, CVART_INTEGER, "-2", "2", help_r_lodbias,
+ "MD3 LoD bias", CVARCAT_GRAPHICS, "Applies to items and player models\nLower means more detail", ""
+ },
+ {
+ &r_ignoreShaderSortKey, "r_ignoreShaderSortKey", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_ignoreShaderSortKey,
+ "Ignore shader draw order", CVARCAT_GRAPHICS, "All transparent surfaces are sorted by depth", ""
+ },
+ {
+ &r_fastsky, "r_fastsky", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_fastsky,
+ "Fast sky", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Draws the sky and portal surfaces in black", ""
+ },
+ {
+ &r_noportals, "r_noportals", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_noportals,
+ "Disable portal rendering", CVARCAT_GRAPHICS, "Draws teleporter and mirror surfaces in black", ""
+ },
+ {
+ &r_dynamiclight, "r_dynamiclight", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables dynamic lights",
+ "", 0, "", "" // @TODO: CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE once implemented
+ },
+ {
+ &r_lego, "r_lego", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "LEGO(R) texture filtering",
+ "LEGO(R) textures", CVARCAT_GRAPHICS, "Makes textures look blocky", "Forces nearest neighbor texture filtering"
+ },
+ {
+ &r_gamma, "r_gamma", "1.2", CVAR_ARCHIVE, CVART_FLOAT, "0.5", "3", help_r_gamma,
+ "Screen gamma", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ &r_greyscale, "r_greyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "how desaturated the final image looks",
+ "Screen desaturation", CVARCAT_GRAPHICS, "", ""
+ },
+ {
+ &r_ditherStrength, "r_ditherStrength", "1.0", CVAR_ARCHIVE, CVART_FLOAT, "0.125", "8.0", help_r_ditherStrength,
+ "Dither strength", CVARCAT_GRAPHICS, "Amount of noise added to fight color banding", ""
+ },
+ {
+ &r_transpSort, "r_transpSort", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_transpSort,
+ "Transparent surface sorting", CVARCAT_GRAPHICS, "", "",
+ CVAR_GUI_VALUE("0", "Sort dynamic", "")
+ CVAR_GUI_VALUE("1", "Sort all", "")
+ },
+ {
+ &r_lodCurveError, "r_lodCurveError", "2000", CVAR_ARCHIVE, CVART_FLOAT, "250", "10000", "curved surfaces LOD scale",
+ "Curve LoD scale", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Higher is more detailed", ""
+ },
+ {
+ &r_mapGreyscale, "r_mapGreyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "how desaturated the map looks",
+ "Non-CTF map desaturation", CVARCAT_GRAPHICS, "Desaturates non-CTF world surfaces", "CTF surfaces are the red/blue base banners/markers"
+ },
+ {
+ &r_mapGreyscaleCTF, "r_mapGreyscaleCTF", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", help_r_mapGreyscaleCTF,
+ "CTF map desaturation", CVARCAT_GRAPHICS, "Desaturates CTF world surfaces", "CTF surfaces are the red/blue base banners/markers"
+ },
+ {
+ &r_teleporterFlash, "r_teleporterFlash", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "draws bright colors when being teleported",
+ "Bright teleporter flash", CVARCAT_GRAPHICS, "Draws bright colors while being teleported", ""
+ },
+ {
+ &r_sleepThreshold, "r_sleepThreshold", "2500", CVAR_ARCHIVE, CVART_INTEGER, "2000", "4000", help_r_sleepThreshold,
+ "Frame sleep threshold", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Higher means more consistent frame times but higher CPU usage",
+ "This is the time cushion (in microseconds) for frame sleep.\n"
+ "It's a trade-off between frame time consistency and CPU usage.\n"
+ "Set to 2000 if you have a struggling old/low-power CPU.\n"
+ "2500 should be enough to deal with delayed thread wake-ups.\n"
+ "Use the frame graph to confirm that higher values help on your system."
+ },
+ {
+ &r_shadingRate, "r_shadingRate", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "6", help_r_shadingRate,
+ "Shading rate", CVARCAT_GRAPHICS | CVARCAT_PERFORMANCE, "Variable-Rate Shading (VRS) mode",
+ "The numbers are the horizontal and vertical subsampling factors.\n"
+ "1x1 is forced for the sky, nopicmipped sprites (e.g. simple items)\n"
+ "and nopicmipped alpha tested surfaces (e.g. grates).\n"
+ "If extended modes are not supported, 2x2 is used instead.\n"
+ "Prefer horizontal subsampling as many maps have textures\n"
+ "with thin horizontal lines, which become an aliased mess when\n"
+ "vertically subsampled.",
+ CVAR_GUI_VALUE("0", "Off", "1x horizontal, 1x vertical")
+ CVAR_GUI_VALUE("1", "2x1", "2x horizontal, 1x vertical")
+ CVAR_GUI_VALUE("2", "1x2", "1x horizontal, 2x vertical")
+ CVAR_GUI_VALUE("3", "2x2", "2x horizontal, 2x vertical")
+ CVAR_GUI_VALUE("4", "4x2", "4x horizontal, 2x vertical")
+ CVAR_GUI_VALUE("5", "2x4", "2x horizontal, 4x vertical")
+ CVAR_GUI_VALUE("6", "4x4", "4x horizontal, 4x vertical")
+ },
+ {
+ &r_guiFont, "r_guiFont", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "1", help_r_guiFont,
+ "GUI font", CVARCAT_GUI, "", "",
+ CVAR_GUI_VALUE("0", "Proggy Clean (13px)", "")
+ CVAR_GUI_VALUE("1", "Sweet16 Mono (16px)", "")
+ },
//
// temporary variables that can change at any time
//
- { &r_ambientScale, "r_ambientScale", "0.6", CVAR_CHEAT, CVART_FLOAT, "0", NULL, "entity ambient light scale" },
- { &r_directedScale, "r_directedScale", "1", CVAR_CHEAT, CVART_FLOAT, "0", NULL, "entity directed light scale" },
- { &r_uiFullScreen, "r_uifullscreen", "0", CVAR_TEMP, CVART_BOOL }, // keeping it around in case we enable other mods again
- { &r_debugLight, "r_debuglight", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "prints entity light values" },
- { &r_debugSort, "r_debugSort", "0", CVAR_CHEAT, CVART_FLOAT, "0", NULL, "doesn't render shaders with a greater sort key" },
- { &r_nocurves, "r_nocurves", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "doesn't render grid meshes" },
- { &r_drawworld, "r_drawworld", "1", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables rendering of world surfaces" },
- { &r_portalOnly, "r_portalOnly", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "only draws the mirrored plane" },
- { &r_lodscale, "r_lodscale", "5", CVAR_CHEAT, CVART_FLOAT, "1", "20", "LOD scale for MD3 models" },
- { &r_norefresh, "r_norefresh", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables 3D scene rendering" },
- { &r_drawentities, "r_drawentities", "1", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "enables entity rendering" },
- { &r_nocull, "r_nocull", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables frustum culling" },
- { &r_novis, "r_novis", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables PVS usage" },
- { &r_speeds, "r_speeds", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "draws rendering performance counters" },
- { &r_verbose, "r_verbose", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "prints additional information" },
- { &r_debugSurface, "r_debugSurface", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "draws collision models" },
- { &r_showsky, "r_showsky", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "forces sky in front of all surfaces" },
- { &r_showtris, "r_showtris", "0", CVAR_CHEAT, CVART_BITMASK, "0", XSTRING(SHOWTRIS_MAX), help_r_showtris },
- { &r_shownormals, "r_shownormals", "0", CVAR_CHEAT, CVART_BITMASK, "0", XSTRING(SHOWTRIS_MAX), help_r_shownormals },
- { &r_clear, "r_clear", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "clears to violet instead of black" },
- { &r_lockpvs, "r_lockpvs", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "helps visualize the current PVS' limits" },
- { &r_maxpolys, "r_maxpolys", XSTRING(DEFAULT_MAX_POLYS), 0, CVART_INTEGER, XSTRING(DEFAULT_MAX_POLYS), NULL, "maximum polygon count per frame" },
- { &r_maxpolyverts, "r_maxpolyverts", XSTRING(DEFAULT_MAX_POLYVERTS), 0, CVART_INTEGER, XSTRING(DEFAULT_MAX_POLYVERTS), NULL, "maximum polygon vertex count per frame" },
- { &r_debugUI, "r_debugUI", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "displays the debug/profile GUI" },
- { &r_debugInput, "r_debugInput", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "routes input to the debug/profile GUI" }
+ {
+ &r_ambientScale, "r_ambientScale", "0.6", CVAR_CHEAT, CVART_FLOAT, "0", NULL, "entity ambient light scale",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_directedScale, "r_directedScale", "1", CVAR_CHEAT, CVART_FLOAT, "0", NULL, "entity directed light scale",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ // keeping it around in case we enable other mods again
+ &r_uiFullScreen, "r_uifullscreen", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, NULL,
+ "", 0, "", ""
+ },
+ {
+ &r_debugLight, "r_debuglight", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "prints entity light values",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_debugSort, "r_debugSort", "0", CVAR_CHEAT, CVART_FLOAT, "0", NULL, "doesn't render shaders with a greater sort key",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_nocurves, "r_nocurves", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "doesn't render grid meshes",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_drawworld, "r_drawworld", "1", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables rendering of world surfaces",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_portalOnly, "r_portalOnly", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "only draws the mirrored plane",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_lodscale, "r_lodscale", "5", CVAR_CHEAT, CVART_FLOAT, "1", "20", "LOD scale for MD3 models",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_norefresh, "r_norefresh", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables 3D scene rendering",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_drawentities, "r_drawentities", "1", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "enables entity rendering",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_nocull, "r_nocull", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables frustum culling",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_novis, "r_novis", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "disables PVS usage",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_debugSurface, "r_debugSurface", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "draws collision models",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_showsky, "r_showsky", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "forces sky in front of all surfaces",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_showtris, "r_showtris", "0", CVAR_CHEAT, CVART_BITMASK, "0", XSTRING(SHOWTRIS_MAX), help_r_showtris,
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_shownormals, "r_shownormals", "0", CVAR_CHEAT, CVART_BITMASK, "0", XSTRING(SHOWTRIS_MAX), help_r_shownormals,
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_clear, "r_clear", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "clears to violet instead of black",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_lockpvs, "r_lockpvs", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "helps visualize the current PVS' limits",
+ "", CVARCAT_GRAPHICS | CVARCAT_DEBUGGING, "", ""
+ },
+ {
+ &r_maxpolys, "r_maxpolys", XSTRING(DEFAULT_MAX_POLYS), 0, CVART_INTEGER, XSTRING(DEFAULT_MAX_POLYS), NULL, "maximum polygon count per frame",
+ "Max poly count", 0, "Maximum polygon count per frame", ""
+ },
+ {
+ &r_maxpolyverts, "r_maxpolyverts", XSTRING(DEFAULT_MAX_POLYVERTS), 0, CVART_INTEGER, XSTRING(DEFAULT_MAX_POLYVERTS), NULL, "maximum polygon vertex count per frame",
+ "Max poly vertices", 0, "Maximum polygon vertex count per frame", ""
+ },
+ {
+ &r_debugUI, "r_debugUI", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "displays the debug/profile GUI",
+ "", 0, "", ""
+ },
+ {
+ &r_debugInput, "r_debugInput", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "routes input to the debug/profile GUI",
+ "", 0, "", ""
+ }
};
@@ -589,6 +847,45 @@ static qbool RE_IsDepthClampEnabled()
}
+static void RE_ComputeCursorPosition( int* x, int* y )
+{
+ if ( r_fullscreen->integer != 1 || r_mode->integer != VIDEOMODE_UPSCALE ) {
+ return;
+ }
+
+ if ( r_blitMode->integer == BLITMODE_CENTERED ) {
+ *x -= (glInfo.winWidth - glConfig.vidWidth) / 2;
+ *y -= (glInfo.winHeight - glConfig.vidHeight) / 2;
+ } else if ( r_blitMode->integer == BLITMODE_STRETCHED ) {
+ const float sx = (float)glConfig.vidWidth / (float)glInfo.winWidth;
+ const float sy = (float)glConfig.vidHeight / (float)glInfo.winHeight;
+ *x *= sx;
+ *y *= sy;
+ } else if ( r_blitMode->integer == BLITMODE_ASPECT ) {
+ const float art = (float)glConfig.vidWidth / (float)glConfig.vidHeight;
+ const float arw = (float)glInfo.winWidth / (float)glInfo.winHeight;
+ float wsx, wsy, s;
+ if ( arw > art ) {
+ wsx = art / arw;
+ wsy = 1.0f;
+ s = (float)glConfig.vidHeight / (float)glInfo.winHeight;
+ } else {
+ wsx = 1.0f;
+ wsy = arw / art;
+ s = (float)glConfig.vidWidth / (float)glInfo.winWidth;
+ }
+ const int x0 = (glInfo.winWidth - (glInfo.winWidth * wsx)) * 0.5f;
+ const int y0 = (glInfo.winHeight - (glInfo.winHeight * wsy)) * 0.5f;
+ *x -= x0;
+ *y -= y0;
+ *x *= s;
+ *y *= s;
+ } else {
+ Q_assert( !"Invalid r_blitMode" );
+ }
+}
+
+
const refexport_t* GetRefAPI( const refimport_t* rimp )
{
static refexport_t re;
@@ -640,5 +937,7 @@ const refexport_t* GetRefAPI( const refimport_t* rimp )
re.DepthClamp = RE_IsDepthClampEnabled;
+ re.ComputeCursorPosition = RE_ComputeCursorPosition;
+
return &re;
}
diff --git a/code/renderer/tr_local.h b/code/renderer/tr_local.h
index 8d3f561..68ab40a 100644
--- a/code/renderer/tr_local.h
+++ b/code/renderer/tr_local.h
@@ -1027,8 +1027,6 @@ extern trGlobals_t tr;
#define GPUPREF_MAX 2
-extern cvar_t *r_verbose; // used for verbose debug spew
-
extern cvar_t *r_lodbias; // push/pull LOD transitions
extern cvar_t *r_lodscale;
@@ -1039,7 +1037,6 @@ extern cvar_t *r_dynamiclight; // dynamic lights enabled/disabled
extern cvar_t *r_norefresh; // bypasses the ref rendering
extern cvar_t *r_drawentities; // disable/enable entity rendering
extern cvar_t *r_drawworld; // disable/enable world rendering
-extern cvar_t *r_speeds; // various levels of information display
extern cvar_t *r_detailTextures; // enables/disables detail texturing stages
extern cvar_t *r_novis; // disable/enable usage of PVS
extern cvar_t *r_nocull;
@@ -1062,6 +1059,7 @@ extern cvar_t *r_mapGreyscaleCTF; // how monochrome CTF map surfaces look
extern cvar_t *r_teleporterFlash; // 1 is default Q3 behavior, 0 is pure black
extern cvar_t *r_sleepThreshold; // time cushion in us for a call to Sleep(1+)
extern cvar_t *r_shadingRate; // variable-rate shading (VRS) mode
+extern cvar_t *r_guiFont; // Dear ImGui font
extern cvar_t *r_fullbright; // avoid lightmap pass
extern cvar_t *r_depthFade; // fades marked shaders based on depth
extern cvar_t *r_dither; // enables dithering
@@ -1079,7 +1077,7 @@ extern cvar_t *r_roundImagesDown;
extern cvar_t *r_colorMipLevels; // development aid to see texture mip usage
extern cvar_t *r_picmip; // controls picmip values
-extern cvar_t *r_swapInterval;
+extern cvar_t *r_vsync;
extern cvar_t *r_lego;
extern cvar_t *r_vertexLight; // vertex lighting mode for better performance
@@ -1280,7 +1278,7 @@ void Sys_V_Init();
// - resetting the proper video mode if necessary
void Sys_V_Shutdown();
-// Swaps buffers and applies r_swapInterval if the back-end can't already do it.
+// Swaps buffers and applies r_vsync if the back-end can't already do it.
void Sys_V_EndFrame();
// Used to know if we must sleep ourselves to maintain the frame-rate cap.
@@ -1628,7 +1626,7 @@ byte* R_AllocateRenderCommand( int bytes, int commandId, qbool endFrame );
void R_AddDrawSurfCmd( drawSurf_t* drawSurfs, int numDrawSurfs, int numTranspSurfs );
void RE_BeginFrame( stereoFrame_t stereoFrame );
-void RE_EndFrame( int* pcFE, int* pc2D, int* pc3D, qbool render );
+void RE_EndFrame( qbool render );
void RE_SetColor( const float* rgba );
void RE_StretchPic( float x, float y, float w, float h,
float s1, float t1, float s2, float t2, qhandle_t hShader );
diff --git a/code/renderer/tr_public.h b/code/renderer/tr_public.h
index d44a14b..3fd176d 100644
--- a/code/renderer/tr_public.h
+++ b/code/renderer/tr_public.h
@@ -146,7 +146,7 @@ typedef struct {
void (*BeginFrame)( stereoFrame_t stereoFrame );
// if the pointers are not NULL, they will be filled with stats tables
- void (*EndFrame)( int* pcFE, int* pc2D, int* pc3D, qbool render );
+ void (*EndFrame)( qbool render );
int (*MarkFragments)( int numPoints, const vec3_t *points, const vec3_t projection,
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer );
@@ -168,6 +168,9 @@ typedef struct {
// is depth clamping enabled?
qbool (*DepthClamp)();
+
+ // transforms window (client rect) coordinates into render target coordinates
+ void (*ComputeCursorPosition)( int* x, int* y );
} refexport_t;
//
diff --git a/code/win32/win_glimp.cpp b/code/win32/win_glimp.cpp
index a117ee8..c8ebb5f 100644
--- a/code/win32/win_glimp.cpp
+++ b/code/win32/win_glimp.cpp
@@ -358,7 +358,7 @@ void Sys_V_Shutdown()
qbool Sys_V_IsVSynced()
{
// with Direct3D 12, our swap interval is (normally) respected
- return r_swapInterval->integer != 0;
+ return r_vsync->integer != 0;
}
diff --git a/makefiles/bsd_gmake/cnq3-server.make b/makefiles/bsd_gmake/cnq3-server.make
index 217a3ef..04c4151 100644
--- a/makefiles/bsd_gmake/cnq3-server.make
+++ b/makefiles/bsd_gmake/cnq3-server.make
@@ -73,15 +73,6 @@ all: prebuild prelink $(TARGET)
endif
OBJECTS := \
- $(OBJDIR)/imgui.o \
- $(OBJDIR)/imgui_demo.o \
- $(OBJDIR)/imgui_draw.o \
- $(OBJDIR)/imgui_tables.o \
- $(OBJDIR)/imgui_widgets.o \
- $(OBJDIR)/example_implot.o \
- $(OBJDIR)/implot.o \
- $(OBJDIR)/implot_demo.o \
- $(OBJDIR)/implot_items.o \
$(OBJDIR)/linux_main.o \
$(OBJDIR)/linux_shared.o \
$(OBJDIR)/linux_signals.o \
@@ -177,33 +168,6 @@ else
$(OBJECTS): | $(OBJDIR)
endif
-$(OBJDIR)/imgui.o: ../../code/imgui/imgui.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_demo.o: ../../code/imgui/imgui_demo.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_draw.o: ../../code/imgui/imgui_draw.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_tables.o: ../../code/imgui/imgui_tables.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_widgets.o: ../../code/imgui/imgui_widgets.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/example_implot.o: ../../code/implot/example_implot.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/implot.o: ../../code/implot/implot.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/implot_demo.o: ../../code/implot/implot_demo.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/implot_items.o: ../../code/implot/implot_items.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/linux_main.o: ../../code/linux/linux_main.cpp
@echo $(notdir $<)
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
diff --git a/makefiles/linux_gmake/cnq3-server.make b/makefiles/linux_gmake/cnq3-server.make
index e5a759e..4636c1b 100644
--- a/makefiles/linux_gmake/cnq3-server.make
+++ b/makefiles/linux_gmake/cnq3-server.make
@@ -73,15 +73,6 @@ all: prebuild prelink $(TARGET)
endif
OBJECTS := \
- $(OBJDIR)/imgui.o \
- $(OBJDIR)/imgui_demo.o \
- $(OBJDIR)/imgui_draw.o \
- $(OBJDIR)/imgui_tables.o \
- $(OBJDIR)/imgui_widgets.o \
- $(OBJDIR)/example_implot.o \
- $(OBJDIR)/implot.o \
- $(OBJDIR)/implot_demo.o \
- $(OBJDIR)/implot_items.o \
$(OBJDIR)/linux_main.o \
$(OBJDIR)/linux_shared.o \
$(OBJDIR)/linux_signals.o \
@@ -177,33 +168,6 @@ else
$(OBJECTS): | $(OBJDIR)
endif
-$(OBJDIR)/imgui.o: ../../code/imgui/imgui.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_demo.o: ../../code/imgui/imgui_demo.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_draw.o: ../../code/imgui/imgui_draw.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_tables.o: ../../code/imgui/imgui_tables.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/imgui_widgets.o: ../../code/imgui/imgui_widgets.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/example_implot.o: ../../code/implot/example_implot.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/implot.o: ../../code/implot/implot.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/implot_demo.o: ../../code/implot/implot_demo.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
-$(OBJDIR)/implot_items.o: ../../code/implot/implot_items.cpp
- @echo $(notdir $<)
- $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/linux_main.o: ../../code/linux/linux_main.cpp
@echo $(notdir $<)
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
diff --git a/makefiles/premake5.lua b/makefiles/premake5.lua
index 32c3807..f7b6d35 100644
--- a/makefiles/premake5.lua
+++ b/makefiles/premake5.lua
@@ -431,8 +431,6 @@ local function ApplyExeProjectSettings(exeName, server)
AddHeaders("cgame")
AddHeaders("game")
AddHeaders("ui")
- AddSourcesAndHeaders("imgui")
- AddSourcesAndHeaders("implot")
links { "botlib" }
@@ -440,6 +438,8 @@ local function ApplyExeProjectSettings(exeName, server)
AddSourcesFromArray(".", server_sources)
else
AddSourcesFromArray(".", client_sources)
+ AddSourcesAndHeaders("imgui")
+ AddSourcesAndHeaders("implot")
AddHeaders("renderer")
links { "renderer", "libjpeg-turbo" }
end
diff --git a/makefiles/windows_vs2019/cnq3-server.vcxproj b/makefiles/windows_vs2019/cnq3-server.vcxproj
index ca09443..b48ae8b 100644
--- a/makefiles/windows_vs2019/cnq3-server.vcxproj
+++ b/makefiles/windows_vs2019/cnq3-server.vcxproj
@@ -278,15 +278,6 @@ copy "..\..\.bin\release_x32\cnq3-server-x86.pdb" "$(QUAKE3DIR)"
-
-
-
-
-
-
-
-
-
@@ -315,15 +306,6 @@ copy "..\..\.bin\release_x32\cnq3-server-x86.pdb" "$(QUAKE3DIR)"
-
-
-
-
-
-
-
-
-
diff --git a/makefiles/windows_vs2019/cnq3-server.vcxproj.filters b/makefiles/windows_vs2019/cnq3-server.vcxproj.filters
index ca9d81b..0b2e311 100644
--- a/makefiles/windows_vs2019/cnq3-server.vcxproj.filters
+++ b/makefiles/windows_vs2019/cnq3-server.vcxproj.filters
@@ -7,12 +7,6 @@
{8461ABF6-7003-D6CC-59BE-E92045FF5C1D}
-
- {0098A80F-6CAC-D0C0-352E-7420A101CDF1}
-
-
- {5A62C004-4604-EBDA-2FBF-FE2E1B00722B}
-
{7F6839ED-EB47-B888-F45F-435F60BE1EEA}
@@ -147,33 +141,6 @@
client
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- implot
-
-
- implot
-
qcommon
@@ -254,33 +221,6 @@
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- implot
-
-
- implot
-
-
- implot
-
-
- implot
-
qcommon
diff --git a/makefiles/windows_vs2019/cnq3.vcxproj b/makefiles/windows_vs2019/cnq3.vcxproj
index 518bbef..df46305 100644
--- a/makefiles/windows_vs2019/cnq3.vcxproj
+++ b/makefiles/windows_vs2019/cnq3.vcxproj
@@ -283,6 +283,7 @@ copy "..\..\.bin\release_x32\cnq3-x86.pdb" "$(QUAKE3DIR)"
+
diff --git a/makefiles/windows_vs2019/cnq3.vcxproj.filters b/makefiles/windows_vs2019/cnq3.vcxproj.filters
index 8d88a8e..164b443 100644
--- a/makefiles/windows_vs2019/cnq3.vcxproj.filters
+++ b/makefiles/windows_vs2019/cnq3.vcxproj.filters
@@ -153,6 +153,9 @@
imgui
+
+ imgui
+
imgui
diff --git a/makefiles/windows_vs2022/botlib.vcxproj.user b/makefiles/windows_vs2022/botlib.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/makefiles/windows_vs2022/botlib.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/makefiles/windows_vs2022/cnq3-server.vcxproj b/makefiles/windows_vs2022/cnq3-server.vcxproj
index 017e417..44c423d 100644
--- a/makefiles/windows_vs2022/cnq3-server.vcxproj
+++ b/makefiles/windows_vs2022/cnq3-server.vcxproj
@@ -282,15 +282,6 @@ copy "..\..\.bin\release_x32\cnq3-server-x86.pdb" "$(QUAKE3DIR)"
-
-
-
-
-
-
-
-
-
@@ -319,15 +310,6 @@ copy "..\..\.bin\release_x32\cnq3-server-x86.pdb" "$(QUAKE3DIR)"
-
-
-
-
-
-
-
-
-
diff --git a/makefiles/windows_vs2022/cnq3-server.vcxproj.filters b/makefiles/windows_vs2022/cnq3-server.vcxproj.filters
index ca9d81b..0b2e311 100644
--- a/makefiles/windows_vs2022/cnq3-server.vcxproj.filters
+++ b/makefiles/windows_vs2022/cnq3-server.vcxproj.filters
@@ -7,12 +7,6 @@
{8461ABF6-7003-D6CC-59BE-E92045FF5C1D}
-
- {0098A80F-6CAC-D0C0-352E-7420A101CDF1}
-
-
- {5A62C004-4604-EBDA-2FBF-FE2E1B00722B}
-
{7F6839ED-EB47-B888-F45F-435F60BE1EEA}
@@ -147,33 +141,6 @@
client
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- implot
-
-
- implot
-
qcommon
@@ -254,33 +221,6 @@
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- imgui
-
-
- implot
-
-
- implot
-
-
- implot
-
-
- implot
-
qcommon
diff --git a/makefiles/windows_vs2022/cnq3.vcxproj b/makefiles/windows_vs2022/cnq3.vcxproj
index 36c1058..d6dfa82 100644
--- a/makefiles/windows_vs2022/cnq3.vcxproj
+++ b/makefiles/windows_vs2022/cnq3.vcxproj
@@ -287,6 +287,7 @@ copy "..\..\.bin\release_x32\cnq3-x86.pdb" "$(QUAKE3DIR)"
+
diff --git a/makefiles/windows_vs2022/cnq3.vcxproj.filters b/makefiles/windows_vs2022/cnq3.vcxproj.filters
index 8d88a8e..164b443 100644
--- a/makefiles/windows_vs2022/cnq3.vcxproj.filters
+++ b/makefiles/windows_vs2022/cnq3.vcxproj.filters
@@ -153,6 +153,9 @@
imgui
+
+ imgui
+
imgui