From c296409d4cf59236f634a3b83bf64ff089bf1220 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Wed, 12 Feb 2025 21:55:06 +0000 Subject: [PATCH 01/10] experiments --- mp/src/game/client/neo/ui/neo_root.cpp | 7 ++++--- mp/src/game/client/neo/ui/neo_ui.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mp/src/game/client/neo/ui/neo_root.cpp b/mp/src/game/client/neo/ui/neo_root.cpp index 7007da334..357e8cefa 100644 --- a/mp/src/game/client/neo/ui/neo_root.cpp +++ b/mp/src/game/client/neo/ui/neo_root.cpp @@ -525,12 +525,12 @@ void CNeoRoot::OnMainLoop(const NeoUI::Mode eMode) void CNeoRoot::MainLoopRoot(const MainLoopParam param) { - const int yTopPos = param.tall / 2 - ((g_uiCtx.iRowTall * BTNS_TOTAL) / 2); + const int yTopPos = 0;//param.tall / 2 - ((g_uiCtx.iRowTall * BTNS_TOTAL) / 2); g_uiCtx.dPanel.wide = m_iTitleWidth + (2 * g_uiCtx.iMarginX); g_uiCtx.dPanel.tall = param.tall - yTopPos; g_uiCtx.dPanel.x = (param.wide / 4) - (g_uiCtx.dPanel.wide / 2); g_uiCtx.dPanel.y = yTopPos; - g_uiCtx.bgColor = COLOR_TRANSPARENT; + g_uiCtx.bgColor = COLOR_NEOPANELSELECTBG; NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxRoot"); NeoUI::BeginSection(true); @@ -569,8 +569,9 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) } } NeoUI::EndSection(); + g_uiCtx.bgColor = COLOR_TRANSPARENT; - const int iBtnPlaceXMid = (param.wide / 4); + const int iBtnPlaceXMid = (param.wide / 5); const int iBtnWide = m_iTitleWidth + (2 * g_uiCtx.iMarginX); const int iRightXPos = iBtnPlaceXMid + (iBtnWide / 2) + g_uiCtx.iMarginX; int iRightSideYStart = yTopPos; diff --git a/mp/src/game/client/neo/ui/neo_ui.h b/mp/src/game/client/neo/ui/neo_ui.h index 9ab077338..08bd51b28 100644 --- a/mp/src/game/client/neo/ui/neo_ui.h +++ b/mp/src/game/client/neo/ui/neo_ui.h @@ -181,8 +181,8 @@ struct Context }; #define COLOR_NEOPANELNORMALBG Color(40, 40, 40, 255) -#define COLOR_NEOPANELSELECTBG Color(40, 10, 10, 255) -#define COLOR_NEOPANELACCENTBG Color(10, 10, 10, 255) +#define COLOR_NEOPANELSELECTBG Color(0, 0, 0, 100) +#define COLOR_NEOPANELACCENTBG Color(0, 0, 0, 0) #define COLOR_NEOPANELTEXTNORMAL Color(200, 200, 200, 255) #define COLOR_NEOPANELTEXTBRIGHT Color(255, 255, 255, 255) #define COLOR_NEOPANELPOPUPBG Color(10, 10, 10, 170) From baec9fe8e05a5033f97d92e75ce93932c0dc34e6 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 13:13:36 +0000 Subject: [PATCH 02/10] wip --- mp/game/neo/resource/ClientScheme.res | 27 +++++++++++++++++++-- mp/game/neo/resource/neotokyo_press_n.ttf | Bin 16944 -> 17348 bytes mp/src/game/client/neo/ui/neo_loading.cpp | 2 +- mp/src/game/client/neo/ui/neo_root.cpp | 28 +++++++++++++++------- mp/src/game/client/neo/ui/neo_ui.h | 5 ++-- 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/mp/game/neo/resource/ClientScheme.res b/mp/game/neo/resource/ClientScheme.res index 65b09966c..21d0c1d9f 100644 --- a/mp/game/neo/resource/ClientScheme.res +++ b/mp/game/neo/resource/ClientScheme.res @@ -679,7 +679,7 @@ Scheme { "1" { - "name" "neotokyo_press_N" // CSlogo.ttf + "name" "neotokyo_press_N" // neotokyo_press_n "tall" "42" [$WINDOWS] "tall" "72" [$LINUX] "weight" "0" @@ -688,7 +688,7 @@ Scheme } "2" { - "name" "neotokyo_press_N" // CSlogo.ttf + "name" "neotokyo_press_N" // neotokyo_press_n "tall" "46" [$WINDOWS] "tall" "76" [$LINUX] "weight" "0" @@ -696,6 +696,29 @@ Scheme "antialias" "1" } } + + ClientTitleFontSmall + { + "1" + { + "name" "neotokyo_press_N" // neotokyo_press_n + "tall" "30" [$WINDOWS] + "tall" "72" [$LINUX] + "weight" "0" + "additive" "0" + "antialias" "1" + } + "2" + { + "name" "neotokyo_press_N" // neotokyo_press_n + "tall" "34" [$WINDOWS] + "tall" "76" [$LINUX] + "weight" "0" + "additive" "0" + "antialias" "1" + } + } + "BetaFont" { diff --git a/mp/game/neo/resource/neotokyo_press_n.ttf b/mp/game/neo/resource/neotokyo_press_n.ttf index 14922e3599c78f2fcc2cbb800040e792e126261b..f3c9c94305a718203b9749a3189b2aa473b9f685 100644 GIT binary patch delta 2253 zcmbVO3sh9c8UE+)WtUwR++Fs;PC*_kVg=>7plejD3M=w3@(@WxR(v1@-QYIC6kSo{ zt5lQR#uyJxEv>qto@9``-nV98XWrN$z)M z=Kue>^UweNb7$tZ?j&8ii4zC_1j06uz>a_1wpu&fgYziQ!1p6I*s9lDuL^w&z;YWvnq}X($zj{rRR=IH1p`{-BZmab-+eW5 z<%Gw+f&hOU2GF(Hr4rj4ed+CXuaz$?3|FP0?hlM;#s>$<=J2^N-+#z!Z7~;y`&^Cn zjn$(*%P2R8gfeUr_awOz9}oVLd$8U0} zhAU>)XRZ@E+2_4hv@4i+@#Kn9sNcSG z*M9DmSAYAv-ydoEBQ@;EpNC_o;}m{=7-f~wlyDZYW(@Sfv48Oj+aI@ z+`Ls@^U2U4+^Bd4{&2c(W#uq@_UZcCKFOACF9KY=)N|#7?o;qKT>IOf|ML0mh^vmv zz2Mxvb zJ0l1A)AErYj5`XcB1uuHI5>_IiW7?Kiu;QD0Z{?D0nZ{12D}~c*%*`>gjHFj-0xJj z`fx9>GAJ%6J*YkC-xIbWnkJl5?-RY)ec`yKZ2lPG(V&!NP!*J9+e zDd{b_PP*v@n}z8prW4{wSqPl5eUMK88|KN+mORd*ZBvmY;@F@+IYyO8&{`QUYI6YUXbJ zu%0 zo1~b=*@cPOlZj-N|1*0;bWJQui;8#*WY0p^p2;PVcGk{crFnv+6BuXc8QLCcU zl9>U^ETzMjaaHeH7jx6$ZN_EULbfyqa<$=ki+Nz#P8^CiVzlY|tjs=sDnF*-`^+3; z(~InwGD^Me^$sTAX!P#lcQm^-5qZWb1TP4}P)# zx!$>Z!xus(SYZ)l!D2jSb08P;ULL(f9-@r>GfG8nbhQA8-inJ8&*u0g=dR$Eg bzqD)w!HY`N#vURzL;aT%#rC^Pyxsm^-IH@e delta 1787 zcmbtUYfuwc6h3!1$rAF~JU2WlpduZR;ZXvXv04NHk(Ur6BBBvNqy%uJ1*=YYr1)r& z>RM~nRzyXmR8s< zOoP7ATyV4%fV&8Q$XKdhQE0W|l_2aHjyo*PTbbQVwzmWDcLMme%Teggp6kXMkYC*K)44nUp5+8u+wq!9jq7R;yM z``z>PhO9ezt|tNBUIf64DJ)n~bar1%4Z!q6IH8&L&EXAp)rD#nN~Zn}0tfsUK-Hzv~iZskdaLxX~flcL2gB;|o7TO|!&9xI?d{{)i^U&A!yD*sF2at_-u&kSjr! zu<7WEpDz@XBQW%{r@g6;F+&Y47C;1d}oD6Zy`kXjpeU7ybj*E4~>_Em6 z-Z+2@VK>)T$>XAtcIFBkG!@7E!5uF^v+KATww3Gen`v#fW?Ii#s{uxbU)BKhec87K zkN&+EdQai|q32}Jt{#((0b(cf0*uYJT0kqb!zH^4a2c*Z2j*Ad8eGTo4Y&!n#$vbO zXSieMzd-Mp)(8EV4ZuCS-!-Nd!{8XZ50Bun-2n0Ib+HGKtxyEp%}X}opEN3ZR?O_! zxcG#`IZ4Ud6y4m^d1>?07i274qzBVSYu9hux^s6;?cP26_8&Y@|MfSA4j(yc{`T1M z@4i2A^3;vO%q2OuKG>C?+f%d*D!1KVKJ+mA{oa9oc<|nbP}gK!Y#4-J`|?)ZCQBU$ zupLyGF@l%I%jcPR7pchqg(NDM+Df%h-TX=XB>slK(Zsi*&rxVcx#JUoLNIjt>DMs6rvIL` z(Emga{hO4K(o%0}nzU3}D{YrPlMynpY?5r6OeZUq)yrNRXFiQ<6k1k|heoi3&a~N_8|$p0_b#mbi?ZuNBieS|p)U72+(BNHW@3 zp))-8@nMU-y}|6G;t{Ojjc7JNokleRmpsGiV?)*BoRA*vJ|Y?&t+J$_a3<&lzLm~r zT~BYt(dBBjxnF&eVAqUGH4@ex_!M_?t3eF-@T1_6U`hE!2JLK5%q&3t-SR!~)CDX$hXD3?LbW{~d z?qitku9ew6mZ3eH_Tp}X+X}gvTLx-8d$6=yJo}Z~e)B<>^N8(qk5i5S!D-@{K#7xi z%U#YWDGx6Vd(3UT!esGWQR3{JQC2ki)X9m^pf&Yi&i6=gGCvH>v0l;Jc`3l=yl(j}QGWu~Yx$G_ diff --git a/mp/src/game/client/neo/ui/neo_loading.cpp b/mp/src/game/client/neo/ui/neo_loading.cpp index 7377e70eb..98c043f35 100644 --- a/mp/src/game/client/neo/ui/neo_loading.cpp +++ b/mp/src/game/client/neo/ui/neo_loading.cpp @@ -44,7 +44,7 @@ void CNeoLoading::ApplySchemeSettings(vgui::IScheme *pScheme) SetBgColor(COLOR_TRANSPARENT); static constexpr const char *FONT_NAMES[NeoUI::FONT__TOTAL] = { - "NeoUINormal", "NHudOCR", "NHudOCRSmallNoAdditive", "ClientTitleFont", + "NeoUINormal", "NHudOCR", "NHudOCRSmallNoAdditive", "ClientTitleFont", "ClientTitleFontSmall", "NeoUILarge" }; for (int i = 0; i < NeoUI::FONT__TOTAL; ++i) diff --git a/mp/src/game/client/neo/ui/neo_root.cpp b/mp/src/game/client/neo/ui/neo_root.cpp index 357e8cefa..8427643d6 100644 --- a/mp/src/game/client/neo/ui/neo_root.cpp +++ b/mp/src/game/client/neo/ui/neo_root.cpp @@ -59,7 +59,8 @@ namespace { int g_iAvatar = 64; int g_iRootSubPanelWide = 600; -constexpr wchar_t WSZ_GAME_TITLE[] = L"neatbkyoc ue"; +constexpr wchar_t WSZ_GAME_TITLE1[] = L"neAtBkyoC"; +constexpr wchar_t WSZ_GAME_TITLE2[] = L";rebuild"; #define SZ_WEBSITE "https://neotokyorebuild.github.io" ConCommand neo_toggleconsole("neo_toggleconsole", NeoToggleconsole); @@ -294,7 +295,7 @@ void CNeoRoot::UpdateControls() { auto hdlFont = g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl; surface()->DrawSetTextFont(hdlFont); - surface()->GetTextSize(hdlFont, WSZ_GAME_TITLE, m_iTitleWidth, m_iTitleHeight); + surface()->GetTextSize(hdlFont, WSZ_GAME_TITLE1, m_iTitleWidth, m_iTitleHeight); } g_uiCtx.iActiveDirection = 0; g_uiCtx.iActive = NeoUI::FOCUSOFF_NUM; @@ -334,7 +335,7 @@ void CNeoRoot::ApplySchemeSettings(IScheme *pScheme) SetBgColor(COLOR_TRANSPARENT); static constexpr const char *FONT_NAMES[NeoUI::FONT__TOTAL] = { - "NeoUINormal", "NHudOCR", "NHudOCRSmallNoAdditive", "ClientTitleFont", + "NeoUINormal", "NHudOCR", "NHudOCRSmallNoAdditive", "ClientTitleFont", "ClientTitleFontSmall", "NeoUILarge" }; for (int i = 0; i < NeoUI::FONT__TOTAL; ++i) @@ -525,11 +526,12 @@ void CNeoRoot::OnMainLoop(const NeoUI::Mode eMode) void CNeoRoot::MainLoopRoot(const MainLoopParam param) { - const int yTopPos = 0;//param.tall / 2 - ((g_uiCtx.iRowTall * BTNS_TOTAL) / 2); - g_uiCtx.dPanel.wide = m_iTitleWidth + (2 * g_uiCtx.iMarginX); + const int yTopPos = 0; + g_uiCtx.dPanel.wide = (m_iTitleWidth * 0.8) + (2 * g_uiCtx.iMarginX); g_uiCtx.dPanel.tall = param.tall - yTopPos; g_uiCtx.dPanel.x = (param.wide / 4) - (g_uiCtx.dPanel.wide / 2); g_uiCtx.dPanel.y = yTopPos; + g_uiCtx.iYOffset[0] = -8; g_uiCtx.bgColor = COLOR_NEOPANELSELECTBG; NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxRoot"); @@ -571,7 +573,7 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) NeoUI::EndSection(); g_uiCtx.bgColor = COLOR_TRANSPARENT; - const int iBtnPlaceXMid = (param.wide / 5); + const int iBtnPlaceXMid = (param.wide / 4); const int iBtnWide = m_iTitleWidth + (2 * g_uiCtx.iMarginX); const int iRightXPos = iBtnPlaceXMid + (iBtnWide / 2) + g_uiCtx.iMarginX; int iRightSideYStart = yTopPos; @@ -581,10 +583,17 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) // Draw title surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl); surface()->DrawSetTextColor(COLOR_NEOTITLE); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth / 2), yTopPos - m_iTitleHeight); - surface()->DrawPrintText(WSZ_GAME_TITLE, SZWSZ_LEN(WSZ_GAME_TITLE)); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), yTopPos + m_iTitleHeight); + surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); + + int iTitleNWidth, iTitleNHeight; + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, L"n", iTitleNWidth, iTitleNHeight); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), yTopPos + m_iTitleHeight + (iTitleNHeight * 0.7)); + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); + surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); +#if (0) surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); ISteamUser *steamUser = steamapicontext->SteamUser(); ISteamFriends *steamFriends = steamapicontext->SteamFriends(); @@ -667,8 +676,10 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) const int iTextTotalTall = iMainTextHeight + iStatusTall; iRightSideYStart += (g_uiCtx.iMarginX * 2) + ((iTextTotalTall > g_iAvatar) ? iTextTotalTall : g_iAvatar); } +#endif (0) } +#if (0) g_uiCtx.dPanel.x = iRightXPos; g_uiCtx.dPanel.y = iRightSideYStart; if (IsInGame()) @@ -720,6 +731,7 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) } } NeoUI::EndSection(); +#endif (0) NeoUI::EndContext(); } diff --git a/mp/src/game/client/neo/ui/neo_ui.h b/mp/src/game/client/neo/ui/neo_ui.h index 08bd51b28..412303c39 100644 --- a/mp/src/game/client/neo/ui/neo_ui.h +++ b/mp/src/game/client/neo/ui/neo_ui.h @@ -102,6 +102,7 @@ enum EFont FONT_NTHEADING, FONT_NTHORIZSIDES, FONT_LOGO, + FONT_LOGOSMALL, FONT_NTLARGE, FONT__TOTAL, @@ -183,11 +184,11 @@ struct Context #define COLOR_NEOPANELNORMALBG Color(40, 40, 40, 255) #define COLOR_NEOPANELSELECTBG Color(0, 0, 0, 100) #define COLOR_NEOPANELACCENTBG Color(0, 0, 0, 0) -#define COLOR_NEOPANELTEXTNORMAL Color(200, 200, 200, 255) +#define COLOR_NEOPANELTEXTNORMAL Color(255, 255, 255, 255)//Color(200, 200, 200, 255) #define COLOR_NEOPANELTEXTBRIGHT Color(255, 255, 255, 255) #define COLOR_NEOPANELPOPUPBG Color(10, 10, 10, 170) #define COLOR_NEOPANELFRAMEBG Color(40, 40, 40, 150) -#define COLOR_NEOTITLE Color(200, 200, 200, 255) +#define COLOR_NEOTITLE Color(255, 255, 255, 255)//Color(200, 200, 200, 255) #define COLOR_NEOPANELBAR Color(20, 20, 20, 255) #define COLOR_NEOPANELMICTEST Color(30, 90, 30, 255) From 10b2479f1fbbdef3f3c91674409693862a725f97 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 13:33:58 +0000 Subject: [PATCH 03/10] beign centering on rebuild --- mp/game/neo/resource/ClientScheme.res | 8 ++++---- mp/src/game/client/neo/ui/neo_root.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mp/game/neo/resource/ClientScheme.res b/mp/game/neo/resource/ClientScheme.res index 21d0c1d9f..721c3dee2 100644 --- a/mp/game/neo/resource/ClientScheme.res +++ b/mp/game/neo/resource/ClientScheme.res @@ -680,7 +680,7 @@ Scheme "1" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "42" [$WINDOWS] + "tall" "54" [$WINDOWS] "tall" "72" [$LINUX] "weight" "0" "additive" "0" @@ -689,7 +689,7 @@ Scheme "2" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "46" [$WINDOWS] + "tall" "58" [$WINDOWS] "tall" "76" [$LINUX] "weight" "0" "additive" "0" @@ -702,7 +702,7 @@ Scheme "1" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "30" [$WINDOWS] + "tall" "42" [$WINDOWS] "tall" "72" [$LINUX] "weight" "0" "additive" "0" @@ -711,7 +711,7 @@ Scheme "2" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "34" [$WINDOWS] + "tall" "46" [$WINDOWS] "tall" "76" [$LINUX] "weight" "0" "additive" "0" diff --git a/mp/src/game/client/neo/ui/neo_root.cpp b/mp/src/game/client/neo/ui/neo_root.cpp index 8427643d6..047bcc89d 100644 --- a/mp/src/game/client/neo/ui/neo_root.cpp +++ b/mp/src/game/client/neo/ui/neo_root.cpp @@ -293,9 +293,9 @@ void CNeoRoot::UpdateControls() { if (m_state == STATE_ROOT) { - auto hdlFont = g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl; + auto hdlFont = g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl; surface()->DrawSetTextFont(hdlFont); - surface()->GetTextSize(hdlFont, WSZ_GAME_TITLE1, m_iTitleWidth, m_iTitleHeight); + surface()->GetTextSize(hdlFont, WSZ_GAME_TITLE2, m_iTitleWidth, m_iTitleHeight); } g_uiCtx.iActiveDirection = 0; g_uiCtx.iActive = NeoUI::FOCUSOFF_NUM; From c4672f3576422bb0ab20d0eecf59e1c99f7236df Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 16:55:14 +0000 Subject: [PATCH 04/10] yeet --- mp/game/neo/resource/ClientScheme.res | 39 +- .../neo_root.cpp | 1597 +++++++++++++++++ mp/src/game/client/neo/ui/neo_root.cpp | 22 +- mp/src/game/client/neo/ui/neo_ui.h | 2 +- 4 files changed, 1641 insertions(+), 19 deletions(-) create mode 100644 mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp diff --git a/mp/game/neo/resource/ClientScheme.res b/mp/game/neo/resource/ClientScheme.res index 721c3dee2..909a7e60c 100644 --- a/mp/game/neo/resource/ClientScheme.res +++ b/mp/game/neo/resource/ClientScheme.res @@ -680,21 +680,33 @@ Scheme "1" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "54" [$WINDOWS] - "tall" "72" [$LINUX] + "tall" "60" "weight" "0" "additive" "0" "antialias" "1" + "custom" "1" + "yres" "1 633" } "2" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "58" [$WINDOWS] - "tall" "76" [$LINUX] + "tall" "100" + "weight" "0" + "additive" "0" + "antialias" "1" + "custom" "1" + "yres" "634 1080" + } + "3" + { + "name" "neotokyo_press_N" // neotokyo_press_n + "tall" "127" "weight" "0" "additive" "0" "antialias" "1" + "yres" "1080 10000" } + // It seems that 127 is the largest a font can be, so we can't make the title any bigger than this } ClientTitleFontSmall @@ -702,20 +714,31 @@ Scheme "1" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "42" [$WINDOWS] - "tall" "72" [$LINUX] + "tall" "42" "weight" "0" "additive" "0" "antialias" "1" + "custom" "1" + "yres" "1 633" } "2" { "name" "neotokyo_press_N" // neotokyo_press_n - "tall" "46" [$WINDOWS] - "tall" "76" [$LINUX] + "tall" "72" + "weight" "0" + "additive" "0" + "antialias" "1" + "custom" "1" + "yres" "634 1080" + } + "3" + { + "name" "neotokyo_press_N" // neotokyo_press_n + "tall" "92" "weight" "0" "additive" "0" "antialias" "1" + "yres" "1080 10000" } } diff --git a/mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp b/mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp new file mode 100644 index 000000000..b6141a312 --- /dev/null +++ b/mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp @@ -0,0 +1,1597 @@ +#include "cbase.h" +#include "neo_root.h" +#include "IOverrideInterface.h" + +#include "vgui/ILocalize.h" +#include "vgui/IPanel.h" +#include "vgui/ISurface.h" +#include "vgui/IVGui.h" +#include "ienginevgui.h" +#include +#include "filesystem.h" +#include "neo_version_info.h" +#include "cdll_client_int.h" +#include +#include +#include +#include +#include +#include +#include "tier1/interface.h" +#include +#include "ui/neo_loading.h" +#include "neo_gamerules.h" +#include "neo_misc.h" + +#include +#include + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// TODO: Gamepad +// Gamepad enable: joystick 0/1 +// Reverse up-down axis: joy_inverty 0/1 +// Swap sticks on dual-stick controllers: joy_movement_stick 0/1 +// Horizontal sens: joy_yawsensitivity: -0.5 to -7.0 +// Vertical sens: joy_pitchsensitivity: 0.5 to 7.0 + +using namespace vgui; + +// See interface.h/.cpp for specifics: basically this ensures that we actually Sys_UnloadModule +// the dll and that we don't call Sys_LoadModule over and over again. +static CDllDemandLoader g_GameUIDLL("GameUI"); + +extern ConVar neo_name; +extern ConVar cl_onlysteamnick; +extern ConVar neo_cl_streamermode; +extern ConVar neo_clantag; + +CNeoRoot *g_pNeoRoot = nullptr; +void NeoToggleconsole(); +extern CNeoLoading *g_pNeoLoading; +inline NeoUI::Context g_uiCtx; +inline ConVar neo_cl_toggleconsole("neo_cl_toggleconsole", "0", FCVAR_ARCHIVE, + "If the console can be toggled with the ` keybind or not.", true, 0.0f, true, 1.0f); +inline int g_iRowsInScreen; + +namespace { + +int g_iAvatar = 64; +int g_iRootSubPanelWide = 600; +constexpr wchar_t WSZ_GAME_TITLE1[] = L"neAtBkyoC"; +constexpr wchar_t WSZ_GAME_TITLE2[] = L";rebuild"; +#define SZ_WEBSITE "https://neotokyorebuild.github.io" + +ConCommand neo_toggleconsole("neo_toggleconsole", NeoToggleconsole); + +struct YMD +{ + YMD(const struct tm tm) + : year(tm.tm_year + 1900) + , month(tm.tm_mon + 1) + , day(tm.tm_mday) + { + } + + bool operator==(const YMD &other) const + { + return year == other.year && month == other.month && day == other.day; + } + bool operator!=(const YMD &other) const + { + return !(*this == other); + } + + int year; + int month; + int day; +}; + +} + +void OverrideGameUI() +{ + if (!OverrideUI->GetPanel()) + { + OverrideUI->Create(0U); + } + + if (g_pNeoRoot->GetGameUI()) + { + g_pNeoRoot->GetGameUI()->SetMainMenuOverride(g_pNeoRoot->GetVPanel()); + } +} + +CNeoRootInput::CNeoRootInput(CNeoRoot *rootPanel) + : Panel(rootPanel, "NeoRootPanelInput") + , m_pNeoRoot(rootPanel) +{ + MakePopup(true); + SetKeyBoardInputEnabled(true); + SetMouseInputEnabled(false); + SetVisible(true); + SetEnabled(true); + PerformLayout(); +} + +void CNeoRootInput::PerformLayout() +{ + SetPos(0, 0); + SetSize(1, 1); + SetBgColor(COLOR_TRANSPARENT); + SetFgColor(COLOR_TRANSPARENT); +} + +void CNeoRootInput::OnKeyCodeTyped(vgui::KeyCode code) +{ + m_pNeoRoot->OnRelayedKeyCodeTyped(code); +} + +void CNeoRootInput::OnKeyTyped(wchar_t unichar) +{ + m_pNeoRoot->OnRelayedKeyTyped(unichar); +} + +void CNeoRootInput::OnThink() +{ + ButtonCode_t code; + if (engine->CheckDoneKeyTrapping(code)) + { + if (code != KEY_ESCAPE) + { + if (code != KEY_DELETE) + { + // The keybind system used requires 1:1 so unbind any duplicates + for (auto &bind : m_pNeoRoot->m_ns.keys.vBinds) + { + if (bind.bcNext == code) + { + bind.bcNext = BUTTON_CODE_NONE; + } + } + } + m_pNeoRoot->m_ns.keys.vBinds[m_pNeoRoot->m_iBindingIdx].bcNext = + (code == KEY_DELETE) ? BUTTON_CODE_NONE : code; + m_pNeoRoot->m_ns.bModified = true; + } + m_pNeoRoot->m_wszBindingText[0] = '\0'; + m_pNeoRoot->m_iBindingIdx = -1; + m_pNeoRoot->m_state = STATE_SETTINGS; + V_memcpy(g_uiCtx.iYOffset, m_pNeoRoot->m_iSavedYOffsets, NeoUI::SIZEOF_SECTIONS); + } +} + +constexpr WidgetInfo BTNS_INFO[BTNS_TOTAL] = { + { "#GameUI_GameMenu_ResumeGame", "ResumeGame", STATE__TOTAL, FLAG_SHOWINGAME }, + { "#GameUI_GameMenu_FindServers", nullptr, STATE_SERVERBROWSER, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, + { "#GameUI_GameMenu_CreateServer", nullptr, STATE_NEWGAME, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, + { "#GameUI_GameMenu_Disconnect", "Disconnect", STATE__TOTAL, FLAG_SHOWINGAME }, + { "#GameUI_GameMenu_PlayerList", nullptr, STATE_PLAYERLIST, FLAG_SHOWINGAME }, + { "#GameUI_GameMenu_Options", nullptr, STATE_SETTINGS, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, + { "#GameUI_GameMenu_Quit", nullptr, STATE_QUIT, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, +}; + +CNeoRoot::CNeoRoot(VPANEL parent) + : EditablePanel(nullptr, "NeoRootPanel") + , m_panelCaptureInput(new CNeoRootInput(this)) +{ + SetParent(parent); + g_pNeoRoot = this; + LoadGameUI(); + SetVisible(true); + SetProportional(false); + + vgui::HScheme neoscheme = vgui::scheme()->LoadSchemeFromFileEx( + enginevgui->GetPanel(PANEL_CLIENTDLL), "resource/ClientScheme.res", "ClientScheme"); + SetScheme(neoscheme); + + for (int i = 0; i < BTNS_TOTAL; ++i) + { + const char *label = BTNS_INFO[i].label; + if (wchar_t *localizedWszStr = g_pVGuiLocalize->Find(label)) + { + V_wcsncpy(m_wszDispBtnTexts[i], localizedWszStr, sizeof(m_wszDispBtnTexts[i])); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode(label, m_wszDispBtnTexts[i], sizeof(m_wszDispBtnTexts[i])); + } + m_iWszDispBtnTextsSizes[i] = V_wcslen(m_wszDispBtnTexts[i]); + } + + NeoSettingsInit(&m_ns); + { + // Initialize map list + FileFindHandle_t findHdl; + for (const char *pszFilename = filesystem->FindFirst("maps/*.bsp", &findHdl); + pszFilename; + pszFilename = filesystem->FindNext(findHdl)) + { + // Sanity check: In-case somehow someone named a directory as *.bsp in here + if (!filesystem->FindIsDirectory(findHdl)) + { + MapInfo mapInfo; + int iSize = g_pVGuiLocalize->ConvertANSIToUnicode(pszFilename, mapInfo.wszName, sizeof(mapInfo.wszName)); + iSize -= sizeof(".bsp"); + mapInfo.wszName[iSize] = '\0'; + m_vWszMaps.AddToTail(mapInfo); + } + } + filesystem->FindClose(findHdl); + } + for (int i = 0; i < GS__TOTAL; ++i) + { + m_serverBrowser[i].m_iType = static_cast(i); + m_serverBrowser[i].m_pSortCtx = &m_sortCtx; + } + + // NEO TODO (nullsystem): What will happen in 2038? 64-bit Source 1 SDK when? Source 2 SDK when? + // We could use GCC 64-bit compiled time_t or Win32 API direct to side-step IFileSystem "long" 32-bit + // limitation for now. Although that could mess with the internal IFileSystem related API usages of time_t. + // If _FILE_OFFSET_BITS=64 and _TIME_BITS=64 is set on Linux, time_t will be 64-bit even on 32-bit executable + // + // If news.txt doesn't exists, it'll just give 1970-01-01 which will always be different to ymdNow anyway + const long lFileTime = filesystem->GetFileTime("news.txt"); + const time_t ttFileTime = lFileTime; + struct tm tmFileStruct; + const struct tm tmFile = *(Plat_localtime(&ttFileTime, &tmFileStruct)); + const YMD ymdFile{tmFile}; + + struct tm tmNowStruct; + const time_t tNow = time(nullptr); + const struct tm tmNow = *(Plat_localtime(&tNow, &tmNowStruct)); + const YMD ymdNow{tmNow}; + + // Read the cached file regardless of needing update or not + if (filesystem->FileExists("news.txt")) + { + CUtlBuffer buf(0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY); + if (filesystem->ReadFile("news.txt", nullptr, buf)) + { + ReadNewsFile(buf); + } + } + if (ymdFile != ymdNow) + { + ISteamHTTP *http = steamapicontext->SteamHTTP(); + HTTPRequestHandle httpReqHdl = http->CreateHTTPRequest(k_EHTTPMethodGET, SZ_WEBSITE "/news.txt"); + SteamAPICall_t httpReqCallback; + http->SendHTTPRequest(httpReqHdl, &httpReqCallback); + m_ccallbackHttp.Set(httpReqCallback, this, &CNeoRoot::HTTPCallbackRequest); + } + + SetKeyBoardInputEnabled(true); + SetMouseInputEnabled(true); + UpdateControls(); + ivgui()->AddTickSignal(GetVPanel(), 200); + ListenForGameEvent("server_spawn"); + ListenForGameEvent("game_newmap"); + + vgui::IScheme *pScheme = vgui::scheme()->GetIScheme(neoscheme); + ApplySchemeSettings(pScheme); +} + +CNeoRoot::~CNeoRoot() +{ + if (g_pNeoRoot->m_pFileIODialog) g_pNeoRoot->m_pFileIODialog->DeletePanel(); + m_panelCaptureInput->DeletePanel(); + if (m_avImage) delete m_avImage; + NeoSettingsDeinit(&m_ns); + + m_gameui = nullptr; + g_GameUIDLL.Unload(); +} + +IGameUI *CNeoRoot::GetGameUI() +{ + if (!m_gameui && !LoadGameUI()) return nullptr; + return m_gameui; +} + +void CNeoRoot::UpdateControls() +{ + if (m_state == STATE_ROOT) + { + auto hdlFont = g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl; + surface()->DrawSetTextFont(hdlFont); + surface()->GetTextSize(hdlFont, WSZ_GAME_TITLE2, m_iTitleWidth, m_iTitleHeight); + } + g_uiCtx.iActiveDirection = 0; + g_uiCtx.iActive = NeoUI::FOCUSOFF_NUM; + g_uiCtx.iActiveSection = -1; + V_memset(g_uiCtx.iYOffset, 0, sizeof(g_uiCtx.iYOffset)); + m_ns.bBack = false; + m_bShowBrowserLabel = false; + RequestFocus(); + m_panelCaptureInput->RequestFocus(); + InvalidateLayout(); +} + +bool CNeoRoot::LoadGameUI() +{ + if (!m_gameui) + { + CreateInterfaceFn gameUIFactory = g_GameUIDLL.GetFactory(); + if (!gameUIFactory) return false; + + m_gameui = reinterpret_cast(gameUIFactory(GAMEUI_INTERFACE_VERSION, nullptr)); + if (!m_gameui) return false; + } + return true; +} + +void CNeoRoot::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + // NEO TODO (nullsystem): If we're to provide color scheme controls: + // LoadControlSettings("resource/NeoRootScheme.res"); + + // Resize the panel to the screen size + int wide, tall; + surface()->GetScreenSize(wide, tall); + SetSize(wide, tall); + SetFgColor(COLOR_TRANSPARENT); + SetBgColor(COLOR_TRANSPARENT); + + static constexpr const char *FONT_NAMES[NeoUI::FONT__TOTAL] = { + "NeoUINormal", "NHudOCR", "NHudOCRSmallNoAdditive", "ClientTitleFont", "ClientTitleFontSmall", + "NeoUILarge" + }; + for (int i = 0; i < NeoUI::FONT__TOTAL; ++i) + { + g_uiCtx.fonts[i].hdl = pScheme->GetFont(FONT_NAMES[i], true); + } + + // In 1080p, g_uiCtx.iRowTall == 40, g_uiCtx.iMarginX = 10, g_iAvatar = 64, + // other resolution scales up/down from it + g_uiCtx.iRowTall = tall / 27; + g_iRowsInScreen = (tall * 0.85f) / g_uiCtx.iRowTall; + g_uiCtx.iMarginX = wide / 192; + g_uiCtx.iMarginY = tall / 108; + g_iAvatar = wide / 30; + const float flWide = static_cast(wide); + m_flWideAs43 = static_cast(tall) * (4.0f / 3.0f); + if (m_flWideAs43 > flWide) m_flWideAs43 = flWide; + g_iRootSubPanelWide = static_cast(m_flWideAs43 * 0.9f); + + constexpr int PARTITION = GSIW__TOTAL * 4; + const int iSubDiv = g_iRootSubPanelWide / PARTITION; + g_iGSIX[GSIW_LOCKED] = iSubDiv * 2; + g_iGSIX[GSIW_VAC] = iSubDiv * 2; + g_iGSIX[GSIW_NAME] = iSubDiv * 10; + g_iGSIX[GSIW_MAP] = iSubDiv * 5; + g_iGSIX[GSIW_PLAYERS] = iSubDiv * 3; + g_iGSIX[GSIW_PING] = iSubDiv * 2; + + UpdateControls(); +} + +void CNeoRoot::Paint() +{ + OnMainLoop(NeoUI::MODE_PAINT); +} + +void CNeoRoot::OnMousePressed(vgui::MouseCode code) +{ + g_uiCtx.eCode = code; + OnMainLoop(NeoUI::MODE_MOUSEPRESSED); +} + +void CNeoRoot::OnMouseReleased(vgui::MouseCode code) +{ + g_uiCtx.eCode = code; + OnMainLoop(NeoUI::MODE_MOUSERELEASED); +} + +void CNeoRoot::OnMouseDoublePressed(vgui::MouseCode code) +{ + g_uiCtx.eCode = code; + OnMainLoop(NeoUI::MODE_MOUSEDOUBLEPRESSED); +} + +void CNeoRoot::OnMouseWheeled(int delta) +{ + g_uiCtx.eCode = (delta > 0) ? MOUSE_WHEEL_UP : MOUSE_WHEEL_DOWN; + OnMainLoop(NeoUI::MODE_MOUSEWHEELED); +} + +void CNeoRoot::OnCursorMoved(int x, int y) +{ + g_uiCtx.iMouseAbsX = x; + g_uiCtx.iMouseAbsY = y; + OnMainLoop(NeoUI::MODE_MOUSEMOVED); +} + +void CNeoRoot::OnTick() +{ + if (m_state == STATE_SERVERBROWSER) + { + if (m_bSBFiltModified) + { + // Pass modified over to the tabs so it doesn't trigger + // the filter refresh immeditely + for (int i = 0; i < GS__TOTAL; ++i) + { + m_serverBrowser[i].m_bModified = true; + } + m_bSBFiltModified = false; + } + + auto *pSbTab = &m_serverBrowser[m_iServerBrowserTab]; + if (pSbTab->m_bModified) + { + pSbTab->UpdateFilteredList(); + pSbTab->m_bModified = false; + } + } +} + +void CNeoRoot::FireGameEvent(IGameEvent *event) +{ + const char *type = event->GetName(); + if (Q_strcmp(type, "server_spawn") == 0) + { + g_pVGuiLocalize->ConvertANSIToUnicode(event->GetString("hostname"), m_wszHostname, sizeof(m_wszHostname)); + } + else if (Q_strcmp(type, "game_newmap") == 0) + { + g_pVGuiLocalize->ConvertANSIToUnicode(event->GetString("mapname"), m_wszMap, sizeof(m_wszMap)); + } +} + +void CNeoRoot::OnRelayedKeyCodeTyped(vgui::KeyCode code) +{ + if (m_ns.keys.bcConsole <= KEY_NONE) + { + m_ns.keys.bcConsole = gameuifuncs->GetButtonCodeForBind("neo_toggleconsole"); + } + + if (code == m_ns.keys.bcConsole && code != KEY_BACKQUOTE) + { + // NEO JANK (nullsystem): Prevent toggle being handled twice causing it to not really open. + // This can happen if using the default ` due to the engine enacting this all the time, however calling + // NeoToggleconsole here is required for non-` keys that is toggled while the root panel is opened. The + // engine will call non-` keys by itself it it's in game and the root panel is not opened, or the console is + // opened which generally doesn't endup calling OnRelayedKeyCodeTyped anyway. + NeoToggleconsole(); + return; + } + g_uiCtx.eCode = code; + OnMainLoop(NeoUI::MODE_KEYPRESSED); +} + +void CNeoRoot::OnRelayedKeyTyped(wchar_t unichar) +{ + g_uiCtx.unichar = unichar; + OnMainLoop(NeoUI::MODE_KEYTYPED); +} + +void CNeoRoot::OnMainLoop(const NeoUI::Mode eMode) +{ + int wide, tall; + GetSize(wide, tall); + + const RootState ePrevState = m_state; + + if (eMode == NeoUI::MODE_PAINT) + { + // Draw version info (bottom left corner) - Always + surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); + int textWidth, textHeight; + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, BUILD_DISPLAY, textWidth, textHeight); + + surface()->DrawSetTextPos(g_uiCtx.iMarginX, tall - textHeight - g_uiCtx.iMarginY); + surface()->DrawPrintText(BUILD_DISPLAY, *BUILD_DISPLAY_SIZE); + } + + // Laading screen just overlays over the root, so don't render anything else if so + if (m_bOnLoadingScreen) + { + return; + } + + static constexpr void (CNeoRoot::*P_FN_MAIN_LOOP[STATE__TOTAL])(const MainLoopParam param) = { + &CNeoRoot::MainLoopRoot, // STATE_ROOT + &CNeoRoot::MainLoopSettings, // STATE_SETTINGS + &CNeoRoot::MainLoopNewGame, // STATE_NEWGAME + &CNeoRoot::MainLoopServerBrowser, // STATE_SERVERBROWSER + + &CNeoRoot::MainLoopMapList, // STATE_MAPLIST + &CNeoRoot::MainLoopServerDetails, // STATE_SERVERDETAILS + &CNeoRoot::MainLoopPlayerList, // STATE_PLAYERLIST + + &CNeoRoot::MainLoopPopup, // STATE_KEYCAPTURE + &CNeoRoot::MainLoopPopup, // STATE_CONFIRMSETTINGS + &CNeoRoot::MainLoopPopup, // STATE_QUIT + &CNeoRoot::MainLoopPopup, // STATE_SERVERPASSWORD + &CNeoRoot::MainLoopPopup, // STATE_SETTINGSRESETDEFAULT + }; + (this->*P_FN_MAIN_LOOP[m_state])(MainLoopParam{.eMode = eMode, .wide = wide, .tall = tall}); + + if (m_state != ePrevState) + { + if (ePrevState == STATE_SETTINGS) + { + V_memcpy(m_iSavedYOffsets, g_uiCtx.iYOffset, NeoUI::SIZEOF_SECTIONS); + } + UpdateControls(); + if (m_state == STATE_SETTINGS && ePrevState >= STATE__POPUPSTART && ePrevState < STATE__TOTAL) + { + V_memcpy(g_uiCtx.iYOffset, m_iSavedYOffsets, NeoUI::SIZEOF_SECTIONS); + } + } +} + +void CNeoRoot::MainLoopRoot(const MainLoopParam param) +{ + const int yTopPos = 0; + int iTitleNWidth, iTitleNHeight; + const int iBtnPlaceXMid = (param.wide / 6); + const int iMargin = (6 * g_uiCtx.iMarginX); + const int iMarginHalf = iMargin * 0.5; + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, L"n", iTitleNWidth, iTitleNHeight); + g_uiCtx.dPanel.wide = (m_iTitleWidth) +iMargin; + g_uiCtx.dPanel.tall = param.tall - yTopPos; + g_uiCtx.dPanel.x = iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - iMarginHalf; + g_uiCtx.dPanel.y = yTopPos; + g_uiCtx.iYOffset[0] = -8; + g_uiCtx.bgColor = COLOR_NEOPANELNORMALBG; + + NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxRoot"); + NeoUI::BeginSection(true); + { + const int iFlagToMatch = IsInGame() ? FLAG_SHOWINGAME : FLAG_SHOWINMAIN; + for (int i = 0; i < BTNS_TOTAL; ++i) + { + const auto btnInfo = BTNS_INFO[i]; + if (btnInfo.flags & iFlagToMatch) + { + const auto retBtn = NeoUI::Button(m_wszDispBtnTexts[i]); + if (retBtn.bPressed || (i == MMBTN_QUIT && !IsInGame() && NeoUI::Bind(KEY_ESCAPE))) + { + surface()->PlaySound("ui/buttonclickrelease.wav"); + if (btnInfo.gamemenucommand) + { + m_state = STATE_ROOT; + GetGameUI()->SendMainMenuCommand(btnInfo.gamemenucommand); + } + else if (btnInfo.nextState < STATE__TOTAL) + { + m_state = btnInfo.nextState; + if (m_state == STATE_SETTINGS) + { + NeoSettingsRestore(&m_ns); + } + } + } + if (retBtn.bMouseHover && i != m_iHoverBtn) + { + // Sound rollover feedback + surface()->PlaySound("ui/buttonrollover.wav"); + m_iHoverBtn = i; + } + } + } + } + NeoUI::EndSection(); + g_uiCtx.bgColor = COLOR_TRANSPARENT; + + const int iBtnWide = m_iTitleWidth + iMargin; + const int iRightXPos = iBtnPlaceXMid + (iBtnWide / 2) + iMarginHalf; + int iRightSideYStart = yTopPos; + + // Draw top steam section portion + { + // Draw title + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl); + surface()->DrawSetTextColor(COLOR_NEOTITLE); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), yTopPos + m_iTitleHeight); + surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); + + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), yTopPos + m_iTitleHeight + (iTitleNHeight * 0.7)); + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); + surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); + +#if (0) + surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); + ISteamUser *steamUser = steamapicontext->SteamUser(); + ISteamFriends *steamFriends = steamapicontext->SteamFriends(); + if (steamUser && steamFriends) + { + const int iSteamPlaceXStart = iRightXPos; + + // Draw player info (top left corner) + const CSteamID steamID = steamUser->GetSteamID(); + if (!m_avImage) + { + m_avImage = new CAvatarImage; + m_avImage->SetAvatarSteamID(steamID, k_EAvatarSize64x64); + } + m_avImage->SetPos(iSteamPlaceXStart + g_uiCtx.iMarginX, iRightSideYStart + g_uiCtx.iMarginY); + m_avImage->SetSize(g_iAvatar, g_iAvatar); + m_avImage->Paint(); + + wchar_t wszDisplayName[NEO_MAX_DISPLAYNAME]; + GetClNeoDisplayName(wszDisplayName, neo_name.GetString(), neo_clantag.GetString(), cl_onlysteamnick.GetBool()); + + const char *szNeoName = neo_name.GetString(); + const bool bUseNeoName = (szNeoName && szNeoName[0] != '\0' && !cl_onlysteamnick.GetBool()); + + int iMainTextWidth, iMainTextHeight; + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTHEADING].hdl); + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTHEADING].hdl, wszDisplayName, iMainTextWidth, iMainTextHeight); + + const int iMainTextStartPosX = g_uiCtx.iMarginX + g_iAvatar + g_uiCtx.iMarginX; + surface()->DrawSetTextPos(iSteamPlaceXStart + iMainTextStartPosX, iRightSideYStart + g_uiCtx.iMarginY); + surface()->DrawPrintText(wszDisplayName, V_wcslen(wszDisplayName)); + + if (bUseNeoName) + { + char szTextBuf[64]; + V_sprintf_safe(szTextBuf, "(Steam name: %s)", steamFriends->GetPersonaName()); + wchar_t wszTextBuf[64] = {}; + g_pVGuiLocalize->ConvertANSIToUnicode(szTextBuf, wszTextBuf, sizeof(wszTextBuf)); + + int iSteamSubTextWidth, iSteamSubTextHeight; + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, wszTextBuf, iSteamSubTextWidth, iSteamSubTextHeight); + + const int iRightOfNicknameXPos = iSteamPlaceXStart + iMainTextStartPosX + iMainTextWidth + g_uiCtx.iMarginX; + // If we have space on the right, set it, otherwise on top of nickname + if ((iRightOfNicknameXPos + iSteamSubTextWidth) < param.wide) + { + surface()->DrawSetTextPos(iRightOfNicknameXPos, iRightSideYStart + g_uiCtx.iMarginY); + } + else + { + surface()->DrawSetTextPos(iSteamPlaceXStart + iMainTextStartPosX, + iRightSideYStart - iSteamSubTextHeight); + } + surface()->DrawPrintText(wszTextBuf, V_strlen(szTextBuf)); + } + + static constexpr const wchar_t *WSZ_PERSONA_STATES[k_EPersonaStateMax] = { + L"Offline", L"Online", L"Busy", L"Away", L"Snooze", L"Trading", L"Looking to play" + }; + const auto eCurStatus = steamFriends->GetPersonaState(); + int iStatusTall = 0; + if (eCurStatus != k_EPersonaStateMax) + { + wchar_t wszStatusTotal[48]; + const int iStatusTotalSize = V_swprintf_safe(wszStatusTotal, L"%ls%ls", + WSZ_PERSONA_STATES[static_cast(eCurStatus)], + neo_cl_streamermode.GetBool() ? L" [Streamer mode on]" : L""); + const int iStatusTextStartPosY = g_uiCtx.iMarginY + iMainTextHeight + g_uiCtx.iMarginY; + + [[maybe_unused]] int iStatusWide; + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, wszStatusTotal, iStatusWide, iStatusTall); + surface()->DrawSetTextPos(iSteamPlaceXStart + iMainTextStartPosX, + iRightSideYStart + iStatusTextStartPosY); + surface()->DrawPrintText(wszStatusTotal, iStatusTotalSize); + } + + // Put the news title in either from avatar or text end Y position + const int iTextTotalTall = iMainTextHeight + iStatusTall; + iRightSideYStart += (g_uiCtx.iMarginX * 2) + ((iTextTotalTall > g_iAvatar) ? iTextTotalTall : g_iAvatar); + } +#endif (0) + } + +#if (0) + g_uiCtx.dPanel.x = iRightXPos; + g_uiCtx.dPanel.y = iRightSideYStart; + if (IsInGame()) + { + g_uiCtx.dPanel.wide = m_flWideAs43 * 0.7f; + g_uiCtx.flWgXPerc = 0.25f; + } + else + { + g_uiCtx.dPanel.wide = GetWide() - iRightXPos - (g_uiCtx.iMarginX * 2); + } + NeoUI::BeginSection(); + { + if (IsInGame()) + { + // Show the current server's information + NeoUI::Label(L"Hostname:", m_wszHostname); + NeoUI::Label(L"Map:", m_wszMap); + NeoUI::Label(L"Game mode:", NEO_GAME_TYPE_DESC_STRS[NEORules()->GetGameType()].wszStr); + // TODO: more info, g_PR, scoreboard stuff, etc... + } + else + { + // Show the news + NeoUI::SwapFont(NeoUI::FONT_NTHEADING); + NeoUI::Label(L"News"); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + + g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_LEFT; + NeoUI::SwapColorNormal(COLOR_TRANSPARENT); + for (int i = 0; i < m_iNewsSize; ++i) + { + if (NeoUI::Button(m_news[i].wszTitle).bPressed) + { + NeoUI::OpenURL(SZ_WEBSITE, m_news[i].szSitePath); + m_bShowBrowserLabel = true; + } + } + + if (m_bShowBrowserLabel) + { + surface()->DrawSetTextColor(Color(178, 178, 178, 178)); + NeoUI::Label(L"Link opened in your web browser"); + surface()->DrawSetTextColor(COLOR_NEOPANELTEXTNORMAL); + } + + g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_CENTER; + NeoUI::SwapColorNormal(COLOR_NEOPANELACCENTBG); + } + } + NeoUI::EndSection(); +#endif (0) + NeoUI::EndContext(); +} + +void CNeoRoot::MainLoopSettings(const MainLoopParam param) +{ + struct NeoSettingsFunc + { + void (*func)(NeoSettings *); + bool bUISectionManaged; + }; + static constexpr NeoSettingsFunc P_FN[] = { + {NeoSettings_General, false}, + {NeoSettings_Keys, false}, + {NeoSettings_Mouse, false}, + {NeoSettings_Audio, false}, + {NeoSettings_Video, false}, + {NeoSettings_Crosshair, true}, + }; + static const wchar_t *WSZ_TABS_LABELS[ARRAYSIZE(P_FN)] = { + L"Multiplayer", L"Keybinds", L"Mouse", L"Audio", L"Video", L"Crosshair" + }; + + m_ns.iNextBinding = -1; + + const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); + + g_uiCtx.dPanel.wide = g_iRootSubPanelWide; + g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); + g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; + g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; + NeoUI::BeginContext(&g_uiCtx, param.eMode, g_pNeoRoot->m_wszDispBtnTexts[MMBTN_OPTIONS], "CtxOptions"); + { + NeoUI::BeginSection(); + { + NeoUI::Tabs(WSZ_TABS_LABELS, ARRAYSIZE(WSZ_TABS_LABELS), &m_ns.iCurTab); + } + NeoUI::EndSection(); + if (!P_FN[m_ns.iCurTab].bUISectionManaged) + { + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * g_iRowsInScreen; + NeoUI::BeginSection(true); + } + { + P_FN[m_ns.iCurTab].func(&m_ns); + } + if (!P_FN[m_ns.iCurTab].bUISectionManaged) + { + NeoUI::EndSection(); + } + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; + NeoUI::BeginSection(); + { + NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); + { + if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_ns.bBack = true; + } + if (NeoUI::Button(L"Legacy").bPressed) + { + g_pNeoRoot->GetGameUI()->SendMainMenuCommand("OpenOptionsDialog"); + } + if (NeoUI::Button(L"Default").bPressed) + { + m_state = STATE_SETTINGSRESETDEFAULT; + engine->GetVoiceTweakAPI()->EndVoiceTweakMode(); + } + if (m_ns.bModified) + { + if (NeoUI::Button(L"Revert").bPressed) + { + NeoSettingsRestore(&m_ns); + } + if (NeoUI::Button(L"Accept").bPressed) + { + NeoSettingsSave(&m_ns); + } + } + } + NeoUI::EndHorizontal(); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + } + NeoUI::EndSection(); + } + NeoUI::EndContext(); + if (!m_ns.bModified && g_uiCtx.bValueEdited) + { + m_ns.bModified = true; + } + + if (m_ns.bBack) + { + m_ns.bBack = false; + m_state = (m_ns.bModified) ? STATE_CONFIRMSETTINGS : STATE_ROOT; + engine->GetVoiceTweakAPI()->EndVoiceTweakMode(); + } + else if (m_ns.iNextBinding >= 0) + { + m_iBindingIdx = m_ns.iNextBinding; + m_ns.iNextBinding = -1; + V_swprintf_safe(m_wszBindingText, L"Change binding for: %ls", + m_ns.keys.vBinds[m_iBindingIdx].wszDisplayText); + m_state = STATE_KEYCAPTURE; + engine->StartKeyTrapMode(); + } +} + +void CNeoRoot::MainLoopNewGame(const MainLoopParam param) +{ + const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); + g_uiCtx.dPanel.wide = g_iRootSubPanelWide; + g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); + g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen + 1); + g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; + NeoUI::BeginContext(&g_uiCtx, param.eMode, m_wszDispBtnTexts[MMBTN_CREATESERVER], "CtxNewGame"); + { + NeoUI::BeginSection(true); + { + if (NeoUI::Button(L"Map", m_newGame.wszMap).bPressed) + { + m_state = STATE_MAPLIST; + } + NeoUI::TextEdit(L"Hostname", m_newGame.wszHostname, SZWSZ_LEN(m_newGame.wszHostname)); + NeoUI::SliderInt(L"Max players", &m_newGame.iMaxPlayers, 1, 32); + NeoUI::TextEdit(L"Password", m_newGame.wszPassword, SZWSZ_LEN(m_newGame.wszPassword)); + NeoUI::RingBoxBool(L"Friendly fire", &m_newGame.bFriendlyFire); + } + NeoUI::EndSection(); + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; + NeoUI::BeginSection(); + { + NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); + { + if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_ROOT; + } + NeoUI::Pad(); + NeoUI::Pad(); + NeoUI::Pad(); + if (NeoUI::Button(L"Start").bPressed) + { + if (IsInGame()) + { + engine->ClientCmd_Unrestricted("disconnect"); + } + + static constexpr int ENTRY_MAX = 64; + char szMap[ENTRY_MAX + 1] = {}; + char szHostname[ENTRY_MAX + 1] = {}; + char szPassword[ENTRY_MAX + 1] = {}; + g_pVGuiLocalize->ConvertUnicodeToANSI(m_newGame.wszMap, szMap, sizeof(szMap)); + g_pVGuiLocalize->ConvertUnicodeToANSI(m_newGame.wszHostname, szHostname, sizeof(szHostname)); + g_pVGuiLocalize->ConvertUnicodeToANSI(m_newGame.wszPassword, szPassword, sizeof(szPassword)); + + ConVarRef("hostname").SetValue(szHostname); + ConVarRef("sv_password").SetValue(szPassword); + ConVarRef("mp_friendlyfire").SetValue(m_newGame.bFriendlyFire); + + char cmdStr[256]; + V_sprintf_safe(cmdStr, "maxplayers %d; progress_enable; map \"%s\"", m_newGame.iMaxPlayers, szMap); + engine->ClientCmd_Unrestricted(cmdStr); + + if (g_pNeoLoading) + { + V_wcscpy_safe(g_pNeoLoading->m_wszLoadingMap, m_newGame.wszMap); + } + + m_state = STATE_ROOT; + } + } + NeoUI::EndHorizontal(); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + } + NeoUI::EndSection(); + } + NeoUI::EndContext(); +} + +void CNeoRoot::MainLoopServerBrowser(const MainLoopParam param) +{ + static const wchar_t *GS_NAMES[GS__TOTAL] = { + L"Internet", L"LAN", L"Friends", L"Fav", L"History", L"Spec" + }; + + static const wchar_t *ANTICHEAT_LABELS[ANTICHEAT__TOTAL] = { + L"", L"On", L"Off" + }; + + bool bEnterServer = false; + const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); + g_uiCtx.dPanel.wide = g_iRootSubPanelWide; + g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); + g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * 2; + g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; + NeoUI::BeginContext(&g_uiCtx, param.eMode, m_wszDispBtnTexts[MMBTN_FINDSERVER], "CtxServerBrowser"); + { + bool bForceRefresh = false; + NeoUI::BeginSection(); + { + const int iPrevTab = m_iServerBrowserTab; + NeoUI::Tabs(GS_NAMES, ARRAYSIZE(GS_NAMES), &m_iServerBrowserTab); + if (iPrevTab != m_iServerBrowserTab) + { + m_iSelectedServer = -1; + } + if (!m_serverBrowser[m_iServerBrowserTab].m_bReloadedAtLeastOnce) + { + bForceRefresh = true; + m_serverBrowser[m_iServerBrowserTab].m_bReloadedAtLeastOnce = true; + } + g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_LEFT; + NeoUI::BeginHorizontal(1); + { + static constexpr const wchar_t *SBLABEL_NAMES[GSIW__TOTAL] = { + L"Lock", L"VAC", L"Name", L"Map", L"Players", L"Ping", + }; + + for (int i = 0; i < GS__TOTAL; ++i) + { + surface()->DrawSetColor((m_sortCtx.col == i) ? COLOR_NEOPANELACCENTBG : COLOR_NEOPANELNORMALBG); + g_uiCtx.iHorizontalWidth = g_iGSIX[i]; + if (NeoUI::Button(SBLABEL_NAMES[i]).bPressed) + { + if (m_sortCtx.col == i) + { + m_sortCtx.bDescending = !m_sortCtx.bDescending; + } + else + { + m_sortCtx.col = static_cast(i); + } + m_bSBFiltModified = true; + } + + if (param.eMode == NeoUI::MODE_PAINT && m_sortCtx.col == i) + { + int iHintTall = g_uiCtx.iMarginY / 3; + surface()->DrawSetColor(COLOR_NEOPANELTEXTNORMAL); + if (!m_sortCtx.bDescending) + { + NeoUI::GCtxDrawFilledRectXtoX(-g_uiCtx.iHorizontalWidth, 0, 0, iHintTall); + } + else + { + NeoUI::GCtxDrawFilledRectXtoX(-g_uiCtx.iHorizontalWidth, g_uiCtx.iRowTall - iHintTall, 0, g_uiCtx.iRowTall); + } + surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); + } + } + } + + // TODO: Should give proper controls over colors through NeoUI + surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); + surface()->DrawSetTextColor(COLOR_NEOPANELTEXTNORMAL); + NeoUI::EndHorizontal(); + g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_CENTER; + } + NeoUI::EndSection(); + static constexpr int FILTER_ROWS = 5; + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen - 1); + if (m_bShowFilterPanel) g_uiCtx.dPanel.tall -= g_uiCtx.iRowTall * FILTER_ROWS; + NeoUI::BeginSection(true); + { + if (m_serverBrowser[m_iServerBrowserTab].m_filteredServers.IsEmpty()) + { + wchar_t wszInfo[128]; + if (m_serverBrowser[m_iServerBrowserTab].m_bSearching) + { + V_swprintf_safe(wszInfo, L"Searching %ls queries...", GS_NAMES[m_iServerBrowserTab]); + } + else + { + V_swprintf_safe(wszInfo, L"No %ls queries found. Press Refresh to re-check", GS_NAMES[m_iServerBrowserTab]); + } + g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; + NeoUI::Label(wszInfo); + g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_LEFT; + } + else + { + // NEO TODO (nullsystem): This is fine since there isn't going to be much servers, it'll + // handle even couple of 100s ok. However if the amount is a concern, NeoUI can be + // expanded to give Y-offset in the form of filtered array range so it only loops + // through what's needed instead. + const auto *sbTab = &m_serverBrowser[m_iServerBrowserTab]; + for (int i = 0; i < sbTab->m_filteredServers.Size(); ++i) + { + const auto &server = sbTab->m_filteredServers[i]; + bool bSkipServer = false; + if (m_sbFilters.bServerNotFull && server.m_nPlayers == server.m_nMaxPlayers) bSkipServer = true; + else if (m_sbFilters.bHasUsersPlaying && server.m_nPlayers == 0) bSkipServer = true; + else if (m_sbFilters.bIsNotPasswordProtected && server.m_bPassword) bSkipServer = true; + else if (m_sbFilters.iAntiCheat == ANTICHEAT_OFF && server.m_bSecure) bSkipServer = true; + else if (m_sbFilters.iAntiCheat == ANTICHEAT_ON && !server.m_bSecure) bSkipServer = true; + else if (m_sbFilters.iMaxPing != 0 && server.m_nPing > m_sbFilters.iMaxPing) bSkipServer = true; + if (bSkipServer) + { + continue; + } + + const auto btn = NeoUI::Button(L""); + if (btn.bPressed) // Dummy button, draw over it in paint + { + m_iSelectedServer = i; + if (btn.bKeyPressed || btn.bMouseDoublePressed) + { + bEnterServer = true; + } + } + + if (param.eMode == NeoUI::MODE_PAINT) + { + Color drawColor = COLOR_NEOPANELNORMALBG; + if (m_iSelectedServer == i) drawColor = COLOR_NEOPANELACCENTBG; + if (btn.bMouseHover) drawColor = COLOR_NEOPANELSELECTBG; + + vgui::surface()->DrawSetColor(drawColor); + NeoUI::GCtxDrawFilledRectXtoX(0, -g_uiCtx.iRowTall, g_uiCtx.dPanel.wide, 0); + + ServerBrowserDrawRow(server); + } + } + } + } + surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); + NeoUI::EndSection(); + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; + if (m_bShowFilterPanel) g_uiCtx.dPanel.tall += g_uiCtx.iRowTall * FILTER_ROWS; + NeoUI::BeginSection(); + { + NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 6); + { + if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_ROOT; + } + if (NeoUI::Button(L"Legacy").bPressed) + { + GetGameUI()->SendMainMenuCommand("OpenServerBrowser"); + } + if (NeoUI::Button(m_bShowFilterPanel ? L"Hide Filters" : L"Show Filters").bPressed) + { + m_bShowFilterPanel = !m_bShowFilterPanel; + } + if (m_iSelectedServer >= 0) + { + if (NeoUI::Button(L"Details").bPressed) + { + m_state = STATE_SERVERDETAILS; + const auto *gameServer = &m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; + m_serverPlayers.RequestList(gameServer->m_NetAdr.GetIP(), gameServer->m_NetAdr.GetQueryPort()); + } + } + else + { + NeoUI::Pad(); + } + if (NeoUI::Button(L"Refresh").bPressed || bForceRefresh) + { + m_iSelectedServer = -1; + ISteamMatchmakingServers *steamMM = steamapicontext->SteamMatchmakingServers(); + CNeoServerList *pServerBrowser = &m_serverBrowser[m_iServerBrowserTab]; + pServerBrowser->m_servers.RemoveAll(); + pServerBrowser->m_filteredServers.RemoveAll(); + if (pServerBrowser->m_hdlRequest) + { + steamMM->CancelQuery(pServerBrowser->m_hdlRequest); + steamMM->ReleaseRequest(pServerBrowser->m_hdlRequest); + pServerBrowser->m_hdlRequest = nullptr; + } + pServerBrowser->RequestList(); + } + if (m_iSelectedServer >= 0) + { + if (bEnterServer || NeoUI::Button(L"Enter").bPressed) + { + if (IsInGame()) + { + engine->ClientCmd_Unrestricted("disconnect"); + } + + ConVarRef("password").SetValue(""); + V_memset(m_wszServerPassword, 0, sizeof(m_wszServerPassword)); + + // NEO NOTE (nullsystem): Deal with password protected server + const auto gameServer = m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; + if (gameServer.m_bPassword) + { + m_state = STATE_SERVERPASSWORD; + } + else + { + char connectCmd[256]; + const char *szAddress = gameServer.m_NetAdr.GetConnectionAddressString(); + V_sprintf_safe(connectCmd, "progress_enable; wait; connect %s", szAddress); + engine->ClientCmd_Unrestricted(connectCmd); + + if (g_pNeoLoading) + { + g_pVGuiLocalize->ConvertANSIToUnicode(gameServer.m_szMap, + g_pNeoLoading->m_wszLoadingMap, + sizeof(g_pNeoLoading->m_wszLoadingMap)); + } + + m_state = STATE_ROOT; + } + } + } + } + NeoUI::EndHorizontal(); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + if (m_bShowFilterPanel) + { + NeoUI::RingBoxBool(L"Server not full", &m_sbFilters.bServerNotFull); + NeoUI::RingBoxBool(L"Has users playing", &m_sbFilters.bHasUsersPlaying); + NeoUI::RingBoxBool(L"Is not password protected", &m_sbFilters.bIsNotPasswordProtected); + NeoUI::RingBox(L"Anti-cheat", ANTICHEAT_LABELS, ARRAYSIZE(ANTICHEAT_LABELS), &m_sbFilters.iAntiCheat); + NeoUI::SliderInt(L"Maximum ping", &m_sbFilters.iMaxPing, 0, 500, 10, L"No limit"); + } + } + NeoUI::EndSection(); + } + NeoUI::EndContext(); + +} + +void CNeoRoot::MainLoopMapList(const MainLoopParam param) +{ + const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); + g_uiCtx.dPanel.wide = g_iRootSubPanelWide; + g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); + g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen + 1); + g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; + NeoUI::BeginContext(&g_uiCtx, param.eMode, L"Pick map", "CtxMapPicker"); + { + NeoUI::BeginSection(true); + { + for (auto &wszMap : m_vWszMaps) + { + if (NeoUI::Button(wszMap.wszName).bPressed) + { + V_wcscpy_safe(m_newGame.wszMap, wszMap.wszName); + m_state = STATE_NEWGAME; + } + } + } + NeoUI::EndSection(); + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; + NeoUI::BeginSection(); + { + NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); + { + if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_NEWGAME; + } + } + NeoUI::EndHorizontal(); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + } + NeoUI::EndSection(); + } + NeoUI::EndContext(); +} + +void CNeoRoot::MainLoopServerDetails(const MainLoopParam param) +{ + const auto *gameServer = &m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; + const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); + g_uiCtx.dPanel.wide = g_iRootSubPanelWide; + g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); + g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * 6; + g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; + NeoUI::BeginContext(&g_uiCtx, param.eMode, L"Server details", "CtxServerDetail"); + { + NeoUI::BeginSection(true); + { + const bool bP = param.eMode == NeoUI::MODE_PAINT; + wchar_t wszText[128]; + if (bP) g_pVGuiLocalize->ConvertANSIToUnicode(gameServer->GetName(), wszText, sizeof(wszText)); + NeoUI::Label(L"Name:", wszText); + if (!neo_cl_streamermode.GetBool()) + { + if (bP) g_pVGuiLocalize->ConvertANSIToUnicode(gameServer->m_NetAdr.GetConnectionAddressString(), wszText, sizeof(wszText)); + NeoUI::Label(L"Address:", wszText); + } + if (bP) g_pVGuiLocalize->ConvertANSIToUnicode(gameServer->m_szMap, wszText, sizeof(wszText)); + NeoUI::Label(L"Map:", wszText); + if (bP) V_swprintf_safe(wszText, L"%d/%d", gameServer->m_nPlayers, gameServer->m_nMaxPlayers); + NeoUI::Label(L"Players:", wszText); + if (bP) V_swprintf_safe(wszText, L"%ls", gameServer->m_bSecure ? L"Enabled" : L"Disabled"); + NeoUI::Label(L"VAC:", wszText); + if (bP) V_swprintf_safe(wszText, L"%d", gameServer->m_nPing); + NeoUI::Label(L"Ping:", wszText); + + // TODO: Header same-style as serverlist's header + } + NeoUI::EndSection(); + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = (iTallTotal - g_uiCtx.iRowTall) - g_uiCtx.dPanel.tall; + NeoUI::BeginSection(); + { + if (!neo_cl_streamermode.GetBool()) + { + if (m_serverPlayers.m_players.IsEmpty()) + { + g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; + NeoUI::Label(L"There are no players in the server."); + g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_LEFT; + } + else + { + for (const auto &player : m_serverPlayers.m_players) + { + NeoUI::Label(player.wszName); + // TODO + } + } + } + } + NeoUI::EndSection(); + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; + NeoUI::BeginSection(); + { + NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); + { + if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_SERVERBROWSER; + } + } + NeoUI::EndHorizontal(); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + } + NeoUI::EndSection(); + } + NeoUI::EndContext(); +} + +void CNeoRoot::MainLoopPlayerList(const MainLoopParam param) +{ + if (IsInGame()) + { + const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); + g_uiCtx.dPanel.wide = g_iRootSubPanelWide; + g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); + g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen + 1); + g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; + NeoUI::BeginContext(&g_uiCtx, param.eMode, L"Player list", "CtxPlayerList"); + { + NeoUI::BeginSection(true); + { + g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_LEFT; + for (int i = 1; i <= gpGlobals->maxClients; i++) + { + if (!g_PR->IsConnected(i) || g_PR->IsHLTV(i) || g_PR->IsFakePlayer(i)) + { + continue; + } + + const bool bOwnLocalPlayer = g_PR->IsLocalPlayer(i); + const bool bPlayerMuted = GetClientVoiceMgr()->IsPlayerBlocked(i); + const char *szPlayerName = g_PR->GetPlayerName(i); + wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH + 1]; + g_pVGuiLocalize->ConvertANSIToUnicode(szPlayerName, wszPlayerName, sizeof(wszPlayerName)); + + wchar_t wszInfo[256]; + V_swprintf_safe(wszInfo, L"%ls%ls", bOwnLocalPlayer ? L"[LOCAL] " : bPlayerMuted ? L"[MUTED] " : L"[VOICE] ", wszPlayerName); + if (NeoUI::Button(wszInfo).bPressed) + { + if (!bOwnLocalPlayer) GetClientVoiceMgr()->SetPlayerBlockedState(i, !bPlayerMuted); + } + } + g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_CENTER; + } + NeoUI::EndSection(); + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; + NeoUI::BeginSection(); + { + NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); + { + if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_ROOT; + } + } + NeoUI::EndHorizontal(); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + } + NeoUI::EndSection(); + } + NeoUI::EndContext(); + } + else + { + m_state = STATE_ROOT; + } +} + +void CNeoRoot::MainLoopPopup(const MainLoopParam param) +{ + surface()->DrawSetColor(COLOR_NEOPANELPOPUPBG); + surface()->DrawFilledRect(0, 0, param.wide, param.tall); + const int tallSplit = param.tall / 3; + surface()->DrawSetColor(COLOR_NEOPANELNORMALBG); + surface()->DrawFilledRect(0, tallSplit, param.wide, param.tall - tallSplit); + + g_uiCtx.dPanel.wide = g_iRootSubPanelWide * 0.75f; + g_uiCtx.dPanel.tall = tallSplit; + g_uiCtx.dPanel.x = (param.wide / 2) - (g_uiCtx.dPanel.wide / 2); + g_uiCtx.dPanel.y = tallSplit + (tallSplit / 2) - g_uiCtx.iRowTall; + g_uiCtx.bgColor = COLOR_TRANSPARENT; + if (m_state == STATE_SERVERPASSWORD) + { + g_uiCtx.dPanel.y -= g_uiCtx.iRowTall; + } + // Technically can get away with have a common context name, since these dialogs + // don't do anything special with it + NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxCommonPopupDlg"); + { + NeoUI::BeginSection(true); + { + g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; + NeoUI::SwapFont(NeoUI::FONT_NTLARGE); + switch (m_state) + { + case STATE_KEYCAPTURE: + { + NeoUI::Label(m_wszBindingText); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + NeoUI::Label(L"Press ESC to cancel or DEL to remove keybind"); + } + break; + case STATE_CONFIRMSETTINGS: + { + NeoUI::Label(L"Settings changed: Do you want to apply the settings?"); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + NeoUI::BeginHorizontal((g_uiCtx.dPanel.wide / 3) - g_uiCtx.iMarginX, g_uiCtx.iMarginX); + { + g_uiCtx.iLayoutX = (g_uiCtx.iMarginX / 2); + if (NeoUI::Button(L"Save (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) + { + NeoSettingsSave(&m_ns); + m_state = STATE_ROOT; + } + if (NeoUI::Button(L"Discard").bPressed) + { + m_state = STATE_ROOT; + } + if (NeoUI::Button(L"Cancel (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_SETTINGS; + } + } + NeoUI::EndHorizontal(); + } + break; + case STATE_QUIT: + { + NeoUI::Label(L"Do you want to quit the game?"); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 3); + { + if (NeoUI::Button(L"Quit (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) + { + engine->ClientCmd_Unrestricted("quit"); + } + NeoUI::Pad(); + if (NeoUI::Button(L"Cancel (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_ROOT; + } + } + NeoUI::EndHorizontal(); + } + break; + case STATE_SERVERPASSWORD: + { + NeoUI::Label(L"Enter the server password"); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + g_uiCtx.bTextEditIsPassword = true; + NeoUI::TextEdit(L"Password:", m_wszServerPassword, SZWSZ_LEN(m_wszServerPassword)); + g_uiCtx.bTextEditIsPassword = false; + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 3); + { + if (NeoUI::Button(L"Enter (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) + { + char szServerPassword[ARRAYSIZE(m_wszServerPassword)]; + g_pVGuiLocalize->ConvertUnicodeToANSI(m_wszServerPassword, szServerPassword, sizeof(szServerPassword)); + ConVarRef("password").SetValue(szServerPassword); + V_memset(m_wszServerPassword, 0, sizeof(m_wszServerPassword)); + + const auto gameServer = m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; + char connectCmd[256]; + const char *szAddress = gameServer.m_NetAdr.GetConnectionAddressString(); + V_sprintf_safe(connectCmd, "progress_enable; wait; connect %s", szAddress); + engine->ClientCmd_Unrestricted(connectCmd); + + m_state = STATE_ROOT; + } + NeoUI::Pad(); + if (NeoUI::Button(L"Cancel (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + V_memset(m_wszServerPassword, 0, sizeof(m_wszServerPassword)); + m_state = STATE_SERVERBROWSER; + } + } + NeoUI::EndHorizontal(); + } + break; + case STATE_SETTINGSRESETDEFAULT: + { + NeoUI::Label(L"Do you want to reset your settings back to default?"); + NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); + NeoUI::BeginHorizontal((g_uiCtx.dPanel.wide / 3) - g_uiCtx.iMarginX, g_uiCtx.iMarginX); + { + if (NeoUI::Button(L"Yes (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) + { + NeoSettingsResetToDefault(&m_ns); + m_state = STATE_SETTINGS; + } + NeoUI::Pad(); + if (NeoUI::Button(L"No (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) + { + m_state = STATE_SETTINGS; + } + } + NeoUI::EndHorizontal(); + } + break; + default: + break; + } + } + NeoUI::EndSection(); + } + NeoUI::EndContext(); +} + +void CNeoRoot::HTTPCallbackRequest(HTTPRequestCompleted_t *request, bool bIOFailure) +{ + ISteamHTTP *http = steamapicontext->SteamHTTP(); + if (request->m_bRequestSuccessful && !bIOFailure) + { + uint32 unBodySize = 0; + http->GetHTTPResponseBodySize(request->m_hRequest, &unBodySize); + + if (unBodySize > 0) + { + uint8 *pData = new uint8[unBodySize + 1]; + http->GetHTTPResponseBodyData(request->m_hRequest, pData, unBodySize); + + CUtlBuffer buf(0, 0, CUtlBuffer::TEXT_BUFFER); + buf.CopyBuffer(pData, unBodySize); + filesystem->WriteFile("news.txt", nullptr, buf); + ReadNewsFile(buf); + + delete[] pData; + } + } + http->ReleaseHTTPRequest(request->m_hRequest); +} + +void CNeoRoot::ReadNewsFile(CUtlBuffer &buf) +{ + buf.SeekGet(CUtlBuffer::SEEK_HEAD, 0); + m_iNewsSize = 0; + while (buf.IsValid() && m_iNewsSize < MAX_NEWS) + { + // TSV row: Path\tDate\tTitle + char szLine[512] = {}; + buf.GetLine(szLine, ARRAYSIZE(szLine) - 1); + char *pszDate = strchr(szLine, '\t'); + if (!pszDate) + { + continue; + } + + *pszDate = '\0'; + ++pszDate; + if (!*pszDate) + { + continue; + } + + char *pszTitle = strchr(pszDate, '\t'); + if (!pszTitle) + { + continue; + } + + *pszTitle = '\0'; + ++pszTitle; + if (!*pszTitle) + { + continue; + } + + V_strcpy_safe(m_news[m_iNewsSize].szSitePath, szLine); + wchar_t wszDate[12]; + wchar_t wszTitle[235]; + g_pVGuiLocalize->ConvertANSIToUnicode(pszDate, wszDate, sizeof(wszDate)); + g_pVGuiLocalize->ConvertANSIToUnicode(pszTitle, wszTitle, sizeof(wszTitle)); + V_swprintf_safe(m_news[m_iNewsSize].wszTitle, L"%ls: %ls", wszDate, wszTitle); + ++m_iNewsSize; + } +} + +void CNeoRoot::OnFileSelected(const char *szFullpath) +{ + ((m_ns.crosshair.eFileIOMode == vgui::FOD_OPEN) ? + &ImportCrosshair : &ExportCrosshair)(&m_ns.crosshair.info, szFullpath); +} + +// NEO NOTE (nullsystem): NeoRootCaptureESC is so that ESC keybinds can be recognized by non-root states, but root +// state still want to have ESC handled by the game as IsVisible/HasFocus isn't reliable indicator to depend on. +// This goes along with NeoToggleconsole which if the toggleconsole is activated on non-root state that can end up +// blocking ESC key from being usable in-game, so have to force it back to root state first to help with +// NeoRootCaptureESC condition. So this will do. + +bool NeoRootCaptureESC() +{ + return (g_pNeoRoot && g_pNeoRoot->IsEnabled() && g_pNeoRoot->m_state != STATE_ROOT); +} + +void NeoToggleconsole() +{ + if (neo_cl_toggleconsole.GetBool()) + { + if (engine->IsInGame() && g_pNeoRoot) + { + g_pNeoRoot->m_state = STATE_ROOT; + } + // NEO JANK (nullsystem): con_enable 1 is required to allow toggleconsole to + // work and using the legacy settings will alter that value. + // It's in here rather than startup so it doesn't trigger the console on startup + ConVarRef("con_enable").SetValue(true); + engine->ClientCmd_Unrestricted("toggleconsole"); + } +} diff --git a/mp/src/game/client/neo/ui/neo_root.cpp b/mp/src/game/client/neo/ui/neo_root.cpp index 047bcc89d..ab9f85c1e 100644 --- a/mp/src/game/client/neo/ui/neo_root.cpp +++ b/mp/src/game/client/neo/ui/neo_root.cpp @@ -527,12 +527,17 @@ void CNeoRoot::OnMainLoop(const NeoUI::Mode eMode) void CNeoRoot::MainLoopRoot(const MainLoopParam param) { const int yTopPos = 0; - g_uiCtx.dPanel.wide = (m_iTitleWidth * 0.8) + (2 * g_uiCtx.iMarginX); + int iTitleNWidth, iTitleNHeight; + const int iBtnPlaceXMid = (param.wide / 6); + const int iMargin = (6 * g_uiCtx.iMarginX); + const int iMarginHalf = iMargin * 0.5; + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, L"n", iTitleNWidth, iTitleNHeight); + g_uiCtx.dPanel.wide = (m_iTitleWidth) +iMargin; g_uiCtx.dPanel.tall = param.tall - yTopPos; - g_uiCtx.dPanel.x = (param.wide / 4) - (g_uiCtx.dPanel.wide / 2); + g_uiCtx.dPanel.x = iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - iMarginHalf; g_uiCtx.dPanel.y = yTopPos; g_uiCtx.iYOffset[0] = -8; - g_uiCtx.bgColor = COLOR_NEOPANELSELECTBG; + g_uiCtx.bgColor = COLOR_NEOPANELNORMALBG; NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxRoot"); NeoUI::BeginSection(true); @@ -573,9 +578,8 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) NeoUI::EndSection(); g_uiCtx.bgColor = COLOR_TRANSPARENT; - const int iBtnPlaceXMid = (param.wide / 4); - const int iBtnWide = m_iTitleWidth + (2 * g_uiCtx.iMarginX); - const int iRightXPos = iBtnPlaceXMid + (iBtnWide / 2) + g_uiCtx.iMarginX; + const int iBtnWide = m_iTitleWidth + iMargin; + const int iRightXPos = iBtnPlaceXMid + (iBtnWide / 2) + iMarginHalf; int iRightSideYStart = yTopPos; // Draw top steam section portion @@ -583,12 +587,10 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) // Draw title surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl); surface()->DrawSetTextColor(COLOR_NEOTITLE); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), yTopPos + m_iTitleHeight); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), yTopPos + (param.tall * 0.2)); surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); - int iTitleNWidth, iTitleNHeight; - surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, L"n", iTitleNWidth, iTitleNHeight); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), yTopPos + m_iTitleHeight + (iTitleNHeight * 0.7)); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), yTopPos + (param.tall * 0.2) + m_iTitleHeight); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); diff --git a/mp/src/game/client/neo/ui/neo_ui.h b/mp/src/game/client/neo/ui/neo_ui.h index 412303c39..4199ba8ca 100644 --- a/mp/src/game/client/neo/ui/neo_ui.h +++ b/mp/src/game/client/neo/ui/neo_ui.h @@ -181,7 +181,7 @@ struct Context CUtlHashtable htSliders; }; -#define COLOR_NEOPANELNORMALBG Color(40, 40, 40, 255) +#define COLOR_NEOPANELNORMALBG Color(0, 0, 0, 150) #define COLOR_NEOPANELSELECTBG Color(0, 0, 0, 100) #define COLOR_NEOPANELACCENTBG Color(0, 0, 0, 0) #define COLOR_NEOPANELTEXTNORMAL Color(255, 255, 255, 255)//Color(200, 200, 200, 255) From a5e775ab4e35402687274f80db03939e2ecff266 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 18:52:44 +0000 Subject: [PATCH 05/10] better option highlighting and changes to background colour --- .../neo_root.cpp | 1597 ----------------- mp/src/game/client/neo/ui/neo_root.cpp | 76 +- mp/src/game/client/neo/ui/neo_ui.cpp | 17 +- mp/src/game/client/neo/ui/neo_ui.h | 6 +- 4 files changed, 60 insertions(+), 1636 deletions(-) delete mode 100644 mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp diff --git a/mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp b/mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp deleted file mode 100644 index b6141a312..000000000 --- a/mp/src/enc_temp_folder/dd8563d69ea5d69ae7b66cfefaad625a/neo_root.cpp +++ /dev/null @@ -1,1597 +0,0 @@ -#include "cbase.h" -#include "neo_root.h" -#include "IOverrideInterface.h" - -#include "vgui/ILocalize.h" -#include "vgui/IPanel.h" -#include "vgui/ISurface.h" -#include "vgui/IVGui.h" -#include "ienginevgui.h" -#include -#include "filesystem.h" -#include "neo_version_info.h" -#include "cdll_client_int.h" -#include -#include -#include -#include -#include -#include -#include "tier1/interface.h" -#include -#include "ui/neo_loading.h" -#include "neo_gamerules.h" -#include "neo_misc.h" - -#include -#include - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// TODO: Gamepad -// Gamepad enable: joystick 0/1 -// Reverse up-down axis: joy_inverty 0/1 -// Swap sticks on dual-stick controllers: joy_movement_stick 0/1 -// Horizontal sens: joy_yawsensitivity: -0.5 to -7.0 -// Vertical sens: joy_pitchsensitivity: 0.5 to 7.0 - -using namespace vgui; - -// See interface.h/.cpp for specifics: basically this ensures that we actually Sys_UnloadModule -// the dll and that we don't call Sys_LoadModule over and over again. -static CDllDemandLoader g_GameUIDLL("GameUI"); - -extern ConVar neo_name; -extern ConVar cl_onlysteamnick; -extern ConVar neo_cl_streamermode; -extern ConVar neo_clantag; - -CNeoRoot *g_pNeoRoot = nullptr; -void NeoToggleconsole(); -extern CNeoLoading *g_pNeoLoading; -inline NeoUI::Context g_uiCtx; -inline ConVar neo_cl_toggleconsole("neo_cl_toggleconsole", "0", FCVAR_ARCHIVE, - "If the console can be toggled with the ` keybind or not.", true, 0.0f, true, 1.0f); -inline int g_iRowsInScreen; - -namespace { - -int g_iAvatar = 64; -int g_iRootSubPanelWide = 600; -constexpr wchar_t WSZ_GAME_TITLE1[] = L"neAtBkyoC"; -constexpr wchar_t WSZ_GAME_TITLE2[] = L";rebuild"; -#define SZ_WEBSITE "https://neotokyorebuild.github.io" - -ConCommand neo_toggleconsole("neo_toggleconsole", NeoToggleconsole); - -struct YMD -{ - YMD(const struct tm tm) - : year(tm.tm_year + 1900) - , month(tm.tm_mon + 1) - , day(tm.tm_mday) - { - } - - bool operator==(const YMD &other) const - { - return year == other.year && month == other.month && day == other.day; - } - bool operator!=(const YMD &other) const - { - return !(*this == other); - } - - int year; - int month; - int day; -}; - -} - -void OverrideGameUI() -{ - if (!OverrideUI->GetPanel()) - { - OverrideUI->Create(0U); - } - - if (g_pNeoRoot->GetGameUI()) - { - g_pNeoRoot->GetGameUI()->SetMainMenuOverride(g_pNeoRoot->GetVPanel()); - } -} - -CNeoRootInput::CNeoRootInput(CNeoRoot *rootPanel) - : Panel(rootPanel, "NeoRootPanelInput") - , m_pNeoRoot(rootPanel) -{ - MakePopup(true); - SetKeyBoardInputEnabled(true); - SetMouseInputEnabled(false); - SetVisible(true); - SetEnabled(true); - PerformLayout(); -} - -void CNeoRootInput::PerformLayout() -{ - SetPos(0, 0); - SetSize(1, 1); - SetBgColor(COLOR_TRANSPARENT); - SetFgColor(COLOR_TRANSPARENT); -} - -void CNeoRootInput::OnKeyCodeTyped(vgui::KeyCode code) -{ - m_pNeoRoot->OnRelayedKeyCodeTyped(code); -} - -void CNeoRootInput::OnKeyTyped(wchar_t unichar) -{ - m_pNeoRoot->OnRelayedKeyTyped(unichar); -} - -void CNeoRootInput::OnThink() -{ - ButtonCode_t code; - if (engine->CheckDoneKeyTrapping(code)) - { - if (code != KEY_ESCAPE) - { - if (code != KEY_DELETE) - { - // The keybind system used requires 1:1 so unbind any duplicates - for (auto &bind : m_pNeoRoot->m_ns.keys.vBinds) - { - if (bind.bcNext == code) - { - bind.bcNext = BUTTON_CODE_NONE; - } - } - } - m_pNeoRoot->m_ns.keys.vBinds[m_pNeoRoot->m_iBindingIdx].bcNext = - (code == KEY_DELETE) ? BUTTON_CODE_NONE : code; - m_pNeoRoot->m_ns.bModified = true; - } - m_pNeoRoot->m_wszBindingText[0] = '\0'; - m_pNeoRoot->m_iBindingIdx = -1; - m_pNeoRoot->m_state = STATE_SETTINGS; - V_memcpy(g_uiCtx.iYOffset, m_pNeoRoot->m_iSavedYOffsets, NeoUI::SIZEOF_SECTIONS); - } -} - -constexpr WidgetInfo BTNS_INFO[BTNS_TOTAL] = { - { "#GameUI_GameMenu_ResumeGame", "ResumeGame", STATE__TOTAL, FLAG_SHOWINGAME }, - { "#GameUI_GameMenu_FindServers", nullptr, STATE_SERVERBROWSER, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, - { "#GameUI_GameMenu_CreateServer", nullptr, STATE_NEWGAME, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, - { "#GameUI_GameMenu_Disconnect", "Disconnect", STATE__TOTAL, FLAG_SHOWINGAME }, - { "#GameUI_GameMenu_PlayerList", nullptr, STATE_PLAYERLIST, FLAG_SHOWINGAME }, - { "#GameUI_GameMenu_Options", nullptr, STATE_SETTINGS, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, - { "#GameUI_GameMenu_Quit", nullptr, STATE_QUIT, FLAG_SHOWINGAME | FLAG_SHOWINMAIN }, -}; - -CNeoRoot::CNeoRoot(VPANEL parent) - : EditablePanel(nullptr, "NeoRootPanel") - , m_panelCaptureInput(new CNeoRootInput(this)) -{ - SetParent(parent); - g_pNeoRoot = this; - LoadGameUI(); - SetVisible(true); - SetProportional(false); - - vgui::HScheme neoscheme = vgui::scheme()->LoadSchemeFromFileEx( - enginevgui->GetPanel(PANEL_CLIENTDLL), "resource/ClientScheme.res", "ClientScheme"); - SetScheme(neoscheme); - - for (int i = 0; i < BTNS_TOTAL; ++i) - { - const char *label = BTNS_INFO[i].label; - if (wchar_t *localizedWszStr = g_pVGuiLocalize->Find(label)) - { - V_wcsncpy(m_wszDispBtnTexts[i], localizedWszStr, sizeof(m_wszDispBtnTexts[i])); - } - else - { - g_pVGuiLocalize->ConvertANSIToUnicode(label, m_wszDispBtnTexts[i], sizeof(m_wszDispBtnTexts[i])); - } - m_iWszDispBtnTextsSizes[i] = V_wcslen(m_wszDispBtnTexts[i]); - } - - NeoSettingsInit(&m_ns); - { - // Initialize map list - FileFindHandle_t findHdl; - for (const char *pszFilename = filesystem->FindFirst("maps/*.bsp", &findHdl); - pszFilename; - pszFilename = filesystem->FindNext(findHdl)) - { - // Sanity check: In-case somehow someone named a directory as *.bsp in here - if (!filesystem->FindIsDirectory(findHdl)) - { - MapInfo mapInfo; - int iSize = g_pVGuiLocalize->ConvertANSIToUnicode(pszFilename, mapInfo.wszName, sizeof(mapInfo.wszName)); - iSize -= sizeof(".bsp"); - mapInfo.wszName[iSize] = '\0'; - m_vWszMaps.AddToTail(mapInfo); - } - } - filesystem->FindClose(findHdl); - } - for (int i = 0; i < GS__TOTAL; ++i) - { - m_serverBrowser[i].m_iType = static_cast(i); - m_serverBrowser[i].m_pSortCtx = &m_sortCtx; - } - - // NEO TODO (nullsystem): What will happen in 2038? 64-bit Source 1 SDK when? Source 2 SDK when? - // We could use GCC 64-bit compiled time_t or Win32 API direct to side-step IFileSystem "long" 32-bit - // limitation for now. Although that could mess with the internal IFileSystem related API usages of time_t. - // If _FILE_OFFSET_BITS=64 and _TIME_BITS=64 is set on Linux, time_t will be 64-bit even on 32-bit executable - // - // If news.txt doesn't exists, it'll just give 1970-01-01 which will always be different to ymdNow anyway - const long lFileTime = filesystem->GetFileTime("news.txt"); - const time_t ttFileTime = lFileTime; - struct tm tmFileStruct; - const struct tm tmFile = *(Plat_localtime(&ttFileTime, &tmFileStruct)); - const YMD ymdFile{tmFile}; - - struct tm tmNowStruct; - const time_t tNow = time(nullptr); - const struct tm tmNow = *(Plat_localtime(&tNow, &tmNowStruct)); - const YMD ymdNow{tmNow}; - - // Read the cached file regardless of needing update or not - if (filesystem->FileExists("news.txt")) - { - CUtlBuffer buf(0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY); - if (filesystem->ReadFile("news.txt", nullptr, buf)) - { - ReadNewsFile(buf); - } - } - if (ymdFile != ymdNow) - { - ISteamHTTP *http = steamapicontext->SteamHTTP(); - HTTPRequestHandle httpReqHdl = http->CreateHTTPRequest(k_EHTTPMethodGET, SZ_WEBSITE "/news.txt"); - SteamAPICall_t httpReqCallback; - http->SendHTTPRequest(httpReqHdl, &httpReqCallback); - m_ccallbackHttp.Set(httpReqCallback, this, &CNeoRoot::HTTPCallbackRequest); - } - - SetKeyBoardInputEnabled(true); - SetMouseInputEnabled(true); - UpdateControls(); - ivgui()->AddTickSignal(GetVPanel(), 200); - ListenForGameEvent("server_spawn"); - ListenForGameEvent("game_newmap"); - - vgui::IScheme *pScheme = vgui::scheme()->GetIScheme(neoscheme); - ApplySchemeSettings(pScheme); -} - -CNeoRoot::~CNeoRoot() -{ - if (g_pNeoRoot->m_pFileIODialog) g_pNeoRoot->m_pFileIODialog->DeletePanel(); - m_panelCaptureInput->DeletePanel(); - if (m_avImage) delete m_avImage; - NeoSettingsDeinit(&m_ns); - - m_gameui = nullptr; - g_GameUIDLL.Unload(); -} - -IGameUI *CNeoRoot::GetGameUI() -{ - if (!m_gameui && !LoadGameUI()) return nullptr; - return m_gameui; -} - -void CNeoRoot::UpdateControls() -{ - if (m_state == STATE_ROOT) - { - auto hdlFont = g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl; - surface()->DrawSetTextFont(hdlFont); - surface()->GetTextSize(hdlFont, WSZ_GAME_TITLE2, m_iTitleWidth, m_iTitleHeight); - } - g_uiCtx.iActiveDirection = 0; - g_uiCtx.iActive = NeoUI::FOCUSOFF_NUM; - g_uiCtx.iActiveSection = -1; - V_memset(g_uiCtx.iYOffset, 0, sizeof(g_uiCtx.iYOffset)); - m_ns.bBack = false; - m_bShowBrowserLabel = false; - RequestFocus(); - m_panelCaptureInput->RequestFocus(); - InvalidateLayout(); -} - -bool CNeoRoot::LoadGameUI() -{ - if (!m_gameui) - { - CreateInterfaceFn gameUIFactory = g_GameUIDLL.GetFactory(); - if (!gameUIFactory) return false; - - m_gameui = reinterpret_cast(gameUIFactory(GAMEUI_INTERFACE_VERSION, nullptr)); - if (!m_gameui) return false; - } - return true; -} - -void CNeoRoot::ApplySchemeSettings(IScheme *pScheme) -{ - BaseClass::ApplySchemeSettings(pScheme); - // NEO TODO (nullsystem): If we're to provide color scheme controls: - // LoadControlSettings("resource/NeoRootScheme.res"); - - // Resize the panel to the screen size - int wide, tall; - surface()->GetScreenSize(wide, tall); - SetSize(wide, tall); - SetFgColor(COLOR_TRANSPARENT); - SetBgColor(COLOR_TRANSPARENT); - - static constexpr const char *FONT_NAMES[NeoUI::FONT__TOTAL] = { - "NeoUINormal", "NHudOCR", "NHudOCRSmallNoAdditive", "ClientTitleFont", "ClientTitleFontSmall", - "NeoUILarge" - }; - for (int i = 0; i < NeoUI::FONT__TOTAL; ++i) - { - g_uiCtx.fonts[i].hdl = pScheme->GetFont(FONT_NAMES[i], true); - } - - // In 1080p, g_uiCtx.iRowTall == 40, g_uiCtx.iMarginX = 10, g_iAvatar = 64, - // other resolution scales up/down from it - g_uiCtx.iRowTall = tall / 27; - g_iRowsInScreen = (tall * 0.85f) / g_uiCtx.iRowTall; - g_uiCtx.iMarginX = wide / 192; - g_uiCtx.iMarginY = tall / 108; - g_iAvatar = wide / 30; - const float flWide = static_cast(wide); - m_flWideAs43 = static_cast(tall) * (4.0f / 3.0f); - if (m_flWideAs43 > flWide) m_flWideAs43 = flWide; - g_iRootSubPanelWide = static_cast(m_flWideAs43 * 0.9f); - - constexpr int PARTITION = GSIW__TOTAL * 4; - const int iSubDiv = g_iRootSubPanelWide / PARTITION; - g_iGSIX[GSIW_LOCKED] = iSubDiv * 2; - g_iGSIX[GSIW_VAC] = iSubDiv * 2; - g_iGSIX[GSIW_NAME] = iSubDiv * 10; - g_iGSIX[GSIW_MAP] = iSubDiv * 5; - g_iGSIX[GSIW_PLAYERS] = iSubDiv * 3; - g_iGSIX[GSIW_PING] = iSubDiv * 2; - - UpdateControls(); -} - -void CNeoRoot::Paint() -{ - OnMainLoop(NeoUI::MODE_PAINT); -} - -void CNeoRoot::OnMousePressed(vgui::MouseCode code) -{ - g_uiCtx.eCode = code; - OnMainLoop(NeoUI::MODE_MOUSEPRESSED); -} - -void CNeoRoot::OnMouseReleased(vgui::MouseCode code) -{ - g_uiCtx.eCode = code; - OnMainLoop(NeoUI::MODE_MOUSERELEASED); -} - -void CNeoRoot::OnMouseDoublePressed(vgui::MouseCode code) -{ - g_uiCtx.eCode = code; - OnMainLoop(NeoUI::MODE_MOUSEDOUBLEPRESSED); -} - -void CNeoRoot::OnMouseWheeled(int delta) -{ - g_uiCtx.eCode = (delta > 0) ? MOUSE_WHEEL_UP : MOUSE_WHEEL_DOWN; - OnMainLoop(NeoUI::MODE_MOUSEWHEELED); -} - -void CNeoRoot::OnCursorMoved(int x, int y) -{ - g_uiCtx.iMouseAbsX = x; - g_uiCtx.iMouseAbsY = y; - OnMainLoop(NeoUI::MODE_MOUSEMOVED); -} - -void CNeoRoot::OnTick() -{ - if (m_state == STATE_SERVERBROWSER) - { - if (m_bSBFiltModified) - { - // Pass modified over to the tabs so it doesn't trigger - // the filter refresh immeditely - for (int i = 0; i < GS__TOTAL; ++i) - { - m_serverBrowser[i].m_bModified = true; - } - m_bSBFiltModified = false; - } - - auto *pSbTab = &m_serverBrowser[m_iServerBrowserTab]; - if (pSbTab->m_bModified) - { - pSbTab->UpdateFilteredList(); - pSbTab->m_bModified = false; - } - } -} - -void CNeoRoot::FireGameEvent(IGameEvent *event) -{ - const char *type = event->GetName(); - if (Q_strcmp(type, "server_spawn") == 0) - { - g_pVGuiLocalize->ConvertANSIToUnicode(event->GetString("hostname"), m_wszHostname, sizeof(m_wszHostname)); - } - else if (Q_strcmp(type, "game_newmap") == 0) - { - g_pVGuiLocalize->ConvertANSIToUnicode(event->GetString("mapname"), m_wszMap, sizeof(m_wszMap)); - } -} - -void CNeoRoot::OnRelayedKeyCodeTyped(vgui::KeyCode code) -{ - if (m_ns.keys.bcConsole <= KEY_NONE) - { - m_ns.keys.bcConsole = gameuifuncs->GetButtonCodeForBind("neo_toggleconsole"); - } - - if (code == m_ns.keys.bcConsole && code != KEY_BACKQUOTE) - { - // NEO JANK (nullsystem): Prevent toggle being handled twice causing it to not really open. - // This can happen if using the default ` due to the engine enacting this all the time, however calling - // NeoToggleconsole here is required for non-` keys that is toggled while the root panel is opened. The - // engine will call non-` keys by itself it it's in game and the root panel is not opened, or the console is - // opened which generally doesn't endup calling OnRelayedKeyCodeTyped anyway. - NeoToggleconsole(); - return; - } - g_uiCtx.eCode = code; - OnMainLoop(NeoUI::MODE_KEYPRESSED); -} - -void CNeoRoot::OnRelayedKeyTyped(wchar_t unichar) -{ - g_uiCtx.unichar = unichar; - OnMainLoop(NeoUI::MODE_KEYTYPED); -} - -void CNeoRoot::OnMainLoop(const NeoUI::Mode eMode) -{ - int wide, tall; - GetSize(wide, tall); - - const RootState ePrevState = m_state; - - if (eMode == NeoUI::MODE_PAINT) - { - // Draw version info (bottom left corner) - Always - surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); - int textWidth, textHeight; - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); - surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, BUILD_DISPLAY, textWidth, textHeight); - - surface()->DrawSetTextPos(g_uiCtx.iMarginX, tall - textHeight - g_uiCtx.iMarginY); - surface()->DrawPrintText(BUILD_DISPLAY, *BUILD_DISPLAY_SIZE); - } - - // Laading screen just overlays over the root, so don't render anything else if so - if (m_bOnLoadingScreen) - { - return; - } - - static constexpr void (CNeoRoot::*P_FN_MAIN_LOOP[STATE__TOTAL])(const MainLoopParam param) = { - &CNeoRoot::MainLoopRoot, // STATE_ROOT - &CNeoRoot::MainLoopSettings, // STATE_SETTINGS - &CNeoRoot::MainLoopNewGame, // STATE_NEWGAME - &CNeoRoot::MainLoopServerBrowser, // STATE_SERVERBROWSER - - &CNeoRoot::MainLoopMapList, // STATE_MAPLIST - &CNeoRoot::MainLoopServerDetails, // STATE_SERVERDETAILS - &CNeoRoot::MainLoopPlayerList, // STATE_PLAYERLIST - - &CNeoRoot::MainLoopPopup, // STATE_KEYCAPTURE - &CNeoRoot::MainLoopPopup, // STATE_CONFIRMSETTINGS - &CNeoRoot::MainLoopPopup, // STATE_QUIT - &CNeoRoot::MainLoopPopup, // STATE_SERVERPASSWORD - &CNeoRoot::MainLoopPopup, // STATE_SETTINGSRESETDEFAULT - }; - (this->*P_FN_MAIN_LOOP[m_state])(MainLoopParam{.eMode = eMode, .wide = wide, .tall = tall}); - - if (m_state != ePrevState) - { - if (ePrevState == STATE_SETTINGS) - { - V_memcpy(m_iSavedYOffsets, g_uiCtx.iYOffset, NeoUI::SIZEOF_SECTIONS); - } - UpdateControls(); - if (m_state == STATE_SETTINGS && ePrevState >= STATE__POPUPSTART && ePrevState < STATE__TOTAL) - { - V_memcpy(g_uiCtx.iYOffset, m_iSavedYOffsets, NeoUI::SIZEOF_SECTIONS); - } - } -} - -void CNeoRoot::MainLoopRoot(const MainLoopParam param) -{ - const int yTopPos = 0; - int iTitleNWidth, iTitleNHeight; - const int iBtnPlaceXMid = (param.wide / 6); - const int iMargin = (6 * g_uiCtx.iMarginX); - const int iMarginHalf = iMargin * 0.5; - surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, L"n", iTitleNWidth, iTitleNHeight); - g_uiCtx.dPanel.wide = (m_iTitleWidth) +iMargin; - g_uiCtx.dPanel.tall = param.tall - yTopPos; - g_uiCtx.dPanel.x = iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - iMarginHalf; - g_uiCtx.dPanel.y = yTopPos; - g_uiCtx.iYOffset[0] = -8; - g_uiCtx.bgColor = COLOR_NEOPANELNORMALBG; - - NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxRoot"); - NeoUI::BeginSection(true); - { - const int iFlagToMatch = IsInGame() ? FLAG_SHOWINGAME : FLAG_SHOWINMAIN; - for (int i = 0; i < BTNS_TOTAL; ++i) - { - const auto btnInfo = BTNS_INFO[i]; - if (btnInfo.flags & iFlagToMatch) - { - const auto retBtn = NeoUI::Button(m_wszDispBtnTexts[i]); - if (retBtn.bPressed || (i == MMBTN_QUIT && !IsInGame() && NeoUI::Bind(KEY_ESCAPE))) - { - surface()->PlaySound("ui/buttonclickrelease.wav"); - if (btnInfo.gamemenucommand) - { - m_state = STATE_ROOT; - GetGameUI()->SendMainMenuCommand(btnInfo.gamemenucommand); - } - else if (btnInfo.nextState < STATE__TOTAL) - { - m_state = btnInfo.nextState; - if (m_state == STATE_SETTINGS) - { - NeoSettingsRestore(&m_ns); - } - } - } - if (retBtn.bMouseHover && i != m_iHoverBtn) - { - // Sound rollover feedback - surface()->PlaySound("ui/buttonrollover.wav"); - m_iHoverBtn = i; - } - } - } - } - NeoUI::EndSection(); - g_uiCtx.bgColor = COLOR_TRANSPARENT; - - const int iBtnWide = m_iTitleWidth + iMargin; - const int iRightXPos = iBtnPlaceXMid + (iBtnWide / 2) + iMarginHalf; - int iRightSideYStart = yTopPos; - - // Draw top steam section portion - { - // Draw title - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl); - surface()->DrawSetTextColor(COLOR_NEOTITLE); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), yTopPos + m_iTitleHeight); - surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); - - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), yTopPos + m_iTitleHeight + (iTitleNHeight * 0.7)); - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); - surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); - -#if (0) - surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); - ISteamUser *steamUser = steamapicontext->SteamUser(); - ISteamFriends *steamFriends = steamapicontext->SteamFriends(); - if (steamUser && steamFriends) - { - const int iSteamPlaceXStart = iRightXPos; - - // Draw player info (top left corner) - const CSteamID steamID = steamUser->GetSteamID(); - if (!m_avImage) - { - m_avImage = new CAvatarImage; - m_avImage->SetAvatarSteamID(steamID, k_EAvatarSize64x64); - } - m_avImage->SetPos(iSteamPlaceXStart + g_uiCtx.iMarginX, iRightSideYStart + g_uiCtx.iMarginY); - m_avImage->SetSize(g_iAvatar, g_iAvatar); - m_avImage->Paint(); - - wchar_t wszDisplayName[NEO_MAX_DISPLAYNAME]; - GetClNeoDisplayName(wszDisplayName, neo_name.GetString(), neo_clantag.GetString(), cl_onlysteamnick.GetBool()); - - const char *szNeoName = neo_name.GetString(); - const bool bUseNeoName = (szNeoName && szNeoName[0] != '\0' && !cl_onlysteamnick.GetBool()); - - int iMainTextWidth, iMainTextHeight; - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTHEADING].hdl); - surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTHEADING].hdl, wszDisplayName, iMainTextWidth, iMainTextHeight); - - const int iMainTextStartPosX = g_uiCtx.iMarginX + g_iAvatar + g_uiCtx.iMarginX; - surface()->DrawSetTextPos(iSteamPlaceXStart + iMainTextStartPosX, iRightSideYStart + g_uiCtx.iMarginY); - surface()->DrawPrintText(wszDisplayName, V_wcslen(wszDisplayName)); - - if (bUseNeoName) - { - char szTextBuf[64]; - V_sprintf_safe(szTextBuf, "(Steam name: %s)", steamFriends->GetPersonaName()); - wchar_t wszTextBuf[64] = {}; - g_pVGuiLocalize->ConvertANSIToUnicode(szTextBuf, wszTextBuf, sizeof(wszTextBuf)); - - int iSteamSubTextWidth, iSteamSubTextHeight; - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); - surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, wszTextBuf, iSteamSubTextWidth, iSteamSubTextHeight); - - const int iRightOfNicknameXPos = iSteamPlaceXStart + iMainTextStartPosX + iMainTextWidth + g_uiCtx.iMarginX; - // If we have space on the right, set it, otherwise on top of nickname - if ((iRightOfNicknameXPos + iSteamSubTextWidth) < param.wide) - { - surface()->DrawSetTextPos(iRightOfNicknameXPos, iRightSideYStart + g_uiCtx.iMarginY); - } - else - { - surface()->DrawSetTextPos(iSteamPlaceXStart + iMainTextStartPosX, - iRightSideYStart - iSteamSubTextHeight); - } - surface()->DrawPrintText(wszTextBuf, V_strlen(szTextBuf)); - } - - static constexpr const wchar_t *WSZ_PERSONA_STATES[k_EPersonaStateMax] = { - L"Offline", L"Online", L"Busy", L"Away", L"Snooze", L"Trading", L"Looking to play" - }; - const auto eCurStatus = steamFriends->GetPersonaState(); - int iStatusTall = 0; - if (eCurStatus != k_EPersonaStateMax) - { - wchar_t wszStatusTotal[48]; - const int iStatusTotalSize = V_swprintf_safe(wszStatusTotal, L"%ls%ls", - WSZ_PERSONA_STATES[static_cast(eCurStatus)], - neo_cl_streamermode.GetBool() ? L" [Streamer mode on]" : L""); - const int iStatusTextStartPosY = g_uiCtx.iMarginY + iMainTextHeight + g_uiCtx.iMarginY; - - [[maybe_unused]] int iStatusWide; - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); - surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, wszStatusTotal, iStatusWide, iStatusTall); - surface()->DrawSetTextPos(iSteamPlaceXStart + iMainTextStartPosX, - iRightSideYStart + iStatusTextStartPosY); - surface()->DrawPrintText(wszStatusTotal, iStatusTotalSize); - } - - // Put the news title in either from avatar or text end Y position - const int iTextTotalTall = iMainTextHeight + iStatusTall; - iRightSideYStart += (g_uiCtx.iMarginX * 2) + ((iTextTotalTall > g_iAvatar) ? iTextTotalTall : g_iAvatar); - } -#endif (0) - } - -#if (0) - g_uiCtx.dPanel.x = iRightXPos; - g_uiCtx.dPanel.y = iRightSideYStart; - if (IsInGame()) - { - g_uiCtx.dPanel.wide = m_flWideAs43 * 0.7f; - g_uiCtx.flWgXPerc = 0.25f; - } - else - { - g_uiCtx.dPanel.wide = GetWide() - iRightXPos - (g_uiCtx.iMarginX * 2); - } - NeoUI::BeginSection(); - { - if (IsInGame()) - { - // Show the current server's information - NeoUI::Label(L"Hostname:", m_wszHostname); - NeoUI::Label(L"Map:", m_wszMap); - NeoUI::Label(L"Game mode:", NEO_GAME_TYPE_DESC_STRS[NEORules()->GetGameType()].wszStr); - // TODO: more info, g_PR, scoreboard stuff, etc... - } - else - { - // Show the news - NeoUI::SwapFont(NeoUI::FONT_NTHEADING); - NeoUI::Label(L"News"); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - - g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_LEFT; - NeoUI::SwapColorNormal(COLOR_TRANSPARENT); - for (int i = 0; i < m_iNewsSize; ++i) - { - if (NeoUI::Button(m_news[i].wszTitle).bPressed) - { - NeoUI::OpenURL(SZ_WEBSITE, m_news[i].szSitePath); - m_bShowBrowserLabel = true; - } - } - - if (m_bShowBrowserLabel) - { - surface()->DrawSetTextColor(Color(178, 178, 178, 178)); - NeoUI::Label(L"Link opened in your web browser"); - surface()->DrawSetTextColor(COLOR_NEOPANELTEXTNORMAL); - } - - g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_CENTER; - NeoUI::SwapColorNormal(COLOR_NEOPANELACCENTBG); - } - } - NeoUI::EndSection(); -#endif (0) - NeoUI::EndContext(); -} - -void CNeoRoot::MainLoopSettings(const MainLoopParam param) -{ - struct NeoSettingsFunc - { - void (*func)(NeoSettings *); - bool bUISectionManaged; - }; - static constexpr NeoSettingsFunc P_FN[] = { - {NeoSettings_General, false}, - {NeoSettings_Keys, false}, - {NeoSettings_Mouse, false}, - {NeoSettings_Audio, false}, - {NeoSettings_Video, false}, - {NeoSettings_Crosshair, true}, - }; - static const wchar_t *WSZ_TABS_LABELS[ARRAYSIZE(P_FN)] = { - L"Multiplayer", L"Keybinds", L"Mouse", L"Audio", L"Video", L"Crosshair" - }; - - m_ns.iNextBinding = -1; - - const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); - - g_uiCtx.dPanel.wide = g_iRootSubPanelWide; - g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); - g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; - g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; - NeoUI::BeginContext(&g_uiCtx, param.eMode, g_pNeoRoot->m_wszDispBtnTexts[MMBTN_OPTIONS], "CtxOptions"); - { - NeoUI::BeginSection(); - { - NeoUI::Tabs(WSZ_TABS_LABELS, ARRAYSIZE(WSZ_TABS_LABELS), &m_ns.iCurTab); - } - NeoUI::EndSection(); - if (!P_FN[m_ns.iCurTab].bUISectionManaged) - { - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * g_iRowsInScreen; - NeoUI::BeginSection(true); - } - { - P_FN[m_ns.iCurTab].func(&m_ns); - } - if (!P_FN[m_ns.iCurTab].bUISectionManaged) - { - NeoUI::EndSection(); - } - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; - NeoUI::BeginSection(); - { - NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); - { - if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_ns.bBack = true; - } - if (NeoUI::Button(L"Legacy").bPressed) - { - g_pNeoRoot->GetGameUI()->SendMainMenuCommand("OpenOptionsDialog"); - } - if (NeoUI::Button(L"Default").bPressed) - { - m_state = STATE_SETTINGSRESETDEFAULT; - engine->GetVoiceTweakAPI()->EndVoiceTweakMode(); - } - if (m_ns.bModified) - { - if (NeoUI::Button(L"Revert").bPressed) - { - NeoSettingsRestore(&m_ns); - } - if (NeoUI::Button(L"Accept").bPressed) - { - NeoSettingsSave(&m_ns); - } - } - } - NeoUI::EndHorizontal(); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - } - NeoUI::EndSection(); - } - NeoUI::EndContext(); - if (!m_ns.bModified && g_uiCtx.bValueEdited) - { - m_ns.bModified = true; - } - - if (m_ns.bBack) - { - m_ns.bBack = false; - m_state = (m_ns.bModified) ? STATE_CONFIRMSETTINGS : STATE_ROOT; - engine->GetVoiceTweakAPI()->EndVoiceTweakMode(); - } - else if (m_ns.iNextBinding >= 0) - { - m_iBindingIdx = m_ns.iNextBinding; - m_ns.iNextBinding = -1; - V_swprintf_safe(m_wszBindingText, L"Change binding for: %ls", - m_ns.keys.vBinds[m_iBindingIdx].wszDisplayText); - m_state = STATE_KEYCAPTURE; - engine->StartKeyTrapMode(); - } -} - -void CNeoRoot::MainLoopNewGame(const MainLoopParam param) -{ - const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); - g_uiCtx.dPanel.wide = g_iRootSubPanelWide; - g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); - g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen + 1); - g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; - NeoUI::BeginContext(&g_uiCtx, param.eMode, m_wszDispBtnTexts[MMBTN_CREATESERVER], "CtxNewGame"); - { - NeoUI::BeginSection(true); - { - if (NeoUI::Button(L"Map", m_newGame.wszMap).bPressed) - { - m_state = STATE_MAPLIST; - } - NeoUI::TextEdit(L"Hostname", m_newGame.wszHostname, SZWSZ_LEN(m_newGame.wszHostname)); - NeoUI::SliderInt(L"Max players", &m_newGame.iMaxPlayers, 1, 32); - NeoUI::TextEdit(L"Password", m_newGame.wszPassword, SZWSZ_LEN(m_newGame.wszPassword)); - NeoUI::RingBoxBool(L"Friendly fire", &m_newGame.bFriendlyFire); - } - NeoUI::EndSection(); - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; - NeoUI::BeginSection(); - { - NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); - { - if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_ROOT; - } - NeoUI::Pad(); - NeoUI::Pad(); - NeoUI::Pad(); - if (NeoUI::Button(L"Start").bPressed) - { - if (IsInGame()) - { - engine->ClientCmd_Unrestricted("disconnect"); - } - - static constexpr int ENTRY_MAX = 64; - char szMap[ENTRY_MAX + 1] = {}; - char szHostname[ENTRY_MAX + 1] = {}; - char szPassword[ENTRY_MAX + 1] = {}; - g_pVGuiLocalize->ConvertUnicodeToANSI(m_newGame.wszMap, szMap, sizeof(szMap)); - g_pVGuiLocalize->ConvertUnicodeToANSI(m_newGame.wszHostname, szHostname, sizeof(szHostname)); - g_pVGuiLocalize->ConvertUnicodeToANSI(m_newGame.wszPassword, szPassword, sizeof(szPassword)); - - ConVarRef("hostname").SetValue(szHostname); - ConVarRef("sv_password").SetValue(szPassword); - ConVarRef("mp_friendlyfire").SetValue(m_newGame.bFriendlyFire); - - char cmdStr[256]; - V_sprintf_safe(cmdStr, "maxplayers %d; progress_enable; map \"%s\"", m_newGame.iMaxPlayers, szMap); - engine->ClientCmd_Unrestricted(cmdStr); - - if (g_pNeoLoading) - { - V_wcscpy_safe(g_pNeoLoading->m_wszLoadingMap, m_newGame.wszMap); - } - - m_state = STATE_ROOT; - } - } - NeoUI::EndHorizontal(); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - } - NeoUI::EndSection(); - } - NeoUI::EndContext(); -} - -void CNeoRoot::MainLoopServerBrowser(const MainLoopParam param) -{ - static const wchar_t *GS_NAMES[GS__TOTAL] = { - L"Internet", L"LAN", L"Friends", L"Fav", L"History", L"Spec" - }; - - static const wchar_t *ANTICHEAT_LABELS[ANTICHEAT__TOTAL] = { - L"", L"On", L"Off" - }; - - bool bEnterServer = false; - const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); - g_uiCtx.dPanel.wide = g_iRootSubPanelWide; - g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); - g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * 2; - g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; - NeoUI::BeginContext(&g_uiCtx, param.eMode, m_wszDispBtnTexts[MMBTN_FINDSERVER], "CtxServerBrowser"); - { - bool bForceRefresh = false; - NeoUI::BeginSection(); - { - const int iPrevTab = m_iServerBrowserTab; - NeoUI::Tabs(GS_NAMES, ARRAYSIZE(GS_NAMES), &m_iServerBrowserTab); - if (iPrevTab != m_iServerBrowserTab) - { - m_iSelectedServer = -1; - } - if (!m_serverBrowser[m_iServerBrowserTab].m_bReloadedAtLeastOnce) - { - bForceRefresh = true; - m_serverBrowser[m_iServerBrowserTab].m_bReloadedAtLeastOnce = true; - } - g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_LEFT; - NeoUI::BeginHorizontal(1); - { - static constexpr const wchar_t *SBLABEL_NAMES[GSIW__TOTAL] = { - L"Lock", L"VAC", L"Name", L"Map", L"Players", L"Ping", - }; - - for (int i = 0; i < GS__TOTAL; ++i) - { - surface()->DrawSetColor((m_sortCtx.col == i) ? COLOR_NEOPANELACCENTBG : COLOR_NEOPANELNORMALBG); - g_uiCtx.iHorizontalWidth = g_iGSIX[i]; - if (NeoUI::Button(SBLABEL_NAMES[i]).bPressed) - { - if (m_sortCtx.col == i) - { - m_sortCtx.bDescending = !m_sortCtx.bDescending; - } - else - { - m_sortCtx.col = static_cast(i); - } - m_bSBFiltModified = true; - } - - if (param.eMode == NeoUI::MODE_PAINT && m_sortCtx.col == i) - { - int iHintTall = g_uiCtx.iMarginY / 3; - surface()->DrawSetColor(COLOR_NEOPANELTEXTNORMAL); - if (!m_sortCtx.bDescending) - { - NeoUI::GCtxDrawFilledRectXtoX(-g_uiCtx.iHorizontalWidth, 0, 0, iHintTall); - } - else - { - NeoUI::GCtxDrawFilledRectXtoX(-g_uiCtx.iHorizontalWidth, g_uiCtx.iRowTall - iHintTall, 0, g_uiCtx.iRowTall); - } - surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); - } - } - } - - // TODO: Should give proper controls over colors through NeoUI - surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); - surface()->DrawSetTextColor(COLOR_NEOPANELTEXTNORMAL); - NeoUI::EndHorizontal(); - g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_CENTER; - } - NeoUI::EndSection(); - static constexpr int FILTER_ROWS = 5; - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen - 1); - if (m_bShowFilterPanel) g_uiCtx.dPanel.tall -= g_uiCtx.iRowTall * FILTER_ROWS; - NeoUI::BeginSection(true); - { - if (m_serverBrowser[m_iServerBrowserTab].m_filteredServers.IsEmpty()) - { - wchar_t wszInfo[128]; - if (m_serverBrowser[m_iServerBrowserTab].m_bSearching) - { - V_swprintf_safe(wszInfo, L"Searching %ls queries...", GS_NAMES[m_iServerBrowserTab]); - } - else - { - V_swprintf_safe(wszInfo, L"No %ls queries found. Press Refresh to re-check", GS_NAMES[m_iServerBrowserTab]); - } - g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; - NeoUI::Label(wszInfo); - g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_LEFT; - } - else - { - // NEO TODO (nullsystem): This is fine since there isn't going to be much servers, it'll - // handle even couple of 100s ok. However if the amount is a concern, NeoUI can be - // expanded to give Y-offset in the form of filtered array range so it only loops - // through what's needed instead. - const auto *sbTab = &m_serverBrowser[m_iServerBrowserTab]; - for (int i = 0; i < sbTab->m_filteredServers.Size(); ++i) - { - const auto &server = sbTab->m_filteredServers[i]; - bool bSkipServer = false; - if (m_sbFilters.bServerNotFull && server.m_nPlayers == server.m_nMaxPlayers) bSkipServer = true; - else if (m_sbFilters.bHasUsersPlaying && server.m_nPlayers == 0) bSkipServer = true; - else if (m_sbFilters.bIsNotPasswordProtected && server.m_bPassword) bSkipServer = true; - else if (m_sbFilters.iAntiCheat == ANTICHEAT_OFF && server.m_bSecure) bSkipServer = true; - else if (m_sbFilters.iAntiCheat == ANTICHEAT_ON && !server.m_bSecure) bSkipServer = true; - else if (m_sbFilters.iMaxPing != 0 && server.m_nPing > m_sbFilters.iMaxPing) bSkipServer = true; - if (bSkipServer) - { - continue; - } - - const auto btn = NeoUI::Button(L""); - if (btn.bPressed) // Dummy button, draw over it in paint - { - m_iSelectedServer = i; - if (btn.bKeyPressed || btn.bMouseDoublePressed) - { - bEnterServer = true; - } - } - - if (param.eMode == NeoUI::MODE_PAINT) - { - Color drawColor = COLOR_NEOPANELNORMALBG; - if (m_iSelectedServer == i) drawColor = COLOR_NEOPANELACCENTBG; - if (btn.bMouseHover) drawColor = COLOR_NEOPANELSELECTBG; - - vgui::surface()->DrawSetColor(drawColor); - NeoUI::GCtxDrawFilledRectXtoX(0, -g_uiCtx.iRowTall, g_uiCtx.dPanel.wide, 0); - - ServerBrowserDrawRow(server); - } - } - } - } - surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); - NeoUI::EndSection(); - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; - if (m_bShowFilterPanel) g_uiCtx.dPanel.tall += g_uiCtx.iRowTall * FILTER_ROWS; - NeoUI::BeginSection(); - { - NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 6); - { - if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_ROOT; - } - if (NeoUI::Button(L"Legacy").bPressed) - { - GetGameUI()->SendMainMenuCommand("OpenServerBrowser"); - } - if (NeoUI::Button(m_bShowFilterPanel ? L"Hide Filters" : L"Show Filters").bPressed) - { - m_bShowFilterPanel = !m_bShowFilterPanel; - } - if (m_iSelectedServer >= 0) - { - if (NeoUI::Button(L"Details").bPressed) - { - m_state = STATE_SERVERDETAILS; - const auto *gameServer = &m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; - m_serverPlayers.RequestList(gameServer->m_NetAdr.GetIP(), gameServer->m_NetAdr.GetQueryPort()); - } - } - else - { - NeoUI::Pad(); - } - if (NeoUI::Button(L"Refresh").bPressed || bForceRefresh) - { - m_iSelectedServer = -1; - ISteamMatchmakingServers *steamMM = steamapicontext->SteamMatchmakingServers(); - CNeoServerList *pServerBrowser = &m_serverBrowser[m_iServerBrowserTab]; - pServerBrowser->m_servers.RemoveAll(); - pServerBrowser->m_filteredServers.RemoveAll(); - if (pServerBrowser->m_hdlRequest) - { - steamMM->CancelQuery(pServerBrowser->m_hdlRequest); - steamMM->ReleaseRequest(pServerBrowser->m_hdlRequest); - pServerBrowser->m_hdlRequest = nullptr; - } - pServerBrowser->RequestList(); - } - if (m_iSelectedServer >= 0) - { - if (bEnterServer || NeoUI::Button(L"Enter").bPressed) - { - if (IsInGame()) - { - engine->ClientCmd_Unrestricted("disconnect"); - } - - ConVarRef("password").SetValue(""); - V_memset(m_wszServerPassword, 0, sizeof(m_wszServerPassword)); - - // NEO NOTE (nullsystem): Deal with password protected server - const auto gameServer = m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; - if (gameServer.m_bPassword) - { - m_state = STATE_SERVERPASSWORD; - } - else - { - char connectCmd[256]; - const char *szAddress = gameServer.m_NetAdr.GetConnectionAddressString(); - V_sprintf_safe(connectCmd, "progress_enable; wait; connect %s", szAddress); - engine->ClientCmd_Unrestricted(connectCmd); - - if (g_pNeoLoading) - { - g_pVGuiLocalize->ConvertANSIToUnicode(gameServer.m_szMap, - g_pNeoLoading->m_wszLoadingMap, - sizeof(g_pNeoLoading->m_wszLoadingMap)); - } - - m_state = STATE_ROOT; - } - } - } - } - NeoUI::EndHorizontal(); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - if (m_bShowFilterPanel) - { - NeoUI::RingBoxBool(L"Server not full", &m_sbFilters.bServerNotFull); - NeoUI::RingBoxBool(L"Has users playing", &m_sbFilters.bHasUsersPlaying); - NeoUI::RingBoxBool(L"Is not password protected", &m_sbFilters.bIsNotPasswordProtected); - NeoUI::RingBox(L"Anti-cheat", ANTICHEAT_LABELS, ARRAYSIZE(ANTICHEAT_LABELS), &m_sbFilters.iAntiCheat); - NeoUI::SliderInt(L"Maximum ping", &m_sbFilters.iMaxPing, 0, 500, 10, L"No limit"); - } - } - NeoUI::EndSection(); - } - NeoUI::EndContext(); - -} - -void CNeoRoot::MainLoopMapList(const MainLoopParam param) -{ - const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); - g_uiCtx.dPanel.wide = g_iRootSubPanelWide; - g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); - g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen + 1); - g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; - NeoUI::BeginContext(&g_uiCtx, param.eMode, L"Pick map", "CtxMapPicker"); - { - NeoUI::BeginSection(true); - { - for (auto &wszMap : m_vWszMaps) - { - if (NeoUI::Button(wszMap.wszName).bPressed) - { - V_wcscpy_safe(m_newGame.wszMap, wszMap.wszName); - m_state = STATE_NEWGAME; - } - } - } - NeoUI::EndSection(); - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; - NeoUI::BeginSection(); - { - NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); - { - if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_NEWGAME; - } - } - NeoUI::EndHorizontal(); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - } - NeoUI::EndSection(); - } - NeoUI::EndContext(); -} - -void CNeoRoot::MainLoopServerDetails(const MainLoopParam param) -{ - const auto *gameServer = &m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; - const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); - g_uiCtx.dPanel.wide = g_iRootSubPanelWide; - g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); - g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * 6; - g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; - NeoUI::BeginContext(&g_uiCtx, param.eMode, L"Server details", "CtxServerDetail"); - { - NeoUI::BeginSection(true); - { - const bool bP = param.eMode == NeoUI::MODE_PAINT; - wchar_t wszText[128]; - if (bP) g_pVGuiLocalize->ConvertANSIToUnicode(gameServer->GetName(), wszText, sizeof(wszText)); - NeoUI::Label(L"Name:", wszText); - if (!neo_cl_streamermode.GetBool()) - { - if (bP) g_pVGuiLocalize->ConvertANSIToUnicode(gameServer->m_NetAdr.GetConnectionAddressString(), wszText, sizeof(wszText)); - NeoUI::Label(L"Address:", wszText); - } - if (bP) g_pVGuiLocalize->ConvertANSIToUnicode(gameServer->m_szMap, wszText, sizeof(wszText)); - NeoUI::Label(L"Map:", wszText); - if (bP) V_swprintf_safe(wszText, L"%d/%d", gameServer->m_nPlayers, gameServer->m_nMaxPlayers); - NeoUI::Label(L"Players:", wszText); - if (bP) V_swprintf_safe(wszText, L"%ls", gameServer->m_bSecure ? L"Enabled" : L"Disabled"); - NeoUI::Label(L"VAC:", wszText); - if (bP) V_swprintf_safe(wszText, L"%d", gameServer->m_nPing); - NeoUI::Label(L"Ping:", wszText); - - // TODO: Header same-style as serverlist's header - } - NeoUI::EndSection(); - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = (iTallTotal - g_uiCtx.iRowTall) - g_uiCtx.dPanel.tall; - NeoUI::BeginSection(); - { - if (!neo_cl_streamermode.GetBool()) - { - if (m_serverPlayers.m_players.IsEmpty()) - { - g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; - NeoUI::Label(L"There are no players in the server."); - g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_LEFT; - } - else - { - for (const auto &player : m_serverPlayers.m_players) - { - NeoUI::Label(player.wszName); - // TODO - } - } - } - } - NeoUI::EndSection(); - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; - NeoUI::BeginSection(); - { - NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); - { - if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_SERVERBROWSER; - } - } - NeoUI::EndHorizontal(); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - } - NeoUI::EndSection(); - } - NeoUI::EndContext(); -} - -void CNeoRoot::MainLoopPlayerList(const MainLoopParam param) -{ - if (IsInGame()) - { - const int iTallTotal = g_uiCtx.iRowTall * (g_iRowsInScreen + 2); - g_uiCtx.dPanel.wide = g_iRootSubPanelWide; - g_uiCtx.dPanel.x = (param.wide / 2) - (g_iRootSubPanelWide / 2); - g_uiCtx.dPanel.y = (param.tall / 2) - (iTallTotal / 2); - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen + 1); - g_uiCtx.bgColor = COLOR_NEOPANELFRAMEBG; - NeoUI::BeginContext(&g_uiCtx, param.eMode, L"Player list", "CtxPlayerList"); - { - NeoUI::BeginSection(true); - { - g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_LEFT; - for (int i = 1; i <= gpGlobals->maxClients; i++) - { - if (!g_PR->IsConnected(i) || g_PR->IsHLTV(i) || g_PR->IsFakePlayer(i)) - { - continue; - } - - const bool bOwnLocalPlayer = g_PR->IsLocalPlayer(i); - const bool bPlayerMuted = GetClientVoiceMgr()->IsPlayerBlocked(i); - const char *szPlayerName = g_PR->GetPlayerName(i); - wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH + 1]; - g_pVGuiLocalize->ConvertANSIToUnicode(szPlayerName, wszPlayerName, sizeof(wszPlayerName)); - - wchar_t wszInfo[256]; - V_swprintf_safe(wszInfo, L"%ls%ls", bOwnLocalPlayer ? L"[LOCAL] " : bPlayerMuted ? L"[MUTED] " : L"[VOICE] ", wszPlayerName); - if (NeoUI::Button(wszInfo).bPressed) - { - if (!bOwnLocalPlayer) GetClientVoiceMgr()->SetPlayerBlockedState(i, !bPlayerMuted); - } - } - g_uiCtx.eButtonTextStyle = NeoUI::TEXTSTYLE_CENTER; - } - NeoUI::EndSection(); - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall; - NeoUI::BeginSection(); - { - NeoUI::SwapFont(NeoUI::FONT_NTHORIZSIDES); - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); - { - if (NeoUI::Button(L"Back (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_ROOT; - } - } - NeoUI::EndHorizontal(); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - } - NeoUI::EndSection(); - } - NeoUI::EndContext(); - } - else - { - m_state = STATE_ROOT; - } -} - -void CNeoRoot::MainLoopPopup(const MainLoopParam param) -{ - surface()->DrawSetColor(COLOR_NEOPANELPOPUPBG); - surface()->DrawFilledRect(0, 0, param.wide, param.tall); - const int tallSplit = param.tall / 3; - surface()->DrawSetColor(COLOR_NEOPANELNORMALBG); - surface()->DrawFilledRect(0, tallSplit, param.wide, param.tall - tallSplit); - - g_uiCtx.dPanel.wide = g_iRootSubPanelWide * 0.75f; - g_uiCtx.dPanel.tall = tallSplit; - g_uiCtx.dPanel.x = (param.wide / 2) - (g_uiCtx.dPanel.wide / 2); - g_uiCtx.dPanel.y = tallSplit + (tallSplit / 2) - g_uiCtx.iRowTall; - g_uiCtx.bgColor = COLOR_TRANSPARENT; - if (m_state == STATE_SERVERPASSWORD) - { - g_uiCtx.dPanel.y -= g_uiCtx.iRowTall; - } - // Technically can get away with have a common context name, since these dialogs - // don't do anything special with it - NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxCommonPopupDlg"); - { - NeoUI::BeginSection(true); - { - g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; - NeoUI::SwapFont(NeoUI::FONT_NTLARGE); - switch (m_state) - { - case STATE_KEYCAPTURE: - { - NeoUI::Label(m_wszBindingText); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - NeoUI::Label(L"Press ESC to cancel or DEL to remove keybind"); - } - break; - case STATE_CONFIRMSETTINGS: - { - NeoUI::Label(L"Settings changed: Do you want to apply the settings?"); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - NeoUI::BeginHorizontal((g_uiCtx.dPanel.wide / 3) - g_uiCtx.iMarginX, g_uiCtx.iMarginX); - { - g_uiCtx.iLayoutX = (g_uiCtx.iMarginX / 2); - if (NeoUI::Button(L"Save (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) - { - NeoSettingsSave(&m_ns); - m_state = STATE_ROOT; - } - if (NeoUI::Button(L"Discard").bPressed) - { - m_state = STATE_ROOT; - } - if (NeoUI::Button(L"Cancel (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_SETTINGS; - } - } - NeoUI::EndHorizontal(); - } - break; - case STATE_QUIT: - { - NeoUI::Label(L"Do you want to quit the game?"); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 3); - { - if (NeoUI::Button(L"Quit (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) - { - engine->ClientCmd_Unrestricted("quit"); - } - NeoUI::Pad(); - if (NeoUI::Button(L"Cancel (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_ROOT; - } - } - NeoUI::EndHorizontal(); - } - break; - case STATE_SERVERPASSWORD: - { - NeoUI::Label(L"Enter the server password"); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - g_uiCtx.bTextEditIsPassword = true; - NeoUI::TextEdit(L"Password:", m_wszServerPassword, SZWSZ_LEN(m_wszServerPassword)); - g_uiCtx.bTextEditIsPassword = false; - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 3); - { - if (NeoUI::Button(L"Enter (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) - { - char szServerPassword[ARRAYSIZE(m_wszServerPassword)]; - g_pVGuiLocalize->ConvertUnicodeToANSI(m_wszServerPassword, szServerPassword, sizeof(szServerPassword)); - ConVarRef("password").SetValue(szServerPassword); - V_memset(m_wszServerPassword, 0, sizeof(m_wszServerPassword)); - - const auto gameServer = m_serverBrowser[m_iServerBrowserTab].m_filteredServers[m_iSelectedServer]; - char connectCmd[256]; - const char *szAddress = gameServer.m_NetAdr.GetConnectionAddressString(); - V_sprintf_safe(connectCmd, "progress_enable; wait; connect %s", szAddress); - engine->ClientCmd_Unrestricted(connectCmd); - - m_state = STATE_ROOT; - } - NeoUI::Pad(); - if (NeoUI::Button(L"Cancel (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - V_memset(m_wszServerPassword, 0, sizeof(m_wszServerPassword)); - m_state = STATE_SERVERBROWSER; - } - } - NeoUI::EndHorizontal(); - } - break; - case STATE_SETTINGSRESETDEFAULT: - { - NeoUI::Label(L"Do you want to reset your settings back to default?"); - NeoUI::SwapFont(NeoUI::FONT_NTNORMAL); - NeoUI::BeginHorizontal((g_uiCtx.dPanel.wide / 3) - g_uiCtx.iMarginX, g_uiCtx.iMarginX); - { - if (NeoUI::Button(L"Yes (Enter)").bPressed || NeoUI::Bind(KEY_ENTER)) - { - NeoSettingsResetToDefault(&m_ns); - m_state = STATE_SETTINGS; - } - NeoUI::Pad(); - if (NeoUI::Button(L"No (ESC)").bPressed || NeoUI::Bind(KEY_ESCAPE)) - { - m_state = STATE_SETTINGS; - } - } - NeoUI::EndHorizontal(); - } - break; - default: - break; - } - } - NeoUI::EndSection(); - } - NeoUI::EndContext(); -} - -void CNeoRoot::HTTPCallbackRequest(HTTPRequestCompleted_t *request, bool bIOFailure) -{ - ISteamHTTP *http = steamapicontext->SteamHTTP(); - if (request->m_bRequestSuccessful && !bIOFailure) - { - uint32 unBodySize = 0; - http->GetHTTPResponseBodySize(request->m_hRequest, &unBodySize); - - if (unBodySize > 0) - { - uint8 *pData = new uint8[unBodySize + 1]; - http->GetHTTPResponseBodyData(request->m_hRequest, pData, unBodySize); - - CUtlBuffer buf(0, 0, CUtlBuffer::TEXT_BUFFER); - buf.CopyBuffer(pData, unBodySize); - filesystem->WriteFile("news.txt", nullptr, buf); - ReadNewsFile(buf); - - delete[] pData; - } - } - http->ReleaseHTTPRequest(request->m_hRequest); -} - -void CNeoRoot::ReadNewsFile(CUtlBuffer &buf) -{ - buf.SeekGet(CUtlBuffer::SEEK_HEAD, 0); - m_iNewsSize = 0; - while (buf.IsValid() && m_iNewsSize < MAX_NEWS) - { - // TSV row: Path\tDate\tTitle - char szLine[512] = {}; - buf.GetLine(szLine, ARRAYSIZE(szLine) - 1); - char *pszDate = strchr(szLine, '\t'); - if (!pszDate) - { - continue; - } - - *pszDate = '\0'; - ++pszDate; - if (!*pszDate) - { - continue; - } - - char *pszTitle = strchr(pszDate, '\t'); - if (!pszTitle) - { - continue; - } - - *pszTitle = '\0'; - ++pszTitle; - if (!*pszTitle) - { - continue; - } - - V_strcpy_safe(m_news[m_iNewsSize].szSitePath, szLine); - wchar_t wszDate[12]; - wchar_t wszTitle[235]; - g_pVGuiLocalize->ConvertANSIToUnicode(pszDate, wszDate, sizeof(wszDate)); - g_pVGuiLocalize->ConvertANSIToUnicode(pszTitle, wszTitle, sizeof(wszTitle)); - V_swprintf_safe(m_news[m_iNewsSize].wszTitle, L"%ls: %ls", wszDate, wszTitle); - ++m_iNewsSize; - } -} - -void CNeoRoot::OnFileSelected(const char *szFullpath) -{ - ((m_ns.crosshair.eFileIOMode == vgui::FOD_OPEN) ? - &ImportCrosshair : &ExportCrosshair)(&m_ns.crosshair.info, szFullpath); -} - -// NEO NOTE (nullsystem): NeoRootCaptureESC is so that ESC keybinds can be recognized by non-root states, but root -// state still want to have ESC handled by the game as IsVisible/HasFocus isn't reliable indicator to depend on. -// This goes along with NeoToggleconsole which if the toggleconsole is activated on non-root state that can end up -// blocking ESC key from being usable in-game, so have to force it back to root state first to help with -// NeoRootCaptureESC condition. So this will do. - -bool NeoRootCaptureESC() -{ - return (g_pNeoRoot && g_pNeoRoot->IsEnabled() && g_pNeoRoot->m_state != STATE_ROOT); -} - -void NeoToggleconsole() -{ - if (neo_cl_toggleconsole.GetBool()) - { - if (engine->IsInGame() && g_pNeoRoot) - { - g_pNeoRoot->m_state = STATE_ROOT; - } - // NEO JANK (nullsystem): con_enable 1 is required to allow toggleconsole to - // work and using the legacy settings will alter that value. - // It's in here rather than startup so it doesn't trigger the console on startup - ConVarRef("con_enable").SetValue(true); - engine->ClientCmd_Unrestricted("toggleconsole"); - } -} diff --git a/mp/src/game/client/neo/ui/neo_root.cpp b/mp/src/game/client/neo/ui/neo_root.cpp index ab9f85c1e..ceabbdb6a 100644 --- a/mp/src/game/client/neo/ui/neo_root.cpp +++ b/mp/src/game/client/neo/ui/neo_root.cpp @@ -474,25 +474,10 @@ void CNeoRoot::OnMainLoop(const NeoUI::Mode eMode) const RootState ePrevState = m_state; - if (eMode == NeoUI::MODE_PAINT) - { - // Draw version info (bottom left corner) - Always - surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); - int textWidth, textHeight; - surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); - surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, BUILD_DISPLAY, textWidth, textHeight); - - surface()->DrawSetTextPos(g_uiCtx.iMarginX, tall - textHeight - g_uiCtx.iMarginY); - surface()->DrawPrintText(BUILD_DISPLAY, *BUILD_DISPLAY_SIZE); - } - // Laading screen just overlays over the root, so don't render anything else if so - if (m_bOnLoadingScreen) + if (!m_bOnLoadingScreen) { - return; - } - - static constexpr void (CNeoRoot::*P_FN_MAIN_LOOP[STATE__TOTAL])(const MainLoopParam param) = { + static constexpr void (CNeoRoot:: * P_FN_MAIN_LOOP[STATE__TOTAL])(const MainLoopParam param) = { &CNeoRoot::MainLoopRoot, // STATE_ROOT &CNeoRoot::MainLoopSettings, // STATE_SETTINGS &CNeoRoot::MainLoopNewGame, // STATE_NEWGAME @@ -507,36 +492,49 @@ void CNeoRoot::OnMainLoop(const NeoUI::Mode eMode) &CNeoRoot::MainLoopPopup, // STATE_QUIT &CNeoRoot::MainLoopPopup, // STATE_SERVERPASSWORD &CNeoRoot::MainLoopPopup, // STATE_SETTINGSRESETDEFAULT - }; - (this->*P_FN_MAIN_LOOP[m_state])(MainLoopParam{.eMode = eMode, .wide = wide, .tall = tall}); + }; + (this->*P_FN_MAIN_LOOP[m_state])(MainLoopParam{ .eMode = eMode, .wide = wide, .tall = tall }); - if (m_state != ePrevState) - { - if (ePrevState == STATE_SETTINGS) + if (m_state != ePrevState) { - V_memcpy(m_iSavedYOffsets, g_uiCtx.iYOffset, NeoUI::SIZEOF_SECTIONS); - } - UpdateControls(); - if (m_state == STATE_SETTINGS && ePrevState >= STATE__POPUPSTART && ePrevState < STATE__TOTAL) - { - V_memcpy(g_uiCtx.iYOffset, m_iSavedYOffsets, NeoUI::SIZEOF_SECTIONS); + if (ePrevState == STATE_SETTINGS) + { + V_memcpy(m_iSavedYOffsets, g_uiCtx.iYOffset, NeoUI::SIZEOF_SECTIONS); + } + UpdateControls(); + if (m_state == STATE_SETTINGS && ePrevState >= STATE__POPUPSTART && ePrevState < STATE__TOTAL) + { + V_memcpy(g_uiCtx.iYOffset, m_iSavedYOffsets, NeoUI::SIZEOF_SECTIONS); + } } } + + if (eMode == NeoUI::MODE_PAINT) + { + // Draw version info (bottom left corner) - Always + surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); + int textWidth, textHeight; + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl, BUILD_DISPLAY, textWidth, textHeight); + + surface()->DrawSetTextPos(g_uiCtx.iMarginX, tall - textHeight - g_uiCtx.iMarginY); + surface()->DrawPrintText(BUILD_DISPLAY, *BUILD_DISPLAY_SIZE); + } } void CNeoRoot::MainLoopRoot(const MainLoopParam param) { - const int yTopPos = 0; int iTitleNWidth, iTitleNHeight; const int iBtnPlaceXMid = (param.wide / 6); const int iMargin = (6 * g_uiCtx.iMarginX); const int iMarginHalf = iMargin * 0.5; + const int iTitleMarginTop = (param.tall * 0.2); surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, L"n", iTitleNWidth, iTitleNHeight); g_uiCtx.dPanel.wide = (m_iTitleWidth) +iMargin; - g_uiCtx.dPanel.tall = param.tall - yTopPos; + g_uiCtx.dPanel.tall = param.tall; g_uiCtx.dPanel.x = iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - iMarginHalf; - g_uiCtx.dPanel.y = yTopPos; - g_uiCtx.iYOffset[0] = -8; + g_uiCtx.dPanel.y = 0; + g_uiCtx.iYOffset[0] = (iTitleMarginTop + (2 * iTitleNHeight)) / -g_uiCtx.iRowTall; g_uiCtx.bgColor = COLOR_NEOPANELNORMALBG; NeoUI::BeginContext(&g_uiCtx, param.eMode, nullptr, "CtxRoot"); @@ -580,17 +578,25 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) const int iBtnWide = m_iTitleWidth + iMargin; const int iRightXPos = iBtnPlaceXMid + (iBtnWide / 2) + iMarginHalf; - int iRightSideYStart = yTopPos; + int iRightSideYStart = (iTitleMarginTop + (2 * iTitleNHeight)); // Draw top steam section portion { // Draw title surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl); + surface()->DrawSetTextColor(COLOR_BLACK); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) - 8, iTitleMarginTop + 8); + surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); surface()->DrawSetTextColor(COLOR_NEOTITLE); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), yTopPos + (param.tall * 0.2)); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), iTitleMarginTop); surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), yTopPos + (param.tall * 0.2) + m_iTitleHeight); + surface()->DrawSetTextColor(COLOR_BLACK); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - 8, iTitleMarginTop + m_iTitleHeight + 8); + surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); + surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); + surface()->DrawSetTextColor(COLOR_NEOTITLE); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), iTitleMarginTop + m_iTitleHeight); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); diff --git a/mp/src/game/client/neo/ui/neo_ui.cpp b/mp/src/game/client/neo/ui/neo_ui.cpp index d0845f504..e61ff4e03 100644 --- a/mp/src/game/client/neo/ui/neo_ui.cpp +++ b/mp/src/game/client/neo/ui/neo_ui.cpp @@ -562,8 +562,11 @@ NeoUI::RetButton Button(const wchar_t *wszLeftLabel, const wchar_t *wszText) if (wszLeftLabel) { + if (wdgState.bHot) + { + GCtxDrawFilledRectXtoX(0, g_pCtx->dPanel.wide); + } InternalLabel(wszLeftLabel, false); - GCtxDrawFilledRectXtoX(g_pCtx->iWgXPos, g_pCtx->dPanel.wide); const int xMargin = g_pCtx->eButtonTextStyle == TEXTSTYLE_CENTER ? (((g_pCtx->dPanel.wide - g_pCtx->iWgXPos) / 2) - (iFontWide / 2)) : g_pCtx->iMarginX; GCtxDrawSetTextPos(g_pCtx->iWgXPos + xMargin, @@ -629,6 +632,10 @@ void RingBox(const wchar_t *wszLeftLabel, const wchar_t **wszLabelsList, const i { case MODE_PAINT: { + if (wdgState.bHot) + { + GCtxDrawFilledRectXtoX(0, g_pCtx->dPanel.wide); + } const auto *pFontI = &g_pCtx->fonts[g_pCtx->eFont]; InternalLabel(wszLeftLabel, false); @@ -827,6 +834,10 @@ void Slider(const wchar_t *wszLeftLabel, float *flValue, const float flMin, cons case MODE_PAINT: { const auto *pFontI = &g_pCtx->fonts[g_pCtx->eFont]; + if (wdgState.bHot) + { + GCtxDrawFilledRectXtoX(0, g_pCtx->dPanel.wide); + } InternalLabel(wszLeftLabel, false); // Background bar @@ -1029,6 +1040,10 @@ void TextEdit(const wchar_t *wszLeftLabel, wchar_t *wszText, const int iMaxBytes { case MODE_PAINT: { + if (wdgState.bHot) + { + GCtxDrawFilledRectXtoX(0, g_pCtx->dPanel.wide); + } const auto *pFontI = &g_pCtx->fonts[g_pCtx->eFont]; InternalLabel(wszLeftLabel, false); GCtxDrawFilledRectXtoX(g_pCtx->iWgXPos, g_pCtx->dPanel.wide); diff --git a/mp/src/game/client/neo/ui/neo_ui.h b/mp/src/game/client/neo/ui/neo_ui.h index 4199ba8ca..976434a0c 100644 --- a/mp/src/game/client/neo/ui/neo_ui.h +++ b/mp/src/game/client/neo/ui/neo_ui.h @@ -182,12 +182,12 @@ struct Context }; #define COLOR_NEOPANELNORMALBG Color(0, 0, 0, 150) -#define COLOR_NEOPANELSELECTBG Color(0, 0, 0, 100) +#define COLOR_NEOPANELSELECTBG Color(0, 0, 0, 150) #define COLOR_NEOPANELACCENTBG Color(0, 0, 0, 0) #define COLOR_NEOPANELTEXTNORMAL Color(255, 255, 255, 255)//Color(200, 200, 200, 255) #define COLOR_NEOPANELTEXTBRIGHT Color(255, 255, 255, 255) -#define COLOR_NEOPANELPOPUPBG Color(10, 10, 10, 170) -#define COLOR_NEOPANELFRAMEBG Color(40, 40, 40, 150) +#define COLOR_NEOPANELPOPUPBG Color(0, 0, 0, 170) +#define COLOR_NEOPANELFRAMEBG Color(0, 0, 0, 150) #define COLOR_NEOTITLE Color(255, 255, 255, 255)//Color(200, 200, 200, 255) #define COLOR_NEOPANELBAR Color(20, 20, 20, 255) #define COLOR_NEOPANELMICTEST Color(30, 90, 30, 255) From ead82cc217d3a7e5ebe02802cdc84ae759c661d7 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 18:55:13 +0000 Subject: [PATCH 06/10] slightly darker for lighter background maps --- mp/src/game/client/neo/ui/neo_ui.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mp/src/game/client/neo/ui/neo_ui.h b/mp/src/game/client/neo/ui/neo_ui.h index 976434a0c..f96f4008d 100644 --- a/mp/src/game/client/neo/ui/neo_ui.h +++ b/mp/src/game/client/neo/ui/neo_ui.h @@ -181,13 +181,13 @@ struct Context CUtlHashtable htSliders; }; -#define COLOR_NEOPANELNORMALBG Color(0, 0, 0, 150) -#define COLOR_NEOPANELSELECTBG Color(0, 0, 0, 150) +#define COLOR_NEOPANELNORMALBG Color(0, 0, 0, 170) +#define COLOR_NEOPANELSELECTBG Color(0, 0, 0, 170) #define COLOR_NEOPANELACCENTBG Color(0, 0, 0, 0) #define COLOR_NEOPANELTEXTNORMAL Color(255, 255, 255, 255)//Color(200, 200, 200, 255) #define COLOR_NEOPANELTEXTBRIGHT Color(255, 255, 255, 255) #define COLOR_NEOPANELPOPUPBG Color(0, 0, 0, 170) -#define COLOR_NEOPANELFRAMEBG Color(0, 0, 0, 150) +#define COLOR_NEOPANELFRAMEBG Color(0, 0, 0, 170) #define COLOR_NEOTITLE Color(255, 255, 255, 255)//Color(200, 200, 200, 255) #define COLOR_NEOPANELBAR Color(20, 20, 20, 255) #define COLOR_NEOPANELMICTEST Color(30, 90, 30, 255) From fd9c03d4d3acb9e0c3e21404ec1f56f60ca6d7d3 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 20:02:57 +0000 Subject: [PATCH 07/10] add background selection --- .../neo_root_settings.cpp | 856 ++++++++++++++++++ .../game/client/neo/ui/neo_root_settings.cpp | 3 + mp/src/game/client/neo/ui/neo_root_settings.h | 2 + 3 files changed, 861 insertions(+) create mode 100644 mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp diff --git a/mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp b/mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp new file mode 100644 index 000000000..18b7c1d4e --- /dev/null +++ b/mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp @@ -0,0 +1,856 @@ +#include "neo_root_settings.h" + +#include "cdll_client_int.h" +#include "filesystem.h" +#include +#include +#include "vgui/ILocalize.h" +#include "inputsystem/iinputsystem.h" +#include "characterset.h" +#include "materialsystem/materialsystem_config.h" +#include +#include +#include +#include + +#include "neo_ui.h" +#include "neo_root.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern CNeoRoot *g_pNeoRoot; +extern NeoUI::Context g_uiCtx; +extern int g_iRowsInScreen; +extern bool g_bOBSDetected; +extern ConVar neo_cl_streamermode; + +const wchar_t *QUALITY_LABELS[] = { + L"Low", + L"Medium", + L"High", + L"Very High", +}; + +enum QualityEnum +{ + QUALITY_LOW = 0, + QUALITY_MEDIUM, + QUALITY_HIGH, + QUALITY_VERYHIGH, +}; + +enum ESpeaker +{ + SPEAKER_AUTO = -1, + SPEAKER_HEADPHONES = 0, + SPEAKER_STEREO = 2, + SPEAKER_QUAD = 4, + SPEAKER_SURROUND_5_1 = 5, + SPEAKER_SURROUND_7_1 = 7, +}; + +enum MultiThreadIdx +{ + THREAD_SINGLE = 0, + THREAD_MULTI, +}; + +enum FilteringEnum +{ + FILTERING_BILINEAR = 0, + FILTERING_TRILINEAR, + FILTERING_ANISO2X, + FILTERING_ANISO4X, + FILTERING_ANISO8X, + FILTERING_ANISO16X, + + FILTERING__TOTAL, +}; + +static const wchar_t *SPEAKER_CFG_LABELS[] = { + L"Auto", + L"Headphones", + L"2 Speakers (Stereo)", +#ifndef LINUX + L"4 Speakers (Quadraphonic)", + L"5.1 Surround", + L"7.1 Surround", +#endif +}; + +static const char *DLFILTER_STRMAP[] = { + "all", "nosounds", "mapsonly", "none" +}; + +static inline CUtlVector g_vecConVarRefPtrs; + +ConVarRefEx::ConVarRefEx(const char *pName, const bool bExcludeGlobalPtrs) + : ConVarRef(pName) +{ + if (!bExcludeGlobalPtrs) + { + g_vecConVarRefPtrs.AddToTail(this); + } +} + +void NeoSettingsInit(NeoSettings *ns) +{ + int iNativeWidth, iNativeHeight; + gameuifuncs->GetDesktopResolution(iNativeWidth, iNativeHeight); + static constexpr int DISP_SIZE = sizeof("(#######x#######) (Native)"); + NeoSettings::Video *pVideo = &ns->video; + gameuifuncs->GetVideoModes(&pVideo->vmList, &pVideo->iVMListSize); + pVideo->p2WszVmDispList = (wchar_t **)calloc(sizeof(wchar_t *), pVideo->iVMListSize); + pVideo->p2WszVmDispList[0] = (wchar_t *)calloc(sizeof(wchar_t) * DISP_SIZE, pVideo->iVMListSize); + for (int i = 0, offset = 0; i < pVideo->iVMListSize; ++i, offset += DISP_SIZE) + { + vmode_t *vm = &pVideo->vmList[i]; + swprintf(pVideo->p2WszVmDispList[0] + offset, DISP_SIZE - 1, L"%d x %d%ls", + vm->width, vm->height, + (iNativeWidth == vm->width && iNativeHeight == vm->height) ? L" (Native)" : L""); + pVideo->p2WszVmDispList[i] = pVideo->p2WszVmDispList[0] + offset; + } + + // TODO: Alt/secondary keybind, different way on finding keybind + characterset_t breakSet = {}; + breakSet.set[0] = '"'; + NeoSettings::Keys *keys = &ns->keys; + CUtlBuffer bufAct(0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY); + if (filesystem->ReadFile("scripts/kb_act.lst", nullptr, bufAct)) + { + keys->iBindsSize = 0; + + // It's quite specific to the root overridden menu so do it here instead of file + auto *conbind = &keys->vBinds[keys->iBindsSize++]; + V_strcpy_safe(conbind->szBindingCmd, "neo_toggleconsole"); + V_wcscpy_safe(conbind->wszDisplayText, L"Developer console bind"); + + while (bufAct.IsValid() && keys->iBindsSize < ARRAYSIZE(keys->vBinds)) + { + char szBindingCmd[64]; + char szRawDispText[64]; + + bool bIsOk = false; + bIsOk = bufAct.ParseToken(&breakSet, szBindingCmd, sizeof(szBindingCmd)); + if (!bIsOk) break; + bIsOk = bufAct.ParseToken(&breakSet, szRawDispText, sizeof(szRawDispText)); + if (!bIsOk) break; + + if (szBindingCmd[0] == '\0') continue; + + wchar_t wszDispText[64]; + if (wchar_t *localizedWszStr = g_pVGuiLocalize->Find(szRawDispText)) + { + V_wcscpy_safe(wszDispText, localizedWszStr); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode(szRawDispText, wszDispText, sizeof(wszDispText)); + } + + const bool bIsBlank = V_strcmp(szBindingCmd, "blank") == 0; + if (bIsBlank && szRawDispText[0] != '=') + { + // This is category label + auto *bind = &keys->vBinds[keys->iBindsSize++]; + bind->szBindingCmd[0] = '\0'; + V_wcscpy_safe(bind->wszDisplayText, wszDispText); + } + else if (!bIsBlank) + { + // This is a keybind + auto *bind = &keys->vBinds[keys->iBindsSize++]; + V_strcpy_safe(bind->szBindingCmd, szBindingCmd); + V_wcscpy_safe(bind->wszDisplayText, wszDispText); + bind->bcDefault = BUTTON_CODE_NONE; + } + } + } + + CUtlBuffer bufDef(0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY); + if (keys->iBindsSize > 0 && filesystem->ReadFile("scripts/kb_def.lst", nullptr, bufDef)) + { + while (bufDef.IsValid()) + { + char szDefBind[64]; + char szBindingCmd[64]; + + bool bIsOk = false; + bIsOk = bufDef.ParseToken(&breakSet, szDefBind, sizeof(szDefBind)); + if (!bIsOk) break; + bIsOk = bufDef.ParseToken(&breakSet, szBindingCmd, sizeof(szBindingCmd)); + if (!bIsOk) break; + + for (int i = 0; i < keys->iBindsSize; ++i) + { + if (V_strcmp(keys->vBinds[i].szBindingCmd, szBindingCmd) == 0) + { + keys->vBinds[i].bcDefault = g_pInputSystem->StringToButtonCode(szDefBind); + break; + } + } + } + } + + // Setup crosshairs + for (int i = 0; i < CROSSHAIR_STYLE__TOTAL; ++i) + { + if (CROSSHAIR_FILES[i][0]) + { + NeoSettings::Crosshair::Texture *pTex = &ns->crosshair.arTextures[i]; + pTex->iTexId = vgui::surface()->CreateNewTextureID(); + vgui::surface()->DrawSetTextureFile(pTex->iTexId, CROSSHAIR_FILES[i], false, false); + vgui::surface()->DrawGetTextureSize(pTex->iTexId, pTex->iWide, pTex->iTall); + } + } +} + +void NeoSettingsDeinit(NeoSettings *ns) +{ + free(ns->video.p2WszVmDispList[0]); + free(ns->video.p2WszVmDispList); +} + +void NeoSettingsRestore(NeoSettings *ns, const NeoSettings::Keys::Flags flagsKeys) +{ + ns->bModified = false; + NeoSettings::CVR *cvr = &ns->cvr; + { + NeoSettings::General *pGeneral = &ns->general; + g_pVGuiLocalize->ConvertANSIToUnicode(cvr->neo_name.GetString(), pGeneral->wszNeoName, sizeof(pGeneral->wszNeoName)); + g_pVGuiLocalize->ConvertANSIToUnicode(cvr->neo_clantag.GetString(), pGeneral->wszNeoClantag, sizeof(pGeneral->wszNeoClantag)); + pGeneral->bOnlySteamNick = cvr->cl_onlysteamnick.GetBool(); + pGeneral->bMarkerSpecOnlyClantag = cvr->neo_cl_clantag_friendly_marker_spec_only.GetBool(); + pGeneral->iFov = cvr->neo_fov.GetInt(); + pGeneral->iViewmodelFov = cvr->neo_viewmodel_fov_offset.GetInt(); + pGeneral->bAimHold = cvr->neo_aim_hold.GetBool(); + pGeneral->bReloadEmpty = cvr->cl_autoreload_when_empty.GetBool(); + pGeneral->bViewmodelRighthand = cvr->cl_righthand.GetBool(); + pGeneral->bLeanViewmodelOnly = cvr->cl_neo_lean_viewmodel_only.GetBool(); + pGeneral->bLeanAutomatic = cvr->cl_neo_lean_automatic.GetBool(); + pGeneral->bShowPlayerSprays = !(cvr->cl_playerspraydisable.GetBool()); // Inverse + pGeneral->bShowPos = cvr->cl_showpos.GetBool(); + pGeneral->iShowFps = cvr->cl_showfps.GetInt(); + { + const char *szDlFilter = cvr->cl_downloadfilter.GetString(); + pGeneral->iDlFilter = 0; + for (int i = 0; i < ARRAYSIZE(DLFILTER_STRMAP); ++i) + { + if (V_strcmp(szDlFilter, DLFILTER_STRMAP[i]) == 0) + { + pGeneral->iDlFilter = i; + break; + } + } + } + pGeneral->bStreamerMode = cvr->neo_cl_streamermode.GetBool(); + pGeneral->bAutoDetectOBS = cvr->neo_cl_streamermode_autodetect_obs.GetBool(); + pGeneral->bEnableRangeFinder = cvr->neo_cl_hud_rangefinder_enabled.GetBool(); + pGeneral->iBackground = cvr->sv_unlockedchapters.GetInt(); + } + { + NeoSettings::Keys *pKeys = &ns->keys; + pKeys->bWeaponFastSwitch = cvr->hud_fastswitch.GetBool(); + pKeys->bDeveloperConsole = cvr->neo_cl_toggleconsole.GetBool(); + if (!(flagsKeys & NeoSettings::Keys::SKIP_KEYS)) + { + for (int i = 0; i < pKeys->iBindsSize; ++i) + { + auto *bind = &pKeys->vBinds[i]; + bind->bcNext = bind->bcCurrent = gameuifuncs->GetButtonCodeForBind(bind->szBindingCmd); + } + } + } + { + NeoSettings::Mouse *pMouse = &ns->mouse; + pMouse->flSensitivity = cvr->sensitivity.GetFloat(); + pMouse->bRawInput = cvr->m_rawinput.GetBool(); + pMouse->bFilter = cvr->m_filter.GetBool(); + pMouse->bReverse = (cvr->m_pitch.GetFloat() < 0.0f); + pMouse->bCustomAccel = (cvr->m_customaccel.GetInt() == 3); + pMouse->flExponent = cvr->m_customaccel_exponent.GetFloat(); + } + { + NeoSettings::Audio *pAudio = &ns->audio; + + // Output + pAudio->flVolMain = cvr->volume.GetFloat(); + pAudio->flVolMusic = cvr->snd_musicvolume.GetFloat(); + pAudio->flVolVictory = cvr->snd_victory_volume.GetFloat(); + pAudio->iSoundSetup = 0; + switch (cvr->snd_surround_speakers.GetInt()) + { + break; case SPEAKER_HEADPHONES: pAudio->iSoundSetup = 1; + break; case SPEAKER_STEREO: pAudio->iSoundSetup = 2; +#ifndef LINUX + break; case SPEAKER_QUAD: pAudio->iSoundSetup = 3; + break; case SPEAKER_SURROUND_5_1: pAudio->iSoundSetup = 4; + break; case SPEAKER_SURROUND_7_1: pAudio->iSoundSetup = 5; +#endif + break; default: break; + } + pAudio->bMuteAudioUnFocus = cvr->snd_mute_losefocus.GetBool(); + + // Sound quality: snd_pitchquality dsp_slow_cpu + // High 1 0 + // Medium 0 0 + // Low 0 1 + pAudio->iSoundQuality = (cvr->snd_pitchquality.GetBool()) ? QUALITY_HIGH : + (cvr->dsp_slow_cpu.GetBool()) ? QUALITY_LOW : + QUALITY_MEDIUM; + + // Input + pAudio->bVoiceEnabled = cvr->voice_enable.GetBool(); + pAudio->flVolVoiceRecv = cvr->voice_scale.GetFloat(); + pAudio->bMicBoost = (engine->GetVoiceTweakAPI()->GetControlFloat(MicBoost) > 0.0f); + } + { + NeoSettings::Video *pVideo = &ns->video; + + int iScreenWidth, iScreenHeight; + engine->GetScreenSize(iScreenWidth, iScreenHeight); // Or: g_pMaterialSystem->GetDisplayMode? + pVideo->iResolution = pVideo->iVMListSize - 1; + for (int i = 0; i < pVideo->iVMListSize; ++i) + { + vmode_t *vm = &pVideo->vmList[i]; + if (vm->width == iScreenWidth && vm->height == iScreenHeight) + { + pVideo->iResolution = i; + break; + } + } + + pVideo->iWindow = static_cast(g_pMaterialSystem->GetCurrentConfigForVideoCard().Windowed()); + const int queueMode = cvr->mat_queue_mode.GetInt(); + pVideo->iCoreRendering = (queueMode == -1 || queueMode == 2) ? THREAD_MULTI : THREAD_SINGLE; + pVideo->iModelDetail = 2 - cvr->r_rootlod.GetInt(); // Inverse, highest = 0, lowest = 2 + pVideo->iTextureDetail = 3 - (cvr->mat_picmip.GetInt() + 1); // Inverse+1, highest = -1, lowest = 2 + pVideo->iShaderDetail = 1 - cvr->mat_reducefillrate.GetInt(); // Inverse, 1 = low, 0 = high + // Water detail + // r_waterforceexpensive r_waterforcereflectentities + // Simple: 0 0 + // Reflect World: 1 0 + // Reflect all: 1 1 + pVideo->iWaterDetail = (cvr->r_waterforcereflectentities.GetBool()) ? QUALITY_HIGH : + (cvr->r_waterforceexpensive.GetBool()) ? QUALITY_MEDIUM : + QUALITY_LOW; + + // Shadow detail + // r_flashlightdepthtexture r_shadowrendertotexture + // Low: 0 0 + // Medium: 0 1 + // High: 1 1 + pVideo->iShadowDetail = (cvr->r_flashlightdepthtexture.GetBool()) ? QUALITY_HIGH : + (cvr->r_shadowrendertotexture.GetBool()) ? QUALITY_MEDIUM : + QUALITY_LOW; + + pVideo->bColorCorrection = cvr->mat_colorcorrection.GetBool(); + pVideo->iAntiAliasing = (cvr->mat_antialias.GetInt() / 2); // MSAA: Times by 2 + + // Filtering mode + // mat_trilinear: 0 = bilinear, 1 = trilinear (both: mat_forceaniso 1) + // mat_forceaniso: Antisotropic 2x/4x/8x/16x (all aniso: mat_trilinear 0) + int filterIdx = 0; + if (cvr->mat_forceaniso.GetInt() < 2) + { + filterIdx = cvr->mat_trilinear.GetBool() ? FILTERING_TRILINEAR : FILTERING_BILINEAR; + } + else + { + switch (cvr->mat_forceaniso.GetInt()) + { + break; case 2: filterIdx = FILTERING_ANISO2X; + break; case 4: filterIdx = FILTERING_ANISO4X; + break; case 8: filterIdx = FILTERING_ANISO8X; + break; case 16: filterIdx = FILTERING_ANISO16X; + break; default: filterIdx = FILTERING_ANISO4X; // Some invalid number, just set to 4X (idx 3) + } + } + pVideo->iFilteringMode = filterIdx; + pVideo->bVSync = cvr->mat_vsync.GetBool(); + pVideo->bMotionBlur = cvr->mat_motion_blur_enabled.GetBool(); + pVideo->iHDR = cvr->mat_hdr_level.GetInt(); + pVideo->flGamma = cvr->mat_monitorgamma.GetFloat(); + } + { + NeoSettings::Crosshair *pCrosshair = &ns->crosshair; + pCrosshair->iStyle = cvr->neo_cl_crosshair_style.GetInt(); + pCrosshair->info.color[0] = (uint8)(cvr->neo_cl_crosshair_color_r.GetInt()); + pCrosshair->info.color[1] = (uint8)(cvr->neo_cl_crosshair_color_g.GetInt()); + pCrosshair->info.color[2] = (uint8)(cvr->neo_cl_crosshair_color_b.GetInt()); + pCrosshair->info.color[3] = (uint8)(cvr->neo_cl_crosshair_color_a.GetInt()); + pCrosshair->info.iESizeType = cvr->neo_cl_crosshair_size_type.GetInt(); + pCrosshair->info.iSize = cvr->neo_cl_crosshair_size.GetInt(); + pCrosshair->info.flScrSize = cvr->neo_cl_crosshair_size_screen.GetFloat(); + pCrosshair->info.iThick = cvr->neo_cl_crosshair_thickness.GetInt(); + pCrosshair->info.iGap = cvr->neo_cl_crosshair_gap.GetInt(); + pCrosshair->info.iOutline = cvr->neo_cl_crosshair_outline.GetInt(); + pCrosshair->info.iCenterDot = cvr->neo_cl_crosshair_center_dot.GetInt(); + pCrosshair->info.bTopLine = cvr->neo_cl_crosshair_top_line.GetBool(); + pCrosshair->info.iCircleRad = cvr->neo_cl_crosshair_circle_radius.GetInt(); + pCrosshair->info.iCircleSegments = cvr->neo_cl_crosshair_circle_segments.GetInt(); + } +} + +void NeoToggleConsoleEnforce() +{ + // NEO JANK (nullsystem): Try to unbind toggleconsole when possible + const auto toggleConsoleBind = gameuifuncs->GetButtonCodeForBind("toggleconsole"); + const auto neotoggleConsoleBind = gameuifuncs->GetButtonCodeForBind("neo_toggleconsole"); + const char *bindBtnName = g_pInputSystem->ButtonCodeToString(toggleConsoleBind); + if (bindBtnName && bindBtnName[0]) + { + char szCmdStr[128]; + V_sprintf_safe(szCmdStr, "unbind \"%s\"\n", bindBtnName); + engine->ClientCmd_Unrestricted(szCmdStr); + } + + // NEO JANK (nullsystem): Try to bind to ` if this is none. This should always be bind + // wether the console is enabled or not. If they're on a keyboard layout that can't utilise this + // key, they can just rebind it to another key themselves. + if (neotoggleConsoleBind <= BUTTON_CODE_NONE) + { + engine->ClientCmd_Unrestricted("bind ` neo_toggleconsole"); + } + else if (toggleConsoleBind == neotoggleConsoleBind) + { + // Could be unbinded by the unbind at this point if toggleconsole overlaps, so bring it back to + // neo_toggleconsole + const char *bindBtnName = g_pInputSystem->ButtonCodeToString(neotoggleConsoleBind); + if (bindBtnName && bindBtnName[0]) + { + char szCmdStr[128]; + V_sprintf_safe(szCmdStr, "bind \"%s\" neo_toggleconsole\n", bindBtnName); + engine->ClientCmd_Unrestricted(szCmdStr); + } + } +} + +void NeoSettingsSave(const NeoSettings *ns) +{ + const_cast(ns)->bModified = false; + auto *cvr = const_cast(&ns->cvr); + { + const NeoSettings::General *pGeneral = &ns->general; + char neoNameText[sizeof(pGeneral->wszNeoName)]; + g_pVGuiLocalize->ConvertUnicodeToANSI(pGeneral->wszNeoName, neoNameText, sizeof(neoNameText)); + cvr->neo_name.SetValue(neoNameText); + char neoClantagText[sizeof(pGeneral->wszNeoClantag)]; + g_pVGuiLocalize->ConvertUnicodeToANSI(pGeneral->wszNeoClantag, neoClantagText, sizeof(neoClantagText)); + cvr->neo_clantag.SetValue(neoClantagText); + cvr->cl_onlysteamnick.SetValue(pGeneral->bOnlySteamNick); + cvr->neo_cl_clantag_friendly_marker_spec_only.SetValue(pGeneral->bMarkerSpecOnlyClantag); + cvr->neo_fov.SetValue(pGeneral->iFov); + cvr->neo_viewmodel_fov_offset.SetValue(pGeneral->iViewmodelFov); + cvr->neo_aim_hold.SetValue(pGeneral->bAimHold); + cvr->cl_autoreload_when_empty.SetValue(pGeneral->bReloadEmpty); + cvr->cl_righthand.SetValue(pGeneral->bViewmodelRighthand); + cvr->cl_neo_lean_viewmodel_only.SetValue(pGeneral->bLeanViewmodelOnly); + cvr->cl_neo_lean_automatic.SetValue(pGeneral->bLeanAutomatic); + cvr->cl_playerspraydisable.SetValue(!pGeneral->bShowPlayerSprays); // Inverse + cvr->cl_showpos.SetValue(pGeneral->bShowPos); + cvr->cl_showfps.SetValue(pGeneral->iShowFps); + cvr->cl_downloadfilter.SetValue(DLFILTER_STRMAP[pGeneral->iDlFilter]); + cvr->neo_cl_streamermode.SetValue(pGeneral->bStreamerMode); + cvr->neo_cl_streamermode_autodetect_obs.SetValue(pGeneral->bAutoDetectOBS); + cvr->neo_cl_hud_rangefinder_enabled.SetValue(pGeneral->bEnableRangeFinder); + cvr->sv_unlockedchapters.SetValue(pGeneral->iBackground); + } + { + const NeoSettings::Keys *pKeys = &ns->keys; + cvr->hud_fastswitch.SetValue(pKeys->bWeaponFastSwitch); + NeoToggleConsoleEnforce(); + cvr->neo_cl_toggleconsole.SetValue(pKeys->bDeveloperConsole); + for (int i = 0; i < pKeys->iBindsSize; ++i) + { + const auto *bind = &pKeys->vBinds[i]; + if (bind->szBindingCmd[0] != '\0' && bind->bcCurrent > KEY_NONE) + { + char cmdStr[128]; + const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcCurrent); + V_sprintf_safe(cmdStr, "unbind \"%s\"\n", bindBtnName); + engine->ClientCmd_Unrestricted(cmdStr); + } + } + for (int i = 0; i < pKeys->iBindsSize; ++i) + { + auto *bind = const_cast(&pKeys->vBinds[i]); + if (bind->szBindingCmd[0] != '\0' && bind->bcNext > KEY_NONE) + { + char cmdStr[128]; + const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcNext); + V_sprintf_safe(cmdStr, "bind \"%s\" \"%s\"\n", bindBtnName, bind->szBindingCmd); + engine->ClientCmd_Unrestricted(cmdStr); + } + bind->bcCurrent = bind->bcNext; + } + // Reset the cache to none so it'll refresh on next KeyCodeTyped + const_cast(pKeys)->bcConsole = KEY_NONE; + } + { + const NeoSettings::Mouse *pMouse = &ns->mouse; + cvr->sensitivity.SetValue(pMouse->flSensitivity); + cvr->m_rawinput.SetValue(pMouse->bRawInput); + cvr->m_filter.SetValue(pMouse->bFilter); + const float absPitch = abs(cvr->m_pitch.GetFloat()); + cvr->m_pitch.SetValue(pMouse->bReverse ? -absPitch : absPitch); + cvr->m_customaccel.SetValue(pMouse->bCustomAccel ? 3 : 0); + cvr->m_customaccel_exponent.SetValue(pMouse->flExponent); + } + { + const NeoSettings::Audio *pAudio = &ns->audio; + + static constexpr int SURROUND_RE_MAP[] = { + SPEAKER_AUTO, + SPEAKER_HEADPHONES, + SPEAKER_STEREO, +#ifndef LINUX + SPEAKER_QUAD, + SPEAKER_SURROUND_5_1, + SPEAKER_SURROUND_7_1, +#endif + }; + + // Output + cvr->volume.SetValue(pAudio->flVolMain); + cvr->snd_musicvolume.SetValue(pAudio->flVolMusic); + cvr->snd_victory_volume.SetValue(pAudio->flVolVictory); + cvr->snd_surround_speakers.SetValue(SURROUND_RE_MAP[pAudio->iSoundSetup]); + cvr->snd_mute_losefocus.SetValue(pAudio->bMuteAudioUnFocus); + cvr->snd_pitchquality.SetValue(pAudio->iSoundQuality == QUALITY_HIGH); + cvr->dsp_slow_cpu.SetValue(pAudio->iSoundQuality == QUALITY_LOW); + + // Input + cvr->voice_enable.SetValue(pAudio->bVoiceEnabled); + cvr->voice_scale.SetValue(pAudio->flVolVoiceRecv); + engine->GetVoiceTweakAPI()->SetControlFloat(MicBoost, static_cast(pAudio->bMicBoost)); + } + { + const NeoSettings::Video *pVideo = &ns->video; + + const int resIdx = pVideo->iResolution; + if (resIdx >= 0 && resIdx < pVideo->iVMListSize) + { + // mat_setvideomode [width] [height] [mode] | mode: 0 = fullscreen, 1 = windowed + vmode_t *vm = &pVideo->vmList[resIdx]; + char cmdStr[128]; + V_sprintf_safe(cmdStr, "mat_setvideomode %d %d %d", vm->width, vm->height, pVideo->iWindow); + engine->ClientCmd_Unrestricted(cmdStr); + } + cvr->mat_queue_mode.SetValue((pVideo->iCoreRendering == THREAD_MULTI) ? 2 : 0); + cvr->r_rootlod.SetValue(2 - pVideo->iModelDetail); + cvr->mat_picmip.SetValue(2 - pVideo->iTextureDetail); + cvr->mat_reducefillrate.SetValue(1 - pVideo->iShaderDetail); + cvr->r_waterforceexpensive.SetValue(pVideo->iWaterDetail >= QUALITY_MEDIUM); + cvr->r_waterforcereflectentities.SetValue(pVideo->iWaterDetail == QUALITY_HIGH); + cvr->r_shadowrendertotexture.SetValue(pVideo->iShadowDetail >= QUALITY_MEDIUM); + cvr->r_flashlightdepthtexture.SetValue(pVideo->iShadowDetail == QUALITY_HIGH); + cvr->mat_colorcorrection.SetValue(pVideo->bColorCorrection); + cvr->mat_antialias.SetValue(pVideo->iAntiAliasing * 2); + cvr->mat_trilinear.SetValue(pVideo->iFilteringMode == FILTERING_TRILINEAR); + static constexpr int ANISO_MAP[FILTERING__TOTAL] = { + 1, 1, 2, 4, 8, 16 + }; + cvr->mat_forceaniso.SetValue(ANISO_MAP[pVideo->iFilteringMode]); + cvr->mat_vsync.SetValue(pVideo->bVSync); + cvr->mat_motion_blur_enabled.SetValue(pVideo->bMotionBlur); + cvr->mat_hdr_level.SetValue(pVideo->iHDR); + cvr->mat_monitorgamma.SetValue(pVideo->flGamma); + } + { + const NeoSettings::Crosshair *pCrosshair = &ns->crosshair; + cvr->neo_cl_crosshair_style.SetValue(pCrosshair->iStyle); + cvr->neo_cl_crosshair_color_r.SetValue(pCrosshair->info.color.r()); + cvr->neo_cl_crosshair_color_g.SetValue(pCrosshair->info.color.g()); + cvr->neo_cl_crosshair_color_b.SetValue(pCrosshair->info.color.b()); + cvr->neo_cl_crosshair_color_a.SetValue(pCrosshair->info.color.a()); + cvr->neo_cl_crosshair_size_type.SetValue(pCrosshair->info.iESizeType); + cvr->neo_cl_crosshair_size.SetValue(pCrosshair->info.iSize); + cvr->neo_cl_crosshair_size_screen.SetValue(pCrosshair->info.flScrSize); + cvr->neo_cl_crosshair_thickness.SetValue(pCrosshair->info.iThick); + cvr->neo_cl_crosshair_gap.SetValue(pCrosshair->info.iGap); + cvr->neo_cl_crosshair_outline.SetValue(pCrosshair->info.iOutline); + cvr->neo_cl_crosshair_center_dot.SetValue(pCrosshair->info.iCenterDot); + cvr->neo_cl_crosshair_top_line.SetValue(pCrosshair->info.bTopLine); + cvr->neo_cl_crosshair_circle_radius.SetValue(pCrosshair->info.iCircleRad); + cvr->neo_cl_crosshair_circle_segments.SetValue(pCrosshair->info.iCircleSegments); + } + + engine->ClientCmd_Unrestricted("host_writeconfig"); + engine->ClientCmd_Unrestricted("mat_savechanges"); +} + +void NeoSettingsResetToDefault(NeoSettings *ns) +{ + // NEO NOTE (nullsystem): The only thing left out is video mode and volume, but that's fine + // as we shouldn't need to be altering those + for (ConVarRefEx *convar : g_vecConVarRefPtrs) + { + convar->SetValue(convar->GetDefault()); + } + + NeoSettings::Keys *pKeys = &ns->keys; + for (int i = 0; i < pKeys->iBindsSize; ++i) + { + const auto *bind = &pKeys->vBinds[i]; + if (bind->szBindingCmd[0] != '\0' && bind->bcCurrent > KEY_NONE) + { + char cmdStr[128]; + const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcCurrent); + V_sprintf_safe(cmdStr, "unbind \"%s\"\n", bindBtnName); + engine->ClientCmd_Unrestricted(cmdStr); + } + } + for (int i = 0; i < pKeys->iBindsSize; ++i) + { + auto *bind = &pKeys->vBinds[i]; + if (bind->szBindingCmd[0] != '\0' && bind->bcDefault > KEY_NONE) + { + char cmdStr[128]; + const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcDefault); + V_sprintf_safe(cmdStr, "bind \"%s\" \"%s\"\n", bindBtnName, bind->szBindingCmd); + engine->ClientCmd_Unrestricted(cmdStr); + } + bind->bcCurrent = bind->bcNext = bind->bcDefault; + } + + engine->ClientCmd_Unrestricted("host_writeconfig"); + + // NEO JANK (nullsystem): For some reason, bind -> gameuifuncs->GetButtonCodeForBind is too quick for + // the game engine at this point. So just omit setting binds in restore since we already have anyway. + NeoSettingsRestore(ns, NeoSettings::Keys::SKIP_KEYS); +} + +static const wchar_t *DLFILTER_LABELS[] = { + L"Allow all custom files from server", + L"Do not download custom sounds", + L"Only allow map files", + L"Do not download any custom files", +}; +static const wchar_t *SHOWFPS_LABELS[] = { L"Disabled", L"Enabled (FPS)", L"Enabled (Smooth FPS)", }; +static_assert(ARRAYSIZE(DLFILTER_STRMAP) == ARRAYSIZE(DLFILTER_LABELS)); + +void NeoSettings_General(NeoSettings *ns) +{ + NeoSettings::General *pGeneral = &ns->general; + NeoUI::TextEdit(L"Name", pGeneral->wszNeoName, SZWSZ_LEN(pGeneral->wszNeoName)); + NeoUI::TextEdit(L"Clan tag", pGeneral->wszNeoClantag, SZWSZ_LEN(pGeneral->wszNeoClantag)); + NeoUI::RingBoxBool(L"Show only steam name", &pGeneral->bOnlySteamNick); + NeoUI::RingBoxBool(L"Friendly marker spectator only clantags", &pGeneral->bMarkerSpecOnlyClantag); + + wchar_t wszTotalClanAndName[NEO_MAX_DISPLAYNAME]; + GetClNeoDisplayName(wszTotalClanAndName, pGeneral->wszNeoName, pGeneral->wszNeoClantag, pGeneral->bOnlySteamNick); + NeoUI::Label(L"Display name", wszTotalClanAndName); + + NeoUI::SliderInt(L"FOV", &pGeneral->iFov, 75, 110); + NeoUI::SliderInt(L"Viewmodel FOV Offset", &pGeneral->iViewmodelFov, -20, 40); + NeoUI::RingBoxBool(L"Aim hold", &pGeneral->bAimHold); + NeoUI::RingBoxBool(L"Reload empty", &pGeneral->bReloadEmpty); + NeoUI::RingBoxBool(L"Right hand viewmodel", &pGeneral->bViewmodelRighthand); + NeoUI::RingBoxBool(L"Lean viewmodel only", &pGeneral->bLeanViewmodelOnly); + NeoUI::RingBoxBool(L"Automatic leaning", &pGeneral->bLeanAutomatic); + NeoUI::RingBoxBool(L"Show player spray", &pGeneral->bShowPlayerSprays); + NeoUI::RingBoxBool(L"Show position", &pGeneral->bShowPos); + NeoUI::RingBox(L"Show FPS", SHOWFPS_LABELS, ARRAYSIZE(SHOWFPS_LABELS), &pGeneral->iShowFps); + NeoUI::RingBox(L"Download filter", DLFILTER_LABELS, ARRAYSIZE(DLFILTER_LABELS), &pGeneral->iDlFilter); + NeoUI::RingBoxBool(L"Streamer mode", &pGeneral->bStreamerMode); + NeoUI::RingBoxBool(L"Auto streamer mode (requires restart)", &pGeneral->bAutoDetectOBS); + NeoUI::Label(L"OBS detection", g_bOBSDetected ? L"OBS detected on startup" : L"Not detected on startup"); + NeoUI::RingBoxBool(L"Show rangefinder", &pGeneral->bEnableRangeFinder); + NeoUI::SliderInt(L"Selected Background", &pGeneral->iBackground, 0, 15); // NEO TODO (Adam) switch to RingBox with values read from ChapterBackgrounds.txt +} + +void NeoSettings_Keys(NeoSettings *ns) +{ + NeoSettings::Keys *pKeys = &ns->keys; + NeoUI::RingBoxBool(L"Weapon fastswitch", &pKeys->bWeaponFastSwitch); + NeoUI::RingBoxBool(L"Developer console", &pKeys->bDeveloperConsole); + g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; + for (int i = 0; i < pKeys->iBindsSize; ++i) + { + const auto &bind = pKeys->vBinds[i]; + if (bind.szBindingCmd[0] == '\0') + { + NeoUI::Label(bind.wszDisplayText); + } + else + { + wchar_t wszBindBtnName[64]; + const char *szBindBtnName = g_pInputSystem->ButtonCodeToString(bind.bcNext); + g_pVGuiLocalize->ConvertANSIToUnicode(szBindBtnName, wszBindBtnName, sizeof(wszBindBtnName)); + if (NeoUI::Button(bind.wszDisplayText, wszBindBtnName).bPressed) + { + ns->iNextBinding = i; + } + } + } +} + +void NeoSettings_Mouse(NeoSettings *ns) +{ + NeoSettings::Mouse *pMouse = &ns->mouse; + NeoUI::Slider(L"Sensitivity", &pMouse->flSensitivity, 0.1f, 10.0f, 2, 0.25f); + NeoUI::RingBoxBool(L"Raw input", &pMouse->bRawInput); + NeoUI::RingBoxBool(L"Mouse Filter", &pMouse->bFilter); + NeoUI::RingBoxBool(L"Mouse Reverse", &pMouse->bReverse); + NeoUI::RingBoxBool(L"Custom Acceleration", &pMouse->bCustomAccel); + NeoUI::Slider(L"Exponent", &pMouse->flExponent, 1.0f, 1.4f, 2, 0.1f); +} + +void NeoSettings_Audio(NeoSettings *ns) +{ + NeoSettings::Audio *pAudio = &ns->audio; + NeoUI::Slider(L"Main Volume", &pAudio->flVolMain, 0.0f, 1.0f, 2, 0.1f); + NeoUI::Slider(L"Music Volume", &pAudio->flVolMusic, 0.0f, 1.0f, 2, 0.1f); + NeoUI::Slider(L"Victory Volume", &pAudio->flVolVictory, 0.0f, 1.0f, 2, 0.1f); + NeoUI::RingBox(L"Sound Setup", SPEAKER_CFG_LABELS, ARRAYSIZE(SPEAKER_CFG_LABELS), &pAudio->iSoundSetup); + NeoUI::RingBox(L"Sound Quality", QUALITY_LABELS, 3, &pAudio->iSoundQuality); + NeoUI::RingBoxBool(L"Mute Audio on un-focus", &pAudio->bMuteAudioUnFocus); + NeoUI::RingBoxBool(L"Voice Enabled", &pAudio->bVoiceEnabled); + NeoUI::Slider(L"Voice Receive", &pAudio->flVolVoiceRecv, 0.0f, 1.0f, 2, 0.1f); + NeoUI::RingBoxBool(L"Microphone Boost", &pAudio->bMicBoost); + IVoiceTweak_s *pVoiceTweak = engine->GetVoiceTweakAPI(); + const bool bTweaking = pVoiceTweak->IsStillTweaking(); + if (bTweaking && g_uiCtx.eMode == NeoUI::MODE_PAINT) + { + // Only fetch the value at interval as immediate is too quick/flickers, and give a longer delay when + // it goes from sound to no sound. + static constexpr float FL_FETCH_INTERVAL = 0.1f; + static constexpr float FL_SILENCE_INTERVAL = 0.4f; + const float flNowSpeakingVol = pVoiceTweak->GetControlFloat(SpeakingVolume); + if ((flNowSpeakingVol > 0.0f && pAudio->flLastFetchInterval + FL_FETCH_INTERVAL < gpGlobals->curtime) || + (flNowSpeakingVol == 0.0f && pAudio->flSpeakingVol > 0.0f && + pAudio->flLastFetchInterval + FL_SILENCE_INTERVAL < gpGlobals->curtime)) + { + pAudio->flSpeakingVol = flNowSpeakingVol; + pAudio->flLastFetchInterval = gpGlobals->curtime; + } + vgui::surface()->DrawSetColor(COLOR_NEOPANELMICTEST); + NeoUI::GCtxDrawFilledRectXtoX(g_uiCtx.iWgXPos, 0, + g_uiCtx.iWgXPos + (pAudio->flSpeakingVol * (g_uiCtx.dPanel.wide - g_uiCtx.iWgXPos)), g_uiCtx.iRowTall); + vgui::surface()->DrawSetColor(COLOR_TRANSPARENT); + g_uiCtx.selectBgColor = COLOR_TRANSPARENT; + } + if (NeoUI::Button(L"Microphone Tester", + bTweaking ? L"Stop testing" : L"Start testing").bPressed) + { + bTweaking ? pVoiceTweak->EndVoiceTweakMode() : (void)pVoiceTweak->StartVoiceTweakMode(); + pAudio->flSpeakingVol = 0.0f; + pAudio->flLastFetchInterval = 0.0f; + } + if (bTweaking && g_uiCtx.eMode == NeoUI::MODE_PAINT) + { + vgui::surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); + g_uiCtx.selectBgColor = COLOR_NEOPANELSELECTBG; + } +} + +static const wchar_t *WINDOW_MODE[] = { L"Fullscreen", L"Windowed", }; +static const wchar_t *QUEUE_MODE[] = { L"Single", L"Multi", }; +static const wchar_t *QUALITY2_LABELS[] = { L"Low", L"High", }; +static const wchar_t *FILTERING_LABELS[FILTERING__TOTAL] = { + L"Bilinear", L"Trilinear", L"Anisotropic 2X", L"Anisotropic 4X", L"Anisotropic 8X", L"Anisotropic 16X", +}; +static const wchar_t *HDR_LABELS[] = { L"None", L"Bloom", L"Full", }; +static const wchar_t *WATER_LABELS[] = { L"Simple Reflect", L"Reflect World", L"Reflect All", }; +static const wchar_t *MSAA_LABELS[] = { L"None", L"2x MSAA", L"4x MSAA", L"6x MSAA", L"8x MSAA", }; + +void NeoSettings_Video(NeoSettings *ns) +{ + NeoSettings::Video *pVideo = &ns->video; + NeoUI::RingBox(L"Resolution", const_cast(pVideo->p2WszVmDispList), pVideo->iVMListSize, &pVideo->iResolution); + NeoUI::RingBox(L"Window", WINDOW_MODE, ARRAYSIZE(WINDOW_MODE), &pVideo->iWindow); + NeoUI::RingBox(L"Core Rendering", QUEUE_MODE, ARRAYSIZE(QUEUE_MODE), &pVideo->iCoreRendering); + NeoUI::RingBox(L"Model detail", QUALITY_LABELS, 3, &pVideo->iModelDetail); + NeoUI::RingBox(L"Texture detail", QUALITY_LABELS, 4, &pVideo->iTextureDetail); + NeoUI::RingBox(L"Shader detail", QUALITY2_LABELS, 2, &pVideo->iShaderDetail); + NeoUI::RingBox(L"Water detail", WATER_LABELS, ARRAYSIZE(WATER_LABELS), &pVideo->iWaterDetail); + NeoUI::RingBox(L"Shadow detail", QUALITY_LABELS, 3, &pVideo->iShadowDetail); + NeoUI::RingBoxBool(L"Color correction", &pVideo->bColorCorrection); + NeoUI::RingBox(L"Anti-aliasing", MSAA_LABELS, ARRAYSIZE(MSAA_LABELS), &pVideo->iAntiAliasing); + NeoUI::RingBox(L"Filtering mode", FILTERING_LABELS, FILTERING__TOTAL, &pVideo->iFilteringMode); + NeoUI::RingBoxBool(L"V-Sync", &pVideo->bVSync); + NeoUI::RingBoxBool(L"Motion blur", &pVideo->bMotionBlur); + NeoUI::RingBox(L"HDR", HDR_LABELS, ARRAYSIZE(HDR_LABELS), &pVideo->iHDR); + NeoUI::Slider(L"Gamma", &pVideo->flGamma, 1.6, 2.6, 2, 0.1f); +} + +void NeoSettings_Crosshair(NeoSettings *ns) +{ + static constexpr int IVIEW_ROWS = 5; + NeoSettings::Crosshair *pCrosshair = &ns->crosshair; + + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * IVIEW_ROWS; + NeoUI::BeginSection(); + const bool bTextured = CROSSHAIR_FILES[pCrosshair->iStyle][0]; + if (bTextured) + { + NeoSettings::Crosshair::Texture *pTex = &ns->crosshair.arTextures[pCrosshair->iStyle]; + vgui::surface()->DrawSetTexture(pTex->iTexId); + vgui::surface()->DrawSetColor(pCrosshair->info.color); + vgui::surface()->DrawTexturedRect( + g_uiCtx.dPanel.x + g_uiCtx.iLayoutX - (pTex->iWide / 2) + (g_uiCtx.dPanel.wide / 2), + g_uiCtx.dPanel.y + g_uiCtx.iLayoutY, + g_uiCtx.dPanel.x + g_uiCtx.iLayoutX + (pTex->iWide / 2) + (g_uiCtx.dPanel.wide / 2), + g_uiCtx.dPanel.y + g_uiCtx.iLayoutY + pTex->iTall); + } + else + { + PaintCrosshair(pCrosshair->info, + g_uiCtx.dPanel.x + g_uiCtx.iLayoutX + (g_uiCtx.dPanel.wide / 2), + g_uiCtx.dPanel.y + g_uiCtx.iLayoutY + (g_uiCtx.dPanel.tall / 2)); + } + vgui::surface()->DrawSetColor(g_uiCtx.normalBgColor); + + if (pCrosshair->iStyle == CROSSHAIR_STYLE_CUSTOM) + { + NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); + { + const bool bPresExport = NeoUI::Button(L"Export").bPressed; + const bool bPresImport = NeoUI::Button(L"Import").bPressed; + if (bPresExport || bPresImport) + { + if (g_pNeoRoot->m_pFileIODialog) + { + g_pNeoRoot->m_pFileIODialog->MarkForDeletion(); + } + pCrosshair->eFileIOMode = bPresImport ? vgui::FOD_OPEN : vgui::FOD_SAVE; + g_pNeoRoot->m_pFileIODialog = new vgui::FileOpenDialog(g_pNeoRoot, + bPresImport ? "Import crosshair" : "Export crosshair", + pCrosshair->eFileIOMode); + g_pNeoRoot->m_pFileIODialog->AddFilter("*." NEO_XHAIR_EXT, "NT;RE Crosshair", true); + g_pNeoRoot->m_pFileIODialog->DoModal(); + } + } + NeoUI::EndHorizontal(); + } + NeoUI::EndSection(); + + g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; + g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen - IVIEW_ROWS); + NeoUI::BeginSection(true); + NeoUI::RingBox(L"Crosshair style", CROSSHAIR_LABELS, CROSSHAIR_STYLE__TOTAL, &pCrosshair->iStyle); + NeoUI::SliderU8(L"Red", &pCrosshair->info.color[0], 0, UCHAR_MAX); + NeoUI::SliderU8(L"Green", &pCrosshair->info.color[1], 0, UCHAR_MAX); + NeoUI::SliderU8(L"Blue", &pCrosshair->info.color[2], 0, UCHAR_MAX); + NeoUI::SliderU8(L"Alpha", &pCrosshair->info.color[3], 0, UCHAR_MAX); + if (!bTextured) + { + NeoUI::RingBox(L"Size type", CROSSHAIR_SIZETYPE_LABELS, CROSSHAIR_SIZETYPE__TOTAL, &pCrosshair->info.iESizeType); + switch (pCrosshair->info.iESizeType) + { + case CROSSHAIR_SIZETYPE_ABSOLUTE: NeoUI::SliderInt(L"Size", &pCrosshair->info.iSize, 0, CROSSHAIR_MAX_SIZE); break; + case CROSSHAIR_SIZETYPE_SCREEN: NeoUI::Slider(L"Size", &pCrosshair->info.flScrSize, 0.0f, 1.0f, 5, 0.01f); break; + } + NeoUI::SliderInt(L"Thickness", &pCrosshair->info.iThick, 0, CROSSHAIR_MAX_THICKNESS); + NeoUI::SliderInt(L"Gap", &pCrosshair->info.iGap, 0, CROSSHAIR_MAX_GAP); + NeoUI::SliderInt(L"Outline", &pCrosshair->info.iOutline, 0, CROSSHAIR_MAX_OUTLINE); + NeoUI::SliderInt(L"Center dot", &pCrosshair->info.iCenterDot, 0, CROSSHAIR_MAX_CENTER_DOT); + NeoUI::RingBoxBool(L"Draw top line", &pCrosshair->info.bTopLine); + NeoUI::SliderInt(L"Circle radius", &pCrosshair->info.iCircleRad, 0, CROSSHAIR_MAX_CIRCLE_RAD); + NeoUI::SliderInt(L"Circle segments", &pCrosshair->info.iCircleSegments, 0, CROSSHAIR_MAX_CIRCLE_SEGMENTS); + } + NeoUI::EndSection(); +} diff --git a/mp/src/game/client/neo/ui/neo_root_settings.cpp b/mp/src/game/client/neo/ui/neo_root_settings.cpp index 34bfef785..db16ccd12 100644 --- a/mp/src/game/client/neo/ui/neo_root_settings.cpp +++ b/mp/src/game/client/neo/ui/neo_root_settings.cpp @@ -247,6 +247,7 @@ void NeoSettingsRestore(NeoSettings *ns, const NeoSettings::Keys::Flags flagsKey pGeneral->bStreamerMode = cvr->neo_cl_streamermode.GetBool(); pGeneral->bAutoDetectOBS = cvr->neo_cl_streamermode_autodetect_obs.GetBool(); pGeneral->bEnableRangeFinder = cvr->neo_cl_hud_rangefinder_enabled.GetBool(); + pGeneral->iBackground = cvr->sv_unlockedchapters.GetInt(); } { NeoSettings::Keys *pKeys = &ns->keys; @@ -454,6 +455,7 @@ void NeoSettingsSave(const NeoSettings *ns) cvr->neo_cl_streamermode.SetValue(pGeneral->bStreamerMode); cvr->neo_cl_streamermode_autodetect_obs.SetValue(pGeneral->bAutoDetectOBS); cvr->neo_cl_hud_rangefinder_enabled.SetValue(pGeneral->bEnableRangeFinder); + cvr->sv_unlockedchapters.SetValue(pGeneral->iBackground); } { const NeoSettings::Keys *pKeys = &ns->keys; @@ -656,6 +658,7 @@ void NeoSettings_General(NeoSettings *ns) NeoUI::RingBoxBool(L"Auto streamer mode (requires restart)", &pGeneral->bAutoDetectOBS); NeoUI::Label(L"OBS detection", g_bOBSDetected ? L"OBS detected on startup" : L"Not detected on startup"); NeoUI::RingBoxBool(L"Show rangefinder", &pGeneral->bEnableRangeFinder); + NeoUI::SliderInt(L"Selected Background", &pGeneral->iBackground, 0, 2); // NEO TODO (Adam) switch to RingBox with values read from ChapterBackgrounds.txt } void NeoSettings_Keys(NeoSettings *ns) diff --git a/mp/src/game/client/neo/ui/neo_root_settings.h b/mp/src/game/client/neo/ui/neo_root_settings.h index 67d1b2d80..36255751b 100644 --- a/mp/src/game/client/neo/ui/neo_root_settings.h +++ b/mp/src/game/client/neo/ui/neo_root_settings.h @@ -45,6 +45,7 @@ struct NeoSettings bool bStreamerMode; bool bAutoDetectOBS; bool bEnableRangeFinder; + int iBackground; }; struct Keys @@ -173,6 +174,7 @@ struct NeoSettings CONVARREF_DEF(neo_cl_streamermode); CONVARREF_DEF(neo_cl_streamermode_autodetect_obs); CONVARREF_DEF(neo_cl_hud_rangefinder_enabled); + CONVARREF_DEF(sv_unlockedchapters); // Multiplayer CONVARREF_DEF(cl_playerspraydisable); From 8acce7aff9a8ba49a9bc579f1bbec2445dec80f8 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 20:57:01 +0000 Subject: [PATCH 08/10] fov --- mp/game/neo/scripts/ChapterBackgrounds.txt | 3 + .../neo_root_settings.cpp | 856 ------------------ .../game/client/neo/ui/neo_root_settings.cpp | 2 +- mp/src/game/client/view.cpp | 2 +- mp/src/game/shared/baseplayer_shared.cpp | 4 + 5 files changed, 9 insertions(+), 858 deletions(-) delete mode 100644 mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp diff --git a/mp/game/neo/scripts/ChapterBackgrounds.txt b/mp/game/neo/scripts/ChapterBackgrounds.txt index ea7264b73..e2c742861 100644 --- a/mp/game/neo/scripts/ChapterBackgrounds.txt +++ b/mp/game/neo/scripts/ChapterBackgrounds.txt @@ -1,4 +1,7 @@ "chapters" { 1 "background01" + 2 "background_alley" + 3 "background_door" + 4 "background_door" } \ No newline at end of file diff --git a/mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp b/mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp deleted file mode 100644 index 18b7c1d4e..000000000 --- a/mp/src/enc_temp_folder/2f8341b2a6aaee97f89f0976b1bd28/neo_root_settings.cpp +++ /dev/null @@ -1,856 +0,0 @@ -#include "neo_root_settings.h" - -#include "cdll_client_int.h" -#include "filesystem.h" -#include -#include -#include "vgui/ILocalize.h" -#include "inputsystem/iinputsystem.h" -#include "characterset.h" -#include "materialsystem/materialsystem_config.h" -#include -#include -#include -#include - -#include "neo_ui.h" -#include "neo_root.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern CNeoRoot *g_pNeoRoot; -extern NeoUI::Context g_uiCtx; -extern int g_iRowsInScreen; -extern bool g_bOBSDetected; -extern ConVar neo_cl_streamermode; - -const wchar_t *QUALITY_LABELS[] = { - L"Low", - L"Medium", - L"High", - L"Very High", -}; - -enum QualityEnum -{ - QUALITY_LOW = 0, - QUALITY_MEDIUM, - QUALITY_HIGH, - QUALITY_VERYHIGH, -}; - -enum ESpeaker -{ - SPEAKER_AUTO = -1, - SPEAKER_HEADPHONES = 0, - SPEAKER_STEREO = 2, - SPEAKER_QUAD = 4, - SPEAKER_SURROUND_5_1 = 5, - SPEAKER_SURROUND_7_1 = 7, -}; - -enum MultiThreadIdx -{ - THREAD_SINGLE = 0, - THREAD_MULTI, -}; - -enum FilteringEnum -{ - FILTERING_BILINEAR = 0, - FILTERING_TRILINEAR, - FILTERING_ANISO2X, - FILTERING_ANISO4X, - FILTERING_ANISO8X, - FILTERING_ANISO16X, - - FILTERING__TOTAL, -}; - -static const wchar_t *SPEAKER_CFG_LABELS[] = { - L"Auto", - L"Headphones", - L"2 Speakers (Stereo)", -#ifndef LINUX - L"4 Speakers (Quadraphonic)", - L"5.1 Surround", - L"7.1 Surround", -#endif -}; - -static const char *DLFILTER_STRMAP[] = { - "all", "nosounds", "mapsonly", "none" -}; - -static inline CUtlVector g_vecConVarRefPtrs; - -ConVarRefEx::ConVarRefEx(const char *pName, const bool bExcludeGlobalPtrs) - : ConVarRef(pName) -{ - if (!bExcludeGlobalPtrs) - { - g_vecConVarRefPtrs.AddToTail(this); - } -} - -void NeoSettingsInit(NeoSettings *ns) -{ - int iNativeWidth, iNativeHeight; - gameuifuncs->GetDesktopResolution(iNativeWidth, iNativeHeight); - static constexpr int DISP_SIZE = sizeof("(#######x#######) (Native)"); - NeoSettings::Video *pVideo = &ns->video; - gameuifuncs->GetVideoModes(&pVideo->vmList, &pVideo->iVMListSize); - pVideo->p2WszVmDispList = (wchar_t **)calloc(sizeof(wchar_t *), pVideo->iVMListSize); - pVideo->p2WszVmDispList[0] = (wchar_t *)calloc(sizeof(wchar_t) * DISP_SIZE, pVideo->iVMListSize); - for (int i = 0, offset = 0; i < pVideo->iVMListSize; ++i, offset += DISP_SIZE) - { - vmode_t *vm = &pVideo->vmList[i]; - swprintf(pVideo->p2WszVmDispList[0] + offset, DISP_SIZE - 1, L"%d x %d%ls", - vm->width, vm->height, - (iNativeWidth == vm->width && iNativeHeight == vm->height) ? L" (Native)" : L""); - pVideo->p2WszVmDispList[i] = pVideo->p2WszVmDispList[0] + offset; - } - - // TODO: Alt/secondary keybind, different way on finding keybind - characterset_t breakSet = {}; - breakSet.set[0] = '"'; - NeoSettings::Keys *keys = &ns->keys; - CUtlBuffer bufAct(0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY); - if (filesystem->ReadFile("scripts/kb_act.lst", nullptr, bufAct)) - { - keys->iBindsSize = 0; - - // It's quite specific to the root overridden menu so do it here instead of file - auto *conbind = &keys->vBinds[keys->iBindsSize++]; - V_strcpy_safe(conbind->szBindingCmd, "neo_toggleconsole"); - V_wcscpy_safe(conbind->wszDisplayText, L"Developer console bind"); - - while (bufAct.IsValid() && keys->iBindsSize < ARRAYSIZE(keys->vBinds)) - { - char szBindingCmd[64]; - char szRawDispText[64]; - - bool bIsOk = false; - bIsOk = bufAct.ParseToken(&breakSet, szBindingCmd, sizeof(szBindingCmd)); - if (!bIsOk) break; - bIsOk = bufAct.ParseToken(&breakSet, szRawDispText, sizeof(szRawDispText)); - if (!bIsOk) break; - - if (szBindingCmd[0] == '\0') continue; - - wchar_t wszDispText[64]; - if (wchar_t *localizedWszStr = g_pVGuiLocalize->Find(szRawDispText)) - { - V_wcscpy_safe(wszDispText, localizedWszStr); - } - else - { - g_pVGuiLocalize->ConvertANSIToUnicode(szRawDispText, wszDispText, sizeof(wszDispText)); - } - - const bool bIsBlank = V_strcmp(szBindingCmd, "blank") == 0; - if (bIsBlank && szRawDispText[0] != '=') - { - // This is category label - auto *bind = &keys->vBinds[keys->iBindsSize++]; - bind->szBindingCmd[0] = '\0'; - V_wcscpy_safe(bind->wszDisplayText, wszDispText); - } - else if (!bIsBlank) - { - // This is a keybind - auto *bind = &keys->vBinds[keys->iBindsSize++]; - V_strcpy_safe(bind->szBindingCmd, szBindingCmd); - V_wcscpy_safe(bind->wszDisplayText, wszDispText); - bind->bcDefault = BUTTON_CODE_NONE; - } - } - } - - CUtlBuffer bufDef(0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY); - if (keys->iBindsSize > 0 && filesystem->ReadFile("scripts/kb_def.lst", nullptr, bufDef)) - { - while (bufDef.IsValid()) - { - char szDefBind[64]; - char szBindingCmd[64]; - - bool bIsOk = false; - bIsOk = bufDef.ParseToken(&breakSet, szDefBind, sizeof(szDefBind)); - if (!bIsOk) break; - bIsOk = bufDef.ParseToken(&breakSet, szBindingCmd, sizeof(szBindingCmd)); - if (!bIsOk) break; - - for (int i = 0; i < keys->iBindsSize; ++i) - { - if (V_strcmp(keys->vBinds[i].szBindingCmd, szBindingCmd) == 0) - { - keys->vBinds[i].bcDefault = g_pInputSystem->StringToButtonCode(szDefBind); - break; - } - } - } - } - - // Setup crosshairs - for (int i = 0; i < CROSSHAIR_STYLE__TOTAL; ++i) - { - if (CROSSHAIR_FILES[i][0]) - { - NeoSettings::Crosshair::Texture *pTex = &ns->crosshair.arTextures[i]; - pTex->iTexId = vgui::surface()->CreateNewTextureID(); - vgui::surface()->DrawSetTextureFile(pTex->iTexId, CROSSHAIR_FILES[i], false, false); - vgui::surface()->DrawGetTextureSize(pTex->iTexId, pTex->iWide, pTex->iTall); - } - } -} - -void NeoSettingsDeinit(NeoSettings *ns) -{ - free(ns->video.p2WszVmDispList[0]); - free(ns->video.p2WszVmDispList); -} - -void NeoSettingsRestore(NeoSettings *ns, const NeoSettings::Keys::Flags flagsKeys) -{ - ns->bModified = false; - NeoSettings::CVR *cvr = &ns->cvr; - { - NeoSettings::General *pGeneral = &ns->general; - g_pVGuiLocalize->ConvertANSIToUnicode(cvr->neo_name.GetString(), pGeneral->wszNeoName, sizeof(pGeneral->wszNeoName)); - g_pVGuiLocalize->ConvertANSIToUnicode(cvr->neo_clantag.GetString(), pGeneral->wszNeoClantag, sizeof(pGeneral->wszNeoClantag)); - pGeneral->bOnlySteamNick = cvr->cl_onlysteamnick.GetBool(); - pGeneral->bMarkerSpecOnlyClantag = cvr->neo_cl_clantag_friendly_marker_spec_only.GetBool(); - pGeneral->iFov = cvr->neo_fov.GetInt(); - pGeneral->iViewmodelFov = cvr->neo_viewmodel_fov_offset.GetInt(); - pGeneral->bAimHold = cvr->neo_aim_hold.GetBool(); - pGeneral->bReloadEmpty = cvr->cl_autoreload_when_empty.GetBool(); - pGeneral->bViewmodelRighthand = cvr->cl_righthand.GetBool(); - pGeneral->bLeanViewmodelOnly = cvr->cl_neo_lean_viewmodel_only.GetBool(); - pGeneral->bLeanAutomatic = cvr->cl_neo_lean_automatic.GetBool(); - pGeneral->bShowPlayerSprays = !(cvr->cl_playerspraydisable.GetBool()); // Inverse - pGeneral->bShowPos = cvr->cl_showpos.GetBool(); - pGeneral->iShowFps = cvr->cl_showfps.GetInt(); - { - const char *szDlFilter = cvr->cl_downloadfilter.GetString(); - pGeneral->iDlFilter = 0; - for (int i = 0; i < ARRAYSIZE(DLFILTER_STRMAP); ++i) - { - if (V_strcmp(szDlFilter, DLFILTER_STRMAP[i]) == 0) - { - pGeneral->iDlFilter = i; - break; - } - } - } - pGeneral->bStreamerMode = cvr->neo_cl_streamermode.GetBool(); - pGeneral->bAutoDetectOBS = cvr->neo_cl_streamermode_autodetect_obs.GetBool(); - pGeneral->bEnableRangeFinder = cvr->neo_cl_hud_rangefinder_enabled.GetBool(); - pGeneral->iBackground = cvr->sv_unlockedchapters.GetInt(); - } - { - NeoSettings::Keys *pKeys = &ns->keys; - pKeys->bWeaponFastSwitch = cvr->hud_fastswitch.GetBool(); - pKeys->bDeveloperConsole = cvr->neo_cl_toggleconsole.GetBool(); - if (!(flagsKeys & NeoSettings::Keys::SKIP_KEYS)) - { - for (int i = 0; i < pKeys->iBindsSize; ++i) - { - auto *bind = &pKeys->vBinds[i]; - bind->bcNext = bind->bcCurrent = gameuifuncs->GetButtonCodeForBind(bind->szBindingCmd); - } - } - } - { - NeoSettings::Mouse *pMouse = &ns->mouse; - pMouse->flSensitivity = cvr->sensitivity.GetFloat(); - pMouse->bRawInput = cvr->m_rawinput.GetBool(); - pMouse->bFilter = cvr->m_filter.GetBool(); - pMouse->bReverse = (cvr->m_pitch.GetFloat() < 0.0f); - pMouse->bCustomAccel = (cvr->m_customaccel.GetInt() == 3); - pMouse->flExponent = cvr->m_customaccel_exponent.GetFloat(); - } - { - NeoSettings::Audio *pAudio = &ns->audio; - - // Output - pAudio->flVolMain = cvr->volume.GetFloat(); - pAudio->flVolMusic = cvr->snd_musicvolume.GetFloat(); - pAudio->flVolVictory = cvr->snd_victory_volume.GetFloat(); - pAudio->iSoundSetup = 0; - switch (cvr->snd_surround_speakers.GetInt()) - { - break; case SPEAKER_HEADPHONES: pAudio->iSoundSetup = 1; - break; case SPEAKER_STEREO: pAudio->iSoundSetup = 2; -#ifndef LINUX - break; case SPEAKER_QUAD: pAudio->iSoundSetup = 3; - break; case SPEAKER_SURROUND_5_1: pAudio->iSoundSetup = 4; - break; case SPEAKER_SURROUND_7_1: pAudio->iSoundSetup = 5; -#endif - break; default: break; - } - pAudio->bMuteAudioUnFocus = cvr->snd_mute_losefocus.GetBool(); - - // Sound quality: snd_pitchquality dsp_slow_cpu - // High 1 0 - // Medium 0 0 - // Low 0 1 - pAudio->iSoundQuality = (cvr->snd_pitchquality.GetBool()) ? QUALITY_HIGH : - (cvr->dsp_slow_cpu.GetBool()) ? QUALITY_LOW : - QUALITY_MEDIUM; - - // Input - pAudio->bVoiceEnabled = cvr->voice_enable.GetBool(); - pAudio->flVolVoiceRecv = cvr->voice_scale.GetFloat(); - pAudio->bMicBoost = (engine->GetVoiceTweakAPI()->GetControlFloat(MicBoost) > 0.0f); - } - { - NeoSettings::Video *pVideo = &ns->video; - - int iScreenWidth, iScreenHeight; - engine->GetScreenSize(iScreenWidth, iScreenHeight); // Or: g_pMaterialSystem->GetDisplayMode? - pVideo->iResolution = pVideo->iVMListSize - 1; - for (int i = 0; i < pVideo->iVMListSize; ++i) - { - vmode_t *vm = &pVideo->vmList[i]; - if (vm->width == iScreenWidth && vm->height == iScreenHeight) - { - pVideo->iResolution = i; - break; - } - } - - pVideo->iWindow = static_cast(g_pMaterialSystem->GetCurrentConfigForVideoCard().Windowed()); - const int queueMode = cvr->mat_queue_mode.GetInt(); - pVideo->iCoreRendering = (queueMode == -1 || queueMode == 2) ? THREAD_MULTI : THREAD_SINGLE; - pVideo->iModelDetail = 2 - cvr->r_rootlod.GetInt(); // Inverse, highest = 0, lowest = 2 - pVideo->iTextureDetail = 3 - (cvr->mat_picmip.GetInt() + 1); // Inverse+1, highest = -1, lowest = 2 - pVideo->iShaderDetail = 1 - cvr->mat_reducefillrate.GetInt(); // Inverse, 1 = low, 0 = high - // Water detail - // r_waterforceexpensive r_waterforcereflectentities - // Simple: 0 0 - // Reflect World: 1 0 - // Reflect all: 1 1 - pVideo->iWaterDetail = (cvr->r_waterforcereflectentities.GetBool()) ? QUALITY_HIGH : - (cvr->r_waterforceexpensive.GetBool()) ? QUALITY_MEDIUM : - QUALITY_LOW; - - // Shadow detail - // r_flashlightdepthtexture r_shadowrendertotexture - // Low: 0 0 - // Medium: 0 1 - // High: 1 1 - pVideo->iShadowDetail = (cvr->r_flashlightdepthtexture.GetBool()) ? QUALITY_HIGH : - (cvr->r_shadowrendertotexture.GetBool()) ? QUALITY_MEDIUM : - QUALITY_LOW; - - pVideo->bColorCorrection = cvr->mat_colorcorrection.GetBool(); - pVideo->iAntiAliasing = (cvr->mat_antialias.GetInt() / 2); // MSAA: Times by 2 - - // Filtering mode - // mat_trilinear: 0 = bilinear, 1 = trilinear (both: mat_forceaniso 1) - // mat_forceaniso: Antisotropic 2x/4x/8x/16x (all aniso: mat_trilinear 0) - int filterIdx = 0; - if (cvr->mat_forceaniso.GetInt() < 2) - { - filterIdx = cvr->mat_trilinear.GetBool() ? FILTERING_TRILINEAR : FILTERING_BILINEAR; - } - else - { - switch (cvr->mat_forceaniso.GetInt()) - { - break; case 2: filterIdx = FILTERING_ANISO2X; - break; case 4: filterIdx = FILTERING_ANISO4X; - break; case 8: filterIdx = FILTERING_ANISO8X; - break; case 16: filterIdx = FILTERING_ANISO16X; - break; default: filterIdx = FILTERING_ANISO4X; // Some invalid number, just set to 4X (idx 3) - } - } - pVideo->iFilteringMode = filterIdx; - pVideo->bVSync = cvr->mat_vsync.GetBool(); - pVideo->bMotionBlur = cvr->mat_motion_blur_enabled.GetBool(); - pVideo->iHDR = cvr->mat_hdr_level.GetInt(); - pVideo->flGamma = cvr->mat_monitorgamma.GetFloat(); - } - { - NeoSettings::Crosshair *pCrosshair = &ns->crosshair; - pCrosshair->iStyle = cvr->neo_cl_crosshair_style.GetInt(); - pCrosshair->info.color[0] = (uint8)(cvr->neo_cl_crosshair_color_r.GetInt()); - pCrosshair->info.color[1] = (uint8)(cvr->neo_cl_crosshair_color_g.GetInt()); - pCrosshair->info.color[2] = (uint8)(cvr->neo_cl_crosshair_color_b.GetInt()); - pCrosshair->info.color[3] = (uint8)(cvr->neo_cl_crosshair_color_a.GetInt()); - pCrosshair->info.iESizeType = cvr->neo_cl_crosshair_size_type.GetInt(); - pCrosshair->info.iSize = cvr->neo_cl_crosshair_size.GetInt(); - pCrosshair->info.flScrSize = cvr->neo_cl_crosshair_size_screen.GetFloat(); - pCrosshair->info.iThick = cvr->neo_cl_crosshair_thickness.GetInt(); - pCrosshair->info.iGap = cvr->neo_cl_crosshair_gap.GetInt(); - pCrosshair->info.iOutline = cvr->neo_cl_crosshair_outline.GetInt(); - pCrosshair->info.iCenterDot = cvr->neo_cl_crosshair_center_dot.GetInt(); - pCrosshair->info.bTopLine = cvr->neo_cl_crosshair_top_line.GetBool(); - pCrosshair->info.iCircleRad = cvr->neo_cl_crosshair_circle_radius.GetInt(); - pCrosshair->info.iCircleSegments = cvr->neo_cl_crosshair_circle_segments.GetInt(); - } -} - -void NeoToggleConsoleEnforce() -{ - // NEO JANK (nullsystem): Try to unbind toggleconsole when possible - const auto toggleConsoleBind = gameuifuncs->GetButtonCodeForBind("toggleconsole"); - const auto neotoggleConsoleBind = gameuifuncs->GetButtonCodeForBind("neo_toggleconsole"); - const char *bindBtnName = g_pInputSystem->ButtonCodeToString(toggleConsoleBind); - if (bindBtnName && bindBtnName[0]) - { - char szCmdStr[128]; - V_sprintf_safe(szCmdStr, "unbind \"%s\"\n", bindBtnName); - engine->ClientCmd_Unrestricted(szCmdStr); - } - - // NEO JANK (nullsystem): Try to bind to ` if this is none. This should always be bind - // wether the console is enabled or not. If they're on a keyboard layout that can't utilise this - // key, they can just rebind it to another key themselves. - if (neotoggleConsoleBind <= BUTTON_CODE_NONE) - { - engine->ClientCmd_Unrestricted("bind ` neo_toggleconsole"); - } - else if (toggleConsoleBind == neotoggleConsoleBind) - { - // Could be unbinded by the unbind at this point if toggleconsole overlaps, so bring it back to - // neo_toggleconsole - const char *bindBtnName = g_pInputSystem->ButtonCodeToString(neotoggleConsoleBind); - if (bindBtnName && bindBtnName[0]) - { - char szCmdStr[128]; - V_sprintf_safe(szCmdStr, "bind \"%s\" neo_toggleconsole\n", bindBtnName); - engine->ClientCmd_Unrestricted(szCmdStr); - } - } -} - -void NeoSettingsSave(const NeoSettings *ns) -{ - const_cast(ns)->bModified = false; - auto *cvr = const_cast(&ns->cvr); - { - const NeoSettings::General *pGeneral = &ns->general; - char neoNameText[sizeof(pGeneral->wszNeoName)]; - g_pVGuiLocalize->ConvertUnicodeToANSI(pGeneral->wszNeoName, neoNameText, sizeof(neoNameText)); - cvr->neo_name.SetValue(neoNameText); - char neoClantagText[sizeof(pGeneral->wszNeoClantag)]; - g_pVGuiLocalize->ConvertUnicodeToANSI(pGeneral->wszNeoClantag, neoClantagText, sizeof(neoClantagText)); - cvr->neo_clantag.SetValue(neoClantagText); - cvr->cl_onlysteamnick.SetValue(pGeneral->bOnlySteamNick); - cvr->neo_cl_clantag_friendly_marker_spec_only.SetValue(pGeneral->bMarkerSpecOnlyClantag); - cvr->neo_fov.SetValue(pGeneral->iFov); - cvr->neo_viewmodel_fov_offset.SetValue(pGeneral->iViewmodelFov); - cvr->neo_aim_hold.SetValue(pGeneral->bAimHold); - cvr->cl_autoreload_when_empty.SetValue(pGeneral->bReloadEmpty); - cvr->cl_righthand.SetValue(pGeneral->bViewmodelRighthand); - cvr->cl_neo_lean_viewmodel_only.SetValue(pGeneral->bLeanViewmodelOnly); - cvr->cl_neo_lean_automatic.SetValue(pGeneral->bLeanAutomatic); - cvr->cl_playerspraydisable.SetValue(!pGeneral->bShowPlayerSprays); // Inverse - cvr->cl_showpos.SetValue(pGeneral->bShowPos); - cvr->cl_showfps.SetValue(pGeneral->iShowFps); - cvr->cl_downloadfilter.SetValue(DLFILTER_STRMAP[pGeneral->iDlFilter]); - cvr->neo_cl_streamermode.SetValue(pGeneral->bStreamerMode); - cvr->neo_cl_streamermode_autodetect_obs.SetValue(pGeneral->bAutoDetectOBS); - cvr->neo_cl_hud_rangefinder_enabled.SetValue(pGeneral->bEnableRangeFinder); - cvr->sv_unlockedchapters.SetValue(pGeneral->iBackground); - } - { - const NeoSettings::Keys *pKeys = &ns->keys; - cvr->hud_fastswitch.SetValue(pKeys->bWeaponFastSwitch); - NeoToggleConsoleEnforce(); - cvr->neo_cl_toggleconsole.SetValue(pKeys->bDeveloperConsole); - for (int i = 0; i < pKeys->iBindsSize; ++i) - { - const auto *bind = &pKeys->vBinds[i]; - if (bind->szBindingCmd[0] != '\0' && bind->bcCurrent > KEY_NONE) - { - char cmdStr[128]; - const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcCurrent); - V_sprintf_safe(cmdStr, "unbind \"%s\"\n", bindBtnName); - engine->ClientCmd_Unrestricted(cmdStr); - } - } - for (int i = 0; i < pKeys->iBindsSize; ++i) - { - auto *bind = const_cast(&pKeys->vBinds[i]); - if (bind->szBindingCmd[0] != '\0' && bind->bcNext > KEY_NONE) - { - char cmdStr[128]; - const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcNext); - V_sprintf_safe(cmdStr, "bind \"%s\" \"%s\"\n", bindBtnName, bind->szBindingCmd); - engine->ClientCmd_Unrestricted(cmdStr); - } - bind->bcCurrent = bind->bcNext; - } - // Reset the cache to none so it'll refresh on next KeyCodeTyped - const_cast(pKeys)->bcConsole = KEY_NONE; - } - { - const NeoSettings::Mouse *pMouse = &ns->mouse; - cvr->sensitivity.SetValue(pMouse->flSensitivity); - cvr->m_rawinput.SetValue(pMouse->bRawInput); - cvr->m_filter.SetValue(pMouse->bFilter); - const float absPitch = abs(cvr->m_pitch.GetFloat()); - cvr->m_pitch.SetValue(pMouse->bReverse ? -absPitch : absPitch); - cvr->m_customaccel.SetValue(pMouse->bCustomAccel ? 3 : 0); - cvr->m_customaccel_exponent.SetValue(pMouse->flExponent); - } - { - const NeoSettings::Audio *pAudio = &ns->audio; - - static constexpr int SURROUND_RE_MAP[] = { - SPEAKER_AUTO, - SPEAKER_HEADPHONES, - SPEAKER_STEREO, -#ifndef LINUX - SPEAKER_QUAD, - SPEAKER_SURROUND_5_1, - SPEAKER_SURROUND_7_1, -#endif - }; - - // Output - cvr->volume.SetValue(pAudio->flVolMain); - cvr->snd_musicvolume.SetValue(pAudio->flVolMusic); - cvr->snd_victory_volume.SetValue(pAudio->flVolVictory); - cvr->snd_surround_speakers.SetValue(SURROUND_RE_MAP[pAudio->iSoundSetup]); - cvr->snd_mute_losefocus.SetValue(pAudio->bMuteAudioUnFocus); - cvr->snd_pitchquality.SetValue(pAudio->iSoundQuality == QUALITY_HIGH); - cvr->dsp_slow_cpu.SetValue(pAudio->iSoundQuality == QUALITY_LOW); - - // Input - cvr->voice_enable.SetValue(pAudio->bVoiceEnabled); - cvr->voice_scale.SetValue(pAudio->flVolVoiceRecv); - engine->GetVoiceTweakAPI()->SetControlFloat(MicBoost, static_cast(pAudio->bMicBoost)); - } - { - const NeoSettings::Video *pVideo = &ns->video; - - const int resIdx = pVideo->iResolution; - if (resIdx >= 0 && resIdx < pVideo->iVMListSize) - { - // mat_setvideomode [width] [height] [mode] | mode: 0 = fullscreen, 1 = windowed - vmode_t *vm = &pVideo->vmList[resIdx]; - char cmdStr[128]; - V_sprintf_safe(cmdStr, "mat_setvideomode %d %d %d", vm->width, vm->height, pVideo->iWindow); - engine->ClientCmd_Unrestricted(cmdStr); - } - cvr->mat_queue_mode.SetValue((pVideo->iCoreRendering == THREAD_MULTI) ? 2 : 0); - cvr->r_rootlod.SetValue(2 - pVideo->iModelDetail); - cvr->mat_picmip.SetValue(2 - pVideo->iTextureDetail); - cvr->mat_reducefillrate.SetValue(1 - pVideo->iShaderDetail); - cvr->r_waterforceexpensive.SetValue(pVideo->iWaterDetail >= QUALITY_MEDIUM); - cvr->r_waterforcereflectentities.SetValue(pVideo->iWaterDetail == QUALITY_HIGH); - cvr->r_shadowrendertotexture.SetValue(pVideo->iShadowDetail >= QUALITY_MEDIUM); - cvr->r_flashlightdepthtexture.SetValue(pVideo->iShadowDetail == QUALITY_HIGH); - cvr->mat_colorcorrection.SetValue(pVideo->bColorCorrection); - cvr->mat_antialias.SetValue(pVideo->iAntiAliasing * 2); - cvr->mat_trilinear.SetValue(pVideo->iFilteringMode == FILTERING_TRILINEAR); - static constexpr int ANISO_MAP[FILTERING__TOTAL] = { - 1, 1, 2, 4, 8, 16 - }; - cvr->mat_forceaniso.SetValue(ANISO_MAP[pVideo->iFilteringMode]); - cvr->mat_vsync.SetValue(pVideo->bVSync); - cvr->mat_motion_blur_enabled.SetValue(pVideo->bMotionBlur); - cvr->mat_hdr_level.SetValue(pVideo->iHDR); - cvr->mat_monitorgamma.SetValue(pVideo->flGamma); - } - { - const NeoSettings::Crosshair *pCrosshair = &ns->crosshair; - cvr->neo_cl_crosshair_style.SetValue(pCrosshair->iStyle); - cvr->neo_cl_crosshair_color_r.SetValue(pCrosshair->info.color.r()); - cvr->neo_cl_crosshair_color_g.SetValue(pCrosshair->info.color.g()); - cvr->neo_cl_crosshair_color_b.SetValue(pCrosshair->info.color.b()); - cvr->neo_cl_crosshair_color_a.SetValue(pCrosshair->info.color.a()); - cvr->neo_cl_crosshair_size_type.SetValue(pCrosshair->info.iESizeType); - cvr->neo_cl_crosshair_size.SetValue(pCrosshair->info.iSize); - cvr->neo_cl_crosshair_size_screen.SetValue(pCrosshair->info.flScrSize); - cvr->neo_cl_crosshair_thickness.SetValue(pCrosshair->info.iThick); - cvr->neo_cl_crosshair_gap.SetValue(pCrosshair->info.iGap); - cvr->neo_cl_crosshair_outline.SetValue(pCrosshair->info.iOutline); - cvr->neo_cl_crosshair_center_dot.SetValue(pCrosshair->info.iCenterDot); - cvr->neo_cl_crosshair_top_line.SetValue(pCrosshair->info.bTopLine); - cvr->neo_cl_crosshair_circle_radius.SetValue(pCrosshair->info.iCircleRad); - cvr->neo_cl_crosshair_circle_segments.SetValue(pCrosshair->info.iCircleSegments); - } - - engine->ClientCmd_Unrestricted("host_writeconfig"); - engine->ClientCmd_Unrestricted("mat_savechanges"); -} - -void NeoSettingsResetToDefault(NeoSettings *ns) -{ - // NEO NOTE (nullsystem): The only thing left out is video mode and volume, but that's fine - // as we shouldn't need to be altering those - for (ConVarRefEx *convar : g_vecConVarRefPtrs) - { - convar->SetValue(convar->GetDefault()); - } - - NeoSettings::Keys *pKeys = &ns->keys; - for (int i = 0; i < pKeys->iBindsSize; ++i) - { - const auto *bind = &pKeys->vBinds[i]; - if (bind->szBindingCmd[0] != '\0' && bind->bcCurrent > KEY_NONE) - { - char cmdStr[128]; - const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcCurrent); - V_sprintf_safe(cmdStr, "unbind \"%s\"\n", bindBtnName); - engine->ClientCmd_Unrestricted(cmdStr); - } - } - for (int i = 0; i < pKeys->iBindsSize; ++i) - { - auto *bind = &pKeys->vBinds[i]; - if (bind->szBindingCmd[0] != '\0' && bind->bcDefault > KEY_NONE) - { - char cmdStr[128]; - const char *bindBtnName = g_pInputSystem->ButtonCodeToString(bind->bcDefault); - V_sprintf_safe(cmdStr, "bind \"%s\" \"%s\"\n", bindBtnName, bind->szBindingCmd); - engine->ClientCmd_Unrestricted(cmdStr); - } - bind->bcCurrent = bind->bcNext = bind->bcDefault; - } - - engine->ClientCmd_Unrestricted("host_writeconfig"); - - // NEO JANK (nullsystem): For some reason, bind -> gameuifuncs->GetButtonCodeForBind is too quick for - // the game engine at this point. So just omit setting binds in restore since we already have anyway. - NeoSettingsRestore(ns, NeoSettings::Keys::SKIP_KEYS); -} - -static const wchar_t *DLFILTER_LABELS[] = { - L"Allow all custom files from server", - L"Do not download custom sounds", - L"Only allow map files", - L"Do not download any custom files", -}; -static const wchar_t *SHOWFPS_LABELS[] = { L"Disabled", L"Enabled (FPS)", L"Enabled (Smooth FPS)", }; -static_assert(ARRAYSIZE(DLFILTER_STRMAP) == ARRAYSIZE(DLFILTER_LABELS)); - -void NeoSettings_General(NeoSettings *ns) -{ - NeoSettings::General *pGeneral = &ns->general; - NeoUI::TextEdit(L"Name", pGeneral->wszNeoName, SZWSZ_LEN(pGeneral->wszNeoName)); - NeoUI::TextEdit(L"Clan tag", pGeneral->wszNeoClantag, SZWSZ_LEN(pGeneral->wszNeoClantag)); - NeoUI::RingBoxBool(L"Show only steam name", &pGeneral->bOnlySteamNick); - NeoUI::RingBoxBool(L"Friendly marker spectator only clantags", &pGeneral->bMarkerSpecOnlyClantag); - - wchar_t wszTotalClanAndName[NEO_MAX_DISPLAYNAME]; - GetClNeoDisplayName(wszTotalClanAndName, pGeneral->wszNeoName, pGeneral->wszNeoClantag, pGeneral->bOnlySteamNick); - NeoUI::Label(L"Display name", wszTotalClanAndName); - - NeoUI::SliderInt(L"FOV", &pGeneral->iFov, 75, 110); - NeoUI::SliderInt(L"Viewmodel FOV Offset", &pGeneral->iViewmodelFov, -20, 40); - NeoUI::RingBoxBool(L"Aim hold", &pGeneral->bAimHold); - NeoUI::RingBoxBool(L"Reload empty", &pGeneral->bReloadEmpty); - NeoUI::RingBoxBool(L"Right hand viewmodel", &pGeneral->bViewmodelRighthand); - NeoUI::RingBoxBool(L"Lean viewmodel only", &pGeneral->bLeanViewmodelOnly); - NeoUI::RingBoxBool(L"Automatic leaning", &pGeneral->bLeanAutomatic); - NeoUI::RingBoxBool(L"Show player spray", &pGeneral->bShowPlayerSprays); - NeoUI::RingBoxBool(L"Show position", &pGeneral->bShowPos); - NeoUI::RingBox(L"Show FPS", SHOWFPS_LABELS, ARRAYSIZE(SHOWFPS_LABELS), &pGeneral->iShowFps); - NeoUI::RingBox(L"Download filter", DLFILTER_LABELS, ARRAYSIZE(DLFILTER_LABELS), &pGeneral->iDlFilter); - NeoUI::RingBoxBool(L"Streamer mode", &pGeneral->bStreamerMode); - NeoUI::RingBoxBool(L"Auto streamer mode (requires restart)", &pGeneral->bAutoDetectOBS); - NeoUI::Label(L"OBS detection", g_bOBSDetected ? L"OBS detected on startup" : L"Not detected on startup"); - NeoUI::RingBoxBool(L"Show rangefinder", &pGeneral->bEnableRangeFinder); - NeoUI::SliderInt(L"Selected Background", &pGeneral->iBackground, 0, 15); // NEO TODO (Adam) switch to RingBox with values read from ChapterBackgrounds.txt -} - -void NeoSettings_Keys(NeoSettings *ns) -{ - NeoSettings::Keys *pKeys = &ns->keys; - NeoUI::RingBoxBool(L"Weapon fastswitch", &pKeys->bWeaponFastSwitch); - NeoUI::RingBoxBool(L"Developer console", &pKeys->bDeveloperConsole); - g_uiCtx.eLabelTextStyle = NeoUI::TEXTSTYLE_CENTER; - for (int i = 0; i < pKeys->iBindsSize; ++i) - { - const auto &bind = pKeys->vBinds[i]; - if (bind.szBindingCmd[0] == '\0') - { - NeoUI::Label(bind.wszDisplayText); - } - else - { - wchar_t wszBindBtnName[64]; - const char *szBindBtnName = g_pInputSystem->ButtonCodeToString(bind.bcNext); - g_pVGuiLocalize->ConvertANSIToUnicode(szBindBtnName, wszBindBtnName, sizeof(wszBindBtnName)); - if (NeoUI::Button(bind.wszDisplayText, wszBindBtnName).bPressed) - { - ns->iNextBinding = i; - } - } - } -} - -void NeoSettings_Mouse(NeoSettings *ns) -{ - NeoSettings::Mouse *pMouse = &ns->mouse; - NeoUI::Slider(L"Sensitivity", &pMouse->flSensitivity, 0.1f, 10.0f, 2, 0.25f); - NeoUI::RingBoxBool(L"Raw input", &pMouse->bRawInput); - NeoUI::RingBoxBool(L"Mouse Filter", &pMouse->bFilter); - NeoUI::RingBoxBool(L"Mouse Reverse", &pMouse->bReverse); - NeoUI::RingBoxBool(L"Custom Acceleration", &pMouse->bCustomAccel); - NeoUI::Slider(L"Exponent", &pMouse->flExponent, 1.0f, 1.4f, 2, 0.1f); -} - -void NeoSettings_Audio(NeoSettings *ns) -{ - NeoSettings::Audio *pAudio = &ns->audio; - NeoUI::Slider(L"Main Volume", &pAudio->flVolMain, 0.0f, 1.0f, 2, 0.1f); - NeoUI::Slider(L"Music Volume", &pAudio->flVolMusic, 0.0f, 1.0f, 2, 0.1f); - NeoUI::Slider(L"Victory Volume", &pAudio->flVolVictory, 0.0f, 1.0f, 2, 0.1f); - NeoUI::RingBox(L"Sound Setup", SPEAKER_CFG_LABELS, ARRAYSIZE(SPEAKER_CFG_LABELS), &pAudio->iSoundSetup); - NeoUI::RingBox(L"Sound Quality", QUALITY_LABELS, 3, &pAudio->iSoundQuality); - NeoUI::RingBoxBool(L"Mute Audio on un-focus", &pAudio->bMuteAudioUnFocus); - NeoUI::RingBoxBool(L"Voice Enabled", &pAudio->bVoiceEnabled); - NeoUI::Slider(L"Voice Receive", &pAudio->flVolVoiceRecv, 0.0f, 1.0f, 2, 0.1f); - NeoUI::RingBoxBool(L"Microphone Boost", &pAudio->bMicBoost); - IVoiceTweak_s *pVoiceTweak = engine->GetVoiceTweakAPI(); - const bool bTweaking = pVoiceTweak->IsStillTweaking(); - if (bTweaking && g_uiCtx.eMode == NeoUI::MODE_PAINT) - { - // Only fetch the value at interval as immediate is too quick/flickers, and give a longer delay when - // it goes from sound to no sound. - static constexpr float FL_FETCH_INTERVAL = 0.1f; - static constexpr float FL_SILENCE_INTERVAL = 0.4f; - const float flNowSpeakingVol = pVoiceTweak->GetControlFloat(SpeakingVolume); - if ((flNowSpeakingVol > 0.0f && pAudio->flLastFetchInterval + FL_FETCH_INTERVAL < gpGlobals->curtime) || - (flNowSpeakingVol == 0.0f && pAudio->flSpeakingVol > 0.0f && - pAudio->flLastFetchInterval + FL_SILENCE_INTERVAL < gpGlobals->curtime)) - { - pAudio->flSpeakingVol = flNowSpeakingVol; - pAudio->flLastFetchInterval = gpGlobals->curtime; - } - vgui::surface()->DrawSetColor(COLOR_NEOPANELMICTEST); - NeoUI::GCtxDrawFilledRectXtoX(g_uiCtx.iWgXPos, 0, - g_uiCtx.iWgXPos + (pAudio->flSpeakingVol * (g_uiCtx.dPanel.wide - g_uiCtx.iWgXPos)), g_uiCtx.iRowTall); - vgui::surface()->DrawSetColor(COLOR_TRANSPARENT); - g_uiCtx.selectBgColor = COLOR_TRANSPARENT; - } - if (NeoUI::Button(L"Microphone Tester", - bTweaking ? L"Stop testing" : L"Start testing").bPressed) - { - bTweaking ? pVoiceTweak->EndVoiceTweakMode() : (void)pVoiceTweak->StartVoiceTweakMode(); - pAudio->flSpeakingVol = 0.0f; - pAudio->flLastFetchInterval = 0.0f; - } - if (bTweaking && g_uiCtx.eMode == NeoUI::MODE_PAINT) - { - vgui::surface()->DrawSetColor(COLOR_NEOPANELACCENTBG); - g_uiCtx.selectBgColor = COLOR_NEOPANELSELECTBG; - } -} - -static const wchar_t *WINDOW_MODE[] = { L"Fullscreen", L"Windowed", }; -static const wchar_t *QUEUE_MODE[] = { L"Single", L"Multi", }; -static const wchar_t *QUALITY2_LABELS[] = { L"Low", L"High", }; -static const wchar_t *FILTERING_LABELS[FILTERING__TOTAL] = { - L"Bilinear", L"Trilinear", L"Anisotropic 2X", L"Anisotropic 4X", L"Anisotropic 8X", L"Anisotropic 16X", -}; -static const wchar_t *HDR_LABELS[] = { L"None", L"Bloom", L"Full", }; -static const wchar_t *WATER_LABELS[] = { L"Simple Reflect", L"Reflect World", L"Reflect All", }; -static const wchar_t *MSAA_LABELS[] = { L"None", L"2x MSAA", L"4x MSAA", L"6x MSAA", L"8x MSAA", }; - -void NeoSettings_Video(NeoSettings *ns) -{ - NeoSettings::Video *pVideo = &ns->video; - NeoUI::RingBox(L"Resolution", const_cast(pVideo->p2WszVmDispList), pVideo->iVMListSize, &pVideo->iResolution); - NeoUI::RingBox(L"Window", WINDOW_MODE, ARRAYSIZE(WINDOW_MODE), &pVideo->iWindow); - NeoUI::RingBox(L"Core Rendering", QUEUE_MODE, ARRAYSIZE(QUEUE_MODE), &pVideo->iCoreRendering); - NeoUI::RingBox(L"Model detail", QUALITY_LABELS, 3, &pVideo->iModelDetail); - NeoUI::RingBox(L"Texture detail", QUALITY_LABELS, 4, &pVideo->iTextureDetail); - NeoUI::RingBox(L"Shader detail", QUALITY2_LABELS, 2, &pVideo->iShaderDetail); - NeoUI::RingBox(L"Water detail", WATER_LABELS, ARRAYSIZE(WATER_LABELS), &pVideo->iWaterDetail); - NeoUI::RingBox(L"Shadow detail", QUALITY_LABELS, 3, &pVideo->iShadowDetail); - NeoUI::RingBoxBool(L"Color correction", &pVideo->bColorCorrection); - NeoUI::RingBox(L"Anti-aliasing", MSAA_LABELS, ARRAYSIZE(MSAA_LABELS), &pVideo->iAntiAliasing); - NeoUI::RingBox(L"Filtering mode", FILTERING_LABELS, FILTERING__TOTAL, &pVideo->iFilteringMode); - NeoUI::RingBoxBool(L"V-Sync", &pVideo->bVSync); - NeoUI::RingBoxBool(L"Motion blur", &pVideo->bMotionBlur); - NeoUI::RingBox(L"HDR", HDR_LABELS, ARRAYSIZE(HDR_LABELS), &pVideo->iHDR); - NeoUI::Slider(L"Gamma", &pVideo->flGamma, 1.6, 2.6, 2, 0.1f); -} - -void NeoSettings_Crosshair(NeoSettings *ns) -{ - static constexpr int IVIEW_ROWS = 5; - NeoSettings::Crosshair *pCrosshair = &ns->crosshair; - - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * IVIEW_ROWS; - NeoUI::BeginSection(); - const bool bTextured = CROSSHAIR_FILES[pCrosshair->iStyle][0]; - if (bTextured) - { - NeoSettings::Crosshair::Texture *pTex = &ns->crosshair.arTextures[pCrosshair->iStyle]; - vgui::surface()->DrawSetTexture(pTex->iTexId); - vgui::surface()->DrawSetColor(pCrosshair->info.color); - vgui::surface()->DrawTexturedRect( - g_uiCtx.dPanel.x + g_uiCtx.iLayoutX - (pTex->iWide / 2) + (g_uiCtx.dPanel.wide / 2), - g_uiCtx.dPanel.y + g_uiCtx.iLayoutY, - g_uiCtx.dPanel.x + g_uiCtx.iLayoutX + (pTex->iWide / 2) + (g_uiCtx.dPanel.wide / 2), - g_uiCtx.dPanel.y + g_uiCtx.iLayoutY + pTex->iTall); - } - else - { - PaintCrosshair(pCrosshair->info, - g_uiCtx.dPanel.x + g_uiCtx.iLayoutX + (g_uiCtx.dPanel.wide / 2), - g_uiCtx.dPanel.y + g_uiCtx.iLayoutY + (g_uiCtx.dPanel.tall / 2)); - } - vgui::surface()->DrawSetColor(g_uiCtx.normalBgColor); - - if (pCrosshair->iStyle == CROSSHAIR_STYLE_CUSTOM) - { - NeoUI::BeginHorizontal(g_uiCtx.dPanel.wide / 5); - { - const bool bPresExport = NeoUI::Button(L"Export").bPressed; - const bool bPresImport = NeoUI::Button(L"Import").bPressed; - if (bPresExport || bPresImport) - { - if (g_pNeoRoot->m_pFileIODialog) - { - g_pNeoRoot->m_pFileIODialog->MarkForDeletion(); - } - pCrosshair->eFileIOMode = bPresImport ? vgui::FOD_OPEN : vgui::FOD_SAVE; - g_pNeoRoot->m_pFileIODialog = new vgui::FileOpenDialog(g_pNeoRoot, - bPresImport ? "Import crosshair" : "Export crosshair", - pCrosshair->eFileIOMode); - g_pNeoRoot->m_pFileIODialog->AddFilter("*." NEO_XHAIR_EXT, "NT;RE Crosshair", true); - g_pNeoRoot->m_pFileIODialog->DoModal(); - } - } - NeoUI::EndHorizontal(); - } - NeoUI::EndSection(); - - g_uiCtx.dPanel.y += g_uiCtx.dPanel.tall; - g_uiCtx.dPanel.tall = g_uiCtx.iRowTall * (g_iRowsInScreen - IVIEW_ROWS); - NeoUI::BeginSection(true); - NeoUI::RingBox(L"Crosshair style", CROSSHAIR_LABELS, CROSSHAIR_STYLE__TOTAL, &pCrosshair->iStyle); - NeoUI::SliderU8(L"Red", &pCrosshair->info.color[0], 0, UCHAR_MAX); - NeoUI::SliderU8(L"Green", &pCrosshair->info.color[1], 0, UCHAR_MAX); - NeoUI::SliderU8(L"Blue", &pCrosshair->info.color[2], 0, UCHAR_MAX); - NeoUI::SliderU8(L"Alpha", &pCrosshair->info.color[3], 0, UCHAR_MAX); - if (!bTextured) - { - NeoUI::RingBox(L"Size type", CROSSHAIR_SIZETYPE_LABELS, CROSSHAIR_SIZETYPE__TOTAL, &pCrosshair->info.iESizeType); - switch (pCrosshair->info.iESizeType) - { - case CROSSHAIR_SIZETYPE_ABSOLUTE: NeoUI::SliderInt(L"Size", &pCrosshair->info.iSize, 0, CROSSHAIR_MAX_SIZE); break; - case CROSSHAIR_SIZETYPE_SCREEN: NeoUI::Slider(L"Size", &pCrosshair->info.flScrSize, 0.0f, 1.0f, 5, 0.01f); break; - } - NeoUI::SliderInt(L"Thickness", &pCrosshair->info.iThick, 0, CROSSHAIR_MAX_THICKNESS); - NeoUI::SliderInt(L"Gap", &pCrosshair->info.iGap, 0, CROSSHAIR_MAX_GAP); - NeoUI::SliderInt(L"Outline", &pCrosshair->info.iOutline, 0, CROSSHAIR_MAX_OUTLINE); - NeoUI::SliderInt(L"Center dot", &pCrosshair->info.iCenterDot, 0, CROSSHAIR_MAX_CENTER_DOT); - NeoUI::RingBoxBool(L"Draw top line", &pCrosshair->info.bTopLine); - NeoUI::SliderInt(L"Circle radius", &pCrosshair->info.iCircleRad, 0, CROSSHAIR_MAX_CIRCLE_RAD); - NeoUI::SliderInt(L"Circle segments", &pCrosshair->info.iCircleSegments, 0, CROSSHAIR_MAX_CIRCLE_SEGMENTS); - } - NeoUI::EndSection(); -} diff --git a/mp/src/game/client/neo/ui/neo_root_settings.cpp b/mp/src/game/client/neo/ui/neo_root_settings.cpp index db16ccd12..9cca5c054 100644 --- a/mp/src/game/client/neo/ui/neo_root_settings.cpp +++ b/mp/src/game/client/neo/ui/neo_root_settings.cpp @@ -658,7 +658,7 @@ void NeoSettings_General(NeoSettings *ns) NeoUI::RingBoxBool(L"Auto streamer mode (requires restart)", &pGeneral->bAutoDetectOBS); NeoUI::Label(L"OBS detection", g_bOBSDetected ? L"OBS detected on startup" : L"Not detected on startup"); NeoUI::RingBoxBool(L"Show rangefinder", &pGeneral->bEnableRangeFinder); - NeoUI::SliderInt(L"Selected Background", &pGeneral->iBackground, 0, 2); // NEO TODO (Adam) switch to RingBox with values read from ChapterBackgrounds.txt + NeoUI::SliderInt(L"Selected Background", &pGeneral->iBackground, 1, 4); // NEO TODO (Adam) switch to RingBox with values read from ChapterBackgrounds.txt } void NeoSettings_Keys(NeoSettings *ns) diff --git a/mp/src/game/client/view.cpp b/mp/src/game/client/view.cpp index c47035f6e..13dbec109 100644 --- a/mp/src/game/client/view.cpp +++ b/mp/src/game/client/view.cpp @@ -768,7 +768,7 @@ void CViewRender::SetUpViews() #ifndef NEO view.fov = default_fov.GetFloat(); #else - view.fov = neo_fov.GetFloat(); + view.fov = engine->IsLevelMainMenuBackground() ? 75 : neo_fov.GetFloat(); #endif view.m_bOrtho = false; diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index ddc7ef790..b6a0bc10b 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -1996,6 +1996,10 @@ int CBasePlayer::GetDefaultFOV( void ) const #ifdef CLIENT_DLL int iFOV = neo_fov.GetInt(); #else + if (gpGlobals->eLoadType == MapLoad_Background) + { + return 75; + } int iFOV = ( m_iDefaultFOV == 0 ) ? g_pGameRules->DefaultFOV() : m_iDefaultFOV; if (!(GetFlags() & FL_FAKECLIENT)) { From be22e48a4f4f4ac4cead7d463560ecc35c4bfc96 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 13 Feb 2025 22:16:47 +0000 Subject: [PATCH 09/10] red dots --- mp/game/neo/resource/neotokyo_press_n.ttf | Bin 17348 -> 17440 bytes mp/src/game/client/neo/ui/neo_root.cpp | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mp/game/neo/resource/neotokyo_press_n.ttf b/mp/game/neo/resource/neotokyo_press_n.ttf index f3c9c94305a718203b9749a3189b2aa473b9f685..6bf011e7679e6a437c022dbc5d1167dff3534865 100644 GIT binary patch delta 939 zcmbV~Ur19?7{I@CH{D;i-Mf2t*G-pBx0xF{|7=$FXOU?InrKNgA%~eFmQf}ugNaG` zr+2=*X8=n#>bW)eR17Kpg5b7k}pJyiTSob!F(;deebU+_5^ z>q7;A03ZpvK>!scB{$0YG6tOh#X_7-E-k)X0*{~y;L;9`b=RwM@-7@a{W?^TUbcx7 z;>MQFdpGNxJ^+ayAa}H>!FAWUs(p)VeBIuJ6VAOiWdMlAaYobqwvI*GXvFbr0D-@y zwchn)ym5ADTz{sh7$EW5!`8=buGXL%;NlyEb@->><^HMu?Qg8=~wal zm(>*Z1-gw+4%ebXF_8ljyu`zGL<0)UEE28+&w(`gpU9Ltq|H*VG#FAzatgEJQEsc;7+;)u)x0XC`c7(& zI7R*+mE_;z`SV3D`8%`ZBDqfPQb1X$YN~@8qdrpW)DCs1rqvd8wYpn9sotkM=ze;a zK427#j=9B5Xeu>xJgk`2vE^(#+sk^j3avxy){bcBcnIzC%!Fh~?U4|ZC@ky&8Gt%p z!!n6xWITuLpUnZ2X`b227WSa9X3G??tnvSfKpg8wVImpu;2^8bn6A&&i>yo{YZbBi z7m&RWg-rpoKO1e=(+iBlB18twR>(4y>7!|1Cmvbe0kJwE#76OK!*Ewhk%x#a00>Vf z3}CAkUtsf7NoxvHrRj6=!A9B&(^x{4szNKAfyj!443Q9rHn|b>O1R5K?He`GJhU7j zY#%r-vJ@>x)A$uZWME)B7Xqz^_+OGt6}9N(}-$;6DMSQ|VCv delta 835 zcmZ3`!FZ&d(S(7Kfq{XSp@D&!A;8To#J59PcM}7H^9rD-jJu1g8$%I8Fp%E?l@ksYJNA-MA^3iD8P}PQ<;{mQ+|ShffJ~~&>v5nN+6)Yn z6PQvNCu}~(l*n5Dh?6wlfEAZY6F%?kXUh#=VF82?X*8 z0ig#^7*8M11~B}_o5iQY=fJm%?+1Sa5H70c-y+}#ge6eeBhVwTLg0YF3lJ3KA`_|z z5)13GE6fr^hi!s01Xl^}5WFPBB%~qaB~&CdM`)GMHlcGu&xHO7YX}Dk*9e~y@e)Z8 z*&%X9AbXQ*%Xe(Z3$-Hh;Gll`NP2w^T}s$p~zf x$v<@|DaJS{W{ZCXhSt-pG-ae1zexQvihBFcPl}P@iDrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl); + surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, WSZ_GAME_TITLE1_a, iFirstWidth, iFirstHeight); surface()->DrawSetTextColor(COLOR_BLACK); surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) - 8, iTitleMarginTop + 8); surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); surface()->DrawSetTextColor(COLOR_NEOTITLE); surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), iTitleMarginTop); - surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); + surface()->DrawPrintText(WSZ_GAME_TITLE1_a, SZWSZ_LEN(WSZ_GAME_TITLE1_a)); + surface()->DrawSetTextColor(COLOR_RED); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + iFirstWidth, iTitleMarginTop); + surface()->DrawPrintText(WSZ_GAME_TITLE1_b, SZWSZ_LEN(WSZ_GAME_TITLE1_b)); surface()->DrawSetTextColor(COLOR_BLACK); surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - 8, iTitleMarginTop + m_iTitleHeight + 8); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); + surface()->DrawSetTextColor(COLOR_BLACK); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - 8, iTitleMarginTop + m_iTitleHeight + 8); + surface()->DrawPrintText(L"G", SZWSZ_LEN(L"G")); + surface()->DrawSetTextColor(COLOR_NEOTITLE); surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), iTitleMarginTop + m_iTitleHeight); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); + surface()->DrawSetTextColor(COLOR_RED); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16), iTitleMarginTop + m_iTitleHeight); + surface()->DrawPrintText(L"G", SZWSZ_LEN(L"G")); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); #if (0) From 39b04038df280b3a62cc1228899146bd873f56f0 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Fri, 14 Feb 2025 08:57:46 +0000 Subject: [PATCH 10/10] scale dropShadow with screen size --- mp/src/game/client/neo/ui/neo_root.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mp/src/game/client/neo/ui/neo_root.cpp b/mp/src/game/client/neo/ui/neo_root.cpp index ecc1e2120..524b02c62 100644 --- a/mp/src/game/client/neo/ui/neo_root.cpp +++ b/mp/src/game/client/neo/ui/neo_root.cpp @@ -586,24 +586,23 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) { // Draw title int iFirstWidth, iFirstHeight; + int iDropShadowOffset = MIN(8, param.wide * 0.005); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl); surface()->GetTextSize(g_uiCtx.fonts[NeoUI::FONT_LOGO].hdl, WSZ_GAME_TITLE1_a, iFirstWidth, iFirstHeight); surface()->DrawSetTextColor(COLOR_BLACK); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) - 8, iTitleMarginTop + 8); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) - iDropShadowOffset, iTitleMarginTop + iDropShadowOffset); surface()->DrawPrintText(WSZ_GAME_TITLE1, SZWSZ_LEN(WSZ_GAME_TITLE1)); surface()->DrawSetTextColor(COLOR_NEOTITLE); surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5), iTitleMarginTop); surface()->DrawPrintText(WSZ_GAME_TITLE1_a, SZWSZ_LEN(WSZ_GAME_TITLE1_a)); surface()->DrawSetTextColor(COLOR_RED); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + iFirstWidth, iTitleMarginTop); surface()->DrawPrintText(WSZ_GAME_TITLE1_b, SZWSZ_LEN(WSZ_GAME_TITLE1_b)); surface()->DrawSetTextColor(COLOR_BLACK); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - 8, iTitleMarginTop + m_iTitleHeight + 8); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - iDropShadowOffset, iTitleMarginTop + m_iTitleHeight + iDropShadowOffset); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_LOGOSMALL].hdl); surface()->DrawPrintText(WSZ_GAME_TITLE2, SZWSZ_LEN(WSZ_GAME_TITLE2)); - surface()->DrawSetTextColor(COLOR_BLACK); - surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - 8, iTitleMarginTop + m_iTitleHeight + 8); + surface()->DrawSetTextPos(iBtnPlaceXMid - (m_iTitleWidth * 0.5) + (iTitleNWidth * 1.16) - iDropShadowOffset, iTitleMarginTop + m_iTitleHeight + iDropShadowOffset); surface()->DrawPrintText(L"G", SZWSZ_LEN(L"G")); surface()->DrawSetTextColor(COLOR_NEOTITLE); @@ -615,7 +614,7 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) surface()->DrawPrintText(L"G", SZWSZ_LEN(L"G")); surface()->DrawSetTextFont(g_uiCtx.fonts[NeoUI::FONT_NTNORMAL].hdl); -#if (0) +#if (0) // NEO TODO (Adam) place the current player info in the top right corner maybe? surface()->DrawSetTextColor(COLOR_NEOPANELTEXTBRIGHT); ISteamUser *steamUser = steamapicontext->SteamUser(); ISteamFriends *steamFriends = steamapicontext->SteamFriends(); @@ -701,7 +700,7 @@ void CNeoRoot::MainLoopRoot(const MainLoopParam param) #endif (0) } -#if (0) +#if (0) // NEO TODO (Adam) some kind of drop down for the news section, better position the current server info etc. g_uiCtx.dPanel.x = iRightXPos; g_uiCtx.dPanel.y = iRightSideYStart; if (IsInGame())