ImGui: console and browser code style refactor

Made the style of the code more consistent. Not much logic-wise had changed during the refactor, but there are some.

Console:
* Removed m_bSuggestUpdate and the logic bound to it, this var was never set and the logic was never used. This was the initial workaround for resetting the autocomplete selection pos to kPark (-1), but this is currently done in a more mature way, but the old code was never removed
* CreateSuggestionsFromPartial() (previously, FindFromPartial()) would break if a ConCommand/ConVar was found that was already added in the list. Although this is an engine/sdk level bug, we shouldn't stop iterating there. Added an assert instead and made the loop continue.
* Removed member m_bCopyToClipBoard, this was used to check if the copy button was pressed, to copy the text the next frame. The copy now happens directly in the site of the Copy button which is a better approach.
* Due to the changes with removing m_bCopyToClipBoard, the mutex for m_colorTextLogger is now released right after rendering the color text to fully minimize blocking time between other threads.

Browser:
* Moved ImGui::Begin() call from RunFrame() to DrawSurface(), it fits better there and we can now also return false if the frame didn't render.
* Improved the "Broadcasting" text formatting when server browser is hosting and broadcasting without a server token (public server).

Both:
* Added virtual Shutdown() method.
This commit is contained in:
Kawe Mazidjatari 2024-03-01 13:39:06 +01:00
parent 5229125915
commit 7f36220448
5 changed files with 607 additions and 536 deletions

View File

@ -43,18 +43,18 @@ static ConCommand togglebrowser("togglebrowser", CBrowser::ToggleBrowser_f, "Sho
// Purpose: // Purpose:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
CBrowser::CBrowser(void) CBrowser::CBrowser(void)
: m_bReclaimFocusTokenField(false) : m_reclaimFocusOnTokenField(false)
, m_bQueryListNonRecursive(false) , m_queryNewListNonRecursive(false)
, m_bQueryGlobalBanList(true) , m_queryGlobalBanList(true)
, m_HostMessageColor(1.00f, 1.00f, 1.00f, 1.00f) , m_hostMessageColor(1.00f, 1.00f, 1.00f, 1.00f)
, m_ivHiddenServerMessageColor(0.00f, 1.00f, 0.00f, 1.00f) , m_hiddenServerMessageColor(0.00f, 1.00f, 0.00f, 1.00f)
{ {
m_surfaceLabel = "Server Browser"; m_surfaceLabel = "Server Browser";
memset(m_szServerAddressBuffer, '\0', sizeof(m_szServerAddressBuffer)); memset(m_serverAddressTextBuf, '\0', sizeof(m_serverAddressTextBuf));
memset(m_szServerEncKeyBuffer, '\0', sizeof(m_szServerEncKeyBuffer)); memset(m_serverNetKeyTextBuf, '\0', sizeof(m_serverNetKeyTextBuf));
m_rLockedIconBlob = GetModuleResource(IDB_PNG2); m_lockedIconDataResource = GetModuleResource(IDB_PNG2);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -62,10 +62,7 @@ CBrowser::CBrowser(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
CBrowser::~CBrowser(void) CBrowser::~CBrowser(void)
{ {
if (m_idLockedIcon) Shutdown();
{
m_idLockedIcon->Release();
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -75,13 +72,24 @@ bool CBrowser::Init(void)
{ {
SetStyleVar(928.f, 524.f, -500.f, 50.f); SetStyleVar(928.f, 524.f, -500.f, 50.f);
bool ret = LoadTextureBuffer(reinterpret_cast<unsigned char*>(m_rLockedIconBlob.m_pData), int(m_rLockedIconBlob.m_nSize), bool ret = LoadTextureBuffer(reinterpret_cast<unsigned char*>(m_lockedIconDataResource.m_pData), int(m_lockedIconDataResource.m_nSize),
&m_idLockedIcon, &m_rLockedIconBlob.m_nWidth, &m_rLockedIconBlob.m_nHeight); &m_lockedIconShaderResource, &m_lockedIconDataResource.m_nWidth, &m_lockedIconDataResource.m_nHeight);
IM_ASSERT(ret && m_idLockedIcon); IM_ASSERT(ret && m_lockedIconShaderResource);
return ret; return ret;
} }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBrowser::Shutdown(void)
{
if (m_lockedIconShaderResource)
{
m_lockedIconShaderResource->Release();
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: draws the main browser front-end // Purpose: draws the main browser front-end
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -102,36 +110,29 @@ void CBrowser::RunFrame(void)
Animate(); Animate();
RunTask(); RunTask();
int nVars = 0; int baseWindowStyleVars = 0;
float flWidth; ImVec2 minBaseWindowRect;
float flHeight;
if (m_surfaceStyle == ImGuiStyle_t::MODERN) if (m_surfaceStyle == ImGuiStyle_t::MODERN)
{ {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 8.f, 10.f }); nVars++; ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 8.f, 10.f }); baseWindowStyleVars++;
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); nVars++; ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); baseWindowStyleVars++;
flWidth = 621.f; minBaseWindowRect = ImVec2(621.f, 532.f);
flHeight = 532.f;
} }
else else
{ {
if (m_surfaceStyle == ImGuiStyle_t::LEGACY) minBaseWindowRect = m_surfaceStyle == ImGuiStyle_t::LEGACY
{ ? ImVec2(619.f, 526.f)
flWidth = 619.f; : ImVec2(618.f, 524.f);
flHeight = 526.f;
}
else
{
flWidth = 618.f;
flHeight = 524.f;
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 6.f, 6.f }); nVars++; ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 6.f, 6.f }); baseWindowStyleVars++;
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); nVars++; ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_fadeAlpha); baseWindowStyleVars++;
ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 1.0f); nVars++; ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 1.0f); baseWindowStyleVars++;
} }
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(flWidth, flHeight)); nVars++;
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, minBaseWindowRect); baseWindowStyleVars++;
if (m_activated && m_reclaimFocus) // Reclaim focus on window apparition. if (m_activated && m_reclaimFocus) // Reclaim focus on window apparition.
{ {
@ -139,17 +140,8 @@ void CBrowser::RunFrame(void)
m_reclaimFocus = false; m_reclaimFocus = false;
} }
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_NoScrollbar, &ResetInput))
{
ImGui::End();
ImGui::PopStyleVar(nVars);
return;
}
DrawSurface(); DrawSurface();
ImGui::PopStyleVar(baseWindowStyleVars);
ImGui::End();
ImGui::PopStyleVar(nVars);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -174,38 +166,47 @@ void CBrowser::RunTask()
if (m_activated) if (m_activated)
{ {
if (m_bQueryListNonRecursive) if (m_queryNewListNonRecursive)
{ {
m_bQueryListNonRecursive = false; m_queryNewListNonRecursive = false;
RefreshServerList(); RefreshServerList();
} }
} }
else // Refresh server list the next time 'm_activated' evaluates to true. else // Refresh server list the next time 'm_activated' evaluates to true.
{ {
m_bReclaimFocusTokenField = true; m_reclaimFocusOnTokenField = true;
m_bQueryListNonRecursive = true; m_queryNewListNonRecursive = true;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: draws the compmenu // Purpose: draws the server browser's main surface
// Output : true if a frame has been drawn, false otherwise
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool CBrowser::DrawSurface(void) bool CBrowser::DrawSurface(void)
{ {
if (!ImGui::Begin(m_surfaceLabel, &m_activated, ImGuiWindowFlags_NoScrollbar, &ResetInput))
{
ImGui::End();
return false;
}
ImGui::BeginTabBar("CompMenu"); ImGui::BeginTabBar("CompMenu");
if (ImGui::BeginTabItem("Browsing")) if (ImGui::BeginTabItem("Browsing"))
{ {
BrowserPanel(); DrawBrowserPanel();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
if (ImGui::BeginTabItem("Hosting")) if (ImGui::BeginTabItem("Hosting"))
{ {
HostPanel(); DrawHostPanel();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
ImGui::EndTabBar(); ImGui::EndTabBar();
ImGui::End();
return true; return true;
} }
@ -213,38 +214,38 @@ bool CBrowser::DrawSurface(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: draws the server browser section // Purpose: draws the server browser section
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CBrowser::BrowserPanel(void) void CBrowser::DrawBrowserPanel(void)
{ {
ImGui::BeginGroup(); ImGui::BeginGroup();
m_imServerBrowserFilter.Draw(); m_serverBrowserTextFilter.Draw();
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Refresh")) if (ImGui::Button("Refresh"))
{ {
m_svServerListMessage.clear(); m_serverListMessage.clear();
RefreshServerList(); RefreshServerList();
} }
ImGui::EndGroup(); ImGui::EndGroup();
ImGui::TextColored(ImVec4(1.00f, 0.00f, 0.00f, 1.00f), "%s", m_svServerListMessage.c_str()); ImGui::TextColored(ImVec4(1.00f, 0.00f, 0.00f, 1.00f), "%s", m_serverListMessage.c_str());
ImGui::Separator(); ImGui::Separator();
int iVars = 0; // Eliminate borders around server list table. int windowStyleVars = 0; // Eliminate borders around server list table.
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 1.f, 0.f }); iVars++; ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 1.f, 0.f }); windowStyleVars++;
const float fFooterHeight = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); const float fFooterHeight = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
ImGui::BeginChild("##ServerBrowser_ServerList", { 0, -fFooterHeight }, true, ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::BeginChild("##ServerBrowser_ServerList", { 0, -fFooterHeight }, true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
if (ImGui::BeginTable("##ServerBrowser_ServerListTable", 6, ImGuiTableFlags_Resizable)) if (ImGui::BeginTable("##ServerBrowser_ServerListTable", 6, ImGuiTableFlags_Resizable))
{ {
int nVars = 0; int frameStyleVars = 0;
if (m_surfaceStyle == ImGuiStyle_t::MODERN) if (m_surfaceStyle == ImGuiStyle_t::MODERN)
{ {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 8.f, 0.f }); nVars++; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 8.f, 0.f }); frameStyleVars++;
} }
else else
{ {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 4.f, 0.f }); nVars++; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 4.f, 0.f }); frameStyleVars++;
} }
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 25); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 25);
@ -265,9 +266,9 @@ void CBrowser::BrowserPanel(void)
char pszHostPort[32]; char pszHostPort[32];
sprintf(pszHostPort, "%d", server.port); sprintf(pszHostPort, "%d", server.port);
if (m_imServerBrowserFilter.PassFilter(pszHostName) if (m_serverBrowserTextFilter.PassFilter(pszHostName)
|| m_imServerBrowserFilter.PassFilter(pszHostMap) || m_serverBrowserTextFilter.PassFilter(pszHostMap)
|| m_imServerBrowserFilter.PassFilter(pszHostPort)) || m_serverBrowserTextFilter.PassFilter(pszHostPort))
{ {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("%s", pszHostName); ImGui::Text("%s", pszHostName);
@ -297,11 +298,11 @@ void CBrowser::BrowserPanel(void)
g_ServerListManager.m_Mutex.unlock(); g_ServerListManager.m_Mutex.unlock();
ImGui::EndTable(); ImGui::EndTable();
ImGui::PopStyleVar(nVars); ImGui::PopStyleVar(frameStyleVars);
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::PopStyleVar(iVars); ImGui::PopStyleVar(windowStyleVars);
ImGui::Separator(); ImGui::Separator();
@ -315,17 +316,17 @@ void CBrowser::BrowserPanel(void)
ImGui::PushItemWidth(itemWidth); ImGui::PushItemWidth(itemWidth);
{ {
ImGui::InputTextWithHint("##ServerBrowser_ServerCon", "Server address and port", m_szServerAddressBuffer, IM_ARRAYSIZE(m_szServerAddressBuffer)); ImGui::InputTextWithHint("##ServerBrowser_ServerCon", "Server address and port", m_serverAddressTextBuf, IM_ARRAYSIZE(m_serverAddressTextBuf));
ImGui::SameLine(); ImGui::SameLine();
ImGui::InputTextWithHint("##ServerBrowser_ServerKey", "Encryption key", m_szServerEncKeyBuffer, IM_ARRAYSIZE(m_szServerEncKeyBuffer)); ImGui::InputTextWithHint("##ServerBrowser_ServerKey", "Encryption key", m_serverNetKeyTextBuf, IM_ARRAYSIZE(m_serverNetKeyTextBuf));
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Connect", ImVec2(itemWidth, ImGui::GetFrameHeight()))) if (ImGui::Button("Connect", ImVec2(itemWidth, ImGui::GetFrameHeight())))
{ {
if (m_szServerAddressBuffer[0]) if (m_serverAddressTextBuf[0])
{ {
g_ServerListManager.ConnectToServer(m_szServerAddressBuffer, m_szServerEncKeyBuffer); g_ServerListManager.ConnectToServer(m_serverAddressTextBuf, m_serverNetKeyTextBuf);
} }
} }
@ -351,15 +352,16 @@ void CBrowser::RefreshServerList(void)
// Thread the request, and let the main thread assign status message back // Thread the request, and let the main thread assign status message back
std::thread request([&] std::thread request([&]
{ {
std::string svServerListMessage; std::string serverListMessage;
g_ServerListManager.RefreshServerList(svServerListMessage); g_ServerListManager.RefreshServerList(serverListMessage);
g_TaskQueue.Dispatch([&, svServerListMessage] g_TaskQueue.Dispatch([&, serverListMessage]
{ {
SetServerListMessage(svServerListMessage.c_str()); SetServerListMessage(serverListMessage.c_str());
}, 0); }, 0);
} }
); );
request.detach(); request.detach();
} }
@ -368,32 +370,31 @@ void CBrowser::RefreshServerList(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CBrowser::HiddenServersModal(void) void CBrowser::HiddenServersModal(void)
{ {
float flHeight; // Set the padding accordingly for each theme. float modalWindowHeight; // Set the padding accordingly for each theme.
switch (m_surfaceStyle) switch (m_surfaceStyle)
{ {
case ImGuiStyle_t::LEGACY: case ImGuiStyle_t::LEGACY:
flHeight = 207.f; modalWindowHeight = 207.f;
break; break;
case ImGuiStyle_t::MODERN: case ImGuiStyle_t::MODERN:
flHeight = 214.f; modalWindowHeight = 214.f;
break; break;
default: default:
flHeight = 206.f; modalWindowHeight = 206.f;
break; break;
} }
int nVars = 0; int modalStyleVars = 0;
bool bModalOpen = true; ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(408.f, modalWindowHeight)); modalStyleVars++;
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(408.f, flHeight)); nVars++; bool isModalStillOpen = true;
if (ImGui::BeginPopupModal("Private Server", &isModalStillOpen, ImGuiWindowFlags_NoResize))
if (ImGui::BeginPopupModal("Private Server", &bModalOpen, ImGuiWindowFlags_NoResize))
{ {
ImGui::SetWindowSize(ImVec2(408.f, flHeight), ImGuiCond_Always); ImGui::SetWindowSize(ImVec2(408.f, modalWindowHeight), ImGuiCond_Always);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.00f, 0.00f, 0.00f, 0.00f)); // Override the style color for child bg. ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.00f, 0.00f, 0.00f, 0.00f)); // Override the style color for child bg.
ImGui::BeginChild("##HiddenServersConnectModal_IconParent", ImVec2(float(m_rLockedIconBlob.m_nWidth), float(m_rLockedIconBlob.m_nHeight))); ImGui::BeginChild("##HiddenServersConnectModal_IconParent", ImVec2(float(m_lockedIconDataResource.m_nWidth), float(m_lockedIconDataResource.m_nHeight)));
ImGui::Image(m_idLockedIcon, ImVec2(float(m_rLockedIconBlob.m_nWidth), float(m_rLockedIconBlob.m_nHeight))); // Display texture. ImGui::Image(m_lockedIconShaderResource, ImVec2(float(m_lockedIconDataResource.m_nWidth), float(m_lockedIconDataResource.m_nHeight))); // Display texture.
ImGui::EndChild(); ImGui::EndChild();
ImGui::PopStyleColor(); // Pop the override for the child bg. ImGui::PopStyleColor(); // Pop the override for the child bg.
@ -409,82 +410,82 @@ void CBrowser::HiddenServersModal(void)
ImGui::PopItemWidth(); ImGui::PopItemWidth();
if (m_bReclaimFocusTokenField) if (m_reclaimFocusOnTokenField)
{ {
ImGui::SetKeyboardFocusHere(-1); // -1 means previous widget. ImGui::SetKeyboardFocusHere(-1); // -1 means previous widget.
m_bReclaimFocusTokenField = false; m_reclaimFocusOnTokenField = false;
} }
ImGui::Dummy(ImVec2(contentRegionMax.x, 19.f)); // Place a dummy, basically making space inserting a blank element. ImGui::Dummy(ImVec2(contentRegionMax.x, 19.f)); // Place a dummy, basically making space inserting a blank element.
ImGui::TextColored(m_ivHiddenServerMessageColor, "%s", m_svHiddenServerRequestMessage.c_str()); ImGui::TextColored(m_hiddenServerMessageColor, "%s", m_hiddenServerRequestMessage.c_str());
ImGui::Separator(); ImGui::Separator();
if (ImGui::Button("Connect", ImVec2(contentRegionMax.x, 24))) if (ImGui::Button("Connect", ImVec2(contentRegionMax.x, 24)))
{ {
m_svHiddenServerRequestMessage.clear(); m_hiddenServerRequestMessage.clear();
m_bReclaimFocusTokenField = true; m_reclaimFocusOnTokenField = true;
if (!hiddenServerToken.empty()) if (!hiddenServerToken.empty())
{ {
NetGameServer_t server; NetGameServer_t server;
bool result = g_MasterServer.GetServerByToken(server, m_svHiddenServerRequestMessage, hiddenServerToken); // Send token connect request. const bool result = g_MasterServer.GetServerByToken(server, m_hiddenServerRequestMessage, hiddenServerToken); // Send token connect request.
if (result && !server.name.empty()) if (result && !server.name.empty())
{ {
g_ServerListManager.ConnectToServer(server.address, server.port, server.netKey); // Connect to the server g_ServerListManager.ConnectToServer(server.address, server.port, server.netKey); // Connect to the server
m_svHiddenServerRequestMessage = Format("Found server: %s", server.name.c_str()); m_hiddenServerRequestMessage = Format("Found server: %s", server.name.c_str());
m_ivHiddenServerMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f); m_hiddenServerMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
else else
{ {
if (m_svHiddenServerRequestMessage.empty()) if (m_hiddenServerRequestMessage.empty())
{ {
m_svHiddenServerRequestMessage = "Unknown error."; m_hiddenServerRequestMessage = "Unknown error.";
} }
else // Display error message. else // Display error message.
{ {
m_svHiddenServerRequestMessage = Format("Error: %s", m_svHiddenServerRequestMessage.c_str()); m_hiddenServerRequestMessage = Format("Error: %s", m_hiddenServerRequestMessage.c_str());
} }
m_ivHiddenServerMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); m_hiddenServerMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
} }
} }
else else
{ {
m_svHiddenServerRequestMessage = "Token is required."; m_hiddenServerRequestMessage = "Token is required.";
m_ivHiddenServerMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); m_hiddenServerMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
} }
} }
if (ImGui::Button("Close", ImVec2(contentRegionMax.x, 24))) if (ImGui::Button("Close", ImVec2(contentRegionMax.x, 24)))
{ {
m_svHiddenServerRequestMessage.clear(); m_hiddenServerRequestMessage.clear();
m_bReclaimFocusTokenField = true; m_reclaimFocusOnTokenField = true;
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
ImGui::EndPopup(); ImGui::EndPopup();
ImGui::PopStyleVar(nVars); ImGui::PopStyleVar(modalStyleVars);
} }
else if (!bModalOpen) else if (!isModalStillOpen)
{ {
m_svHiddenServerRequestMessage.clear(); m_hiddenServerRequestMessage.clear();
m_bReclaimFocusTokenField = true; m_reclaimFocusOnTokenField = true;
ImGui::PopStyleVar(nVars); ImGui::PopStyleVar(modalStyleVars);
} }
else else
{ {
ImGui::PopStyleVar(nVars); ImGui::PopStyleVar(modalStyleVars);
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: draws the host section // Purpose: draws the host section
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CBrowser::HostPanel(void) void CBrowser::DrawHostPanel(void)
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex); std::lock_guard<std::mutex> l(g_ServerListManager.m_Mutex);
@ -527,10 +528,10 @@ void CBrowser::HostPanel(void)
ImGui::EndCombo(); ImGui::EndCombo();
} }
m_bQueryGlobalBanList = sv_globalBanlist.GetBool(); // Sync toggle with 'sv_globalBanlist'. m_queryGlobalBanList = sv_globalBanlist.GetBool(); // Sync toggle with 'sv_globalBanlist'.
if (ImGui::Checkbox("Load global banned list", &m_bQueryGlobalBanList)) if (ImGui::Checkbox("Load global banned list", &m_queryGlobalBanList))
{ {
sv_globalBanlist.SetValue(m_bQueryGlobalBanList); sv_globalBanlist.SetValue(m_queryGlobalBanList);
} }
ImGui::Text("Server visibility"); ImGui::Text("Server visibility");
@ -548,47 +549,51 @@ void CBrowser::HostPanel(void)
g_ServerListManager.m_ServerVisibility = EServerVisibility_t::PUBLIC; g_ServerListManager.m_ServerVisibility = EServerVisibility_t::PUBLIC;
} }
ImGui::TextColored(m_HostMessageColor, "%s", m_svHostMessage.c_str()); ImGui::TextColored(m_hostMessageColor, "%s", m_hostMessage.c_str());
if (!m_svHostToken.empty()) if (!m_hostToken.empty())
{ {
ImGui::InputText("##ServerHost_HostToken", &m_svHostToken, ImGuiInputTextFlags_ReadOnly); ImGui::InputText("##ServerHost_HostToken", &m_hostToken, ImGuiInputTextFlags_ReadOnly);
} }
ImGui::Spacing(); ImGui::Spacing();
const ImVec2 contentRegionMax = ImGui::GetContentRegionAvail(); const ImVec2 contentRegionMax = ImGui::GetContentRegionAvail();
const bool bServerActive = g_pServer->IsActive(); const bool serverActive = g_pServer->IsActive();
if (!g_pHostState->m_bActiveGame) if (!g_pHostState->m_bActiveGame)
{ {
if (ImGui::Button("Start server", ImVec2(contentRegionMax.x, 32))) if (ImGui::Button("Start server", ImVec2(contentRegionMax.x, 32)))
{ {
m_svHostMessage.clear(); m_hostMessage.clear();
bool bEnforceField = g_ServerListManager.m_ServerVisibility == EServerVisibility_t::OFFLINE ? true : !g_ServerListManager.m_Server.name.empty(); const bool enforceField = g_ServerListManager.m_ServerVisibility == EServerVisibility_t::OFFLINE
if (bEnforceField && !g_ServerListManager.m_Server.playlist.empty() && !g_ServerListManager.m_Server.map.empty()) ? true
: !g_ServerListManager.m_Server.name.empty();
if (enforceField && !g_ServerListManager.m_Server.playlist.empty() && !g_ServerListManager.m_Server.map.empty())
{ {
g_ServerListManager.LaunchServer(bServerActive); // Launch server. g_ServerListManager.LaunchServer(serverActive); // Launch server.
} }
else else
{ {
if (g_ServerListManager.m_Server.name.empty()) if (g_ServerListManager.m_Server.name.empty())
{ {
m_svHostMessage = "Server name is required."; m_hostMessage = "Server name is required.";
m_HostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
} }
else if (g_ServerListManager.m_Server.playlist.empty()) else if (g_ServerListManager.m_Server.playlist.empty())
{ {
m_svHostMessage = "Playlist is required."; m_hostMessage = "Playlist is required.";
m_HostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
} }
else if (g_ServerListManager.m_Server.map.empty()) else if (g_ServerListManager.m_Server.map.empty())
{ {
m_svHostMessage = "Level name is required."; m_hostMessage = "Level name is required.";
m_HostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
} }
} }
} }
if (ImGui::Button("Reload playlist", ImVec2(contentRegionMax.x, 32))) if (ImGui::Button("Reload playlist", ImVec2(contentRegionMax.x, 32)))
{ {
v_Playlists_Download_f(); v_Playlists_Download_f();
@ -612,16 +617,16 @@ void CBrowser::HostPanel(void)
{ {
if (!g_ServerListManager.m_Server.map.empty()) if (!g_ServerListManager.m_Server.map.empty())
{ {
g_ServerListManager.LaunchServer(bServerActive); g_ServerListManager.LaunchServer(serverActive);
} }
else else
{ {
m_svHostMessage = "Failed to change level: 'levelname' was empty."; m_hostMessage = "Failed to change level: 'levelname' was empty.";
m_HostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
} }
} }
if (bServerActive) if (serverActive)
{ {
ImGui::Spacing(); ImGui::Spacing();
ImGui::Separator(); ImGui::Separator();
@ -677,16 +682,16 @@ void CBrowser::UpdateHostingStatus(void)
{ {
case EHostStatus_t::NOT_HOSTING: case EHostStatus_t::NOT_HOSTING:
{ {
if (!m_svHostToken.empty()) if (!m_hostToken.empty())
{ {
m_svHostToken.clear(); m_hostToken.clear();
} }
if (ImGui::ColorConvertFloat4ToU32(m_HostMessageColor) == // Only clear if this is green (a valid hosting message). if (ImGui::ColorConvertFloat4ToU32(m_hostMessageColor) == // Only clear if this is green (a valid hosting message).
ImGui::ColorConvertFloat4ToU32(ImVec4(0.00f, 1.00f, 0.00f, 1.00f))) ImGui::ColorConvertFloat4ToU32(ImVec4(0.00f, 1.00f, 0.00f, 1.00f)))
{ {
m_svHostMessage.clear(); m_hostMessage.clear();
m_HostMessageColor = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); m_hostMessageColor = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
} }
break; break;
@ -780,8 +785,8 @@ void CBrowser::SendHostingPostRequest(const NetGameServer_t& gameServer)
void CBrowser::InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp) void CBrowser::InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp)
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
m_svHostMessage = hostMessage; m_hostMessage = hostMessage;
m_svHostToken = hostToken; m_hostToken = hostToken;
if (!hostIp.empty()) if (!hostIp.empty())
{ {
@ -790,18 +795,19 @@ void CBrowser::InstallHostingDetails(const bool postFailed, const char* const ho
if (postFailed) if (postFailed)
{ {
m_HostMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f); m_hostMessageColor = ImVec4(0.00f, 1.00f, 0.00f, 1.00f);
stringstream ssMessage; stringstream ssMessage;
ssMessage << "Broadcasting: "; ssMessage << "Broadcasting";
if (!m_svHostToken.empty()) if (!m_hostToken.empty())
{ {
ssMessage << "share the following token for clients to connect: "; ssMessage << ": share the following token for clients to connect: ";
} }
m_svHostMessage = ssMessage.str();
m_hostMessage = ssMessage.str();
} }
else else
{ {
m_HostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); m_hostMessageColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f);
} }
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
} }

View File

@ -15,17 +15,18 @@ public:
virtual ~CBrowser(void); virtual ~CBrowser(void);
virtual bool Init(void); virtual bool Init(void);
virtual void Shutdown(void);
virtual void RunFrame(void); virtual void RunFrame(void);
void RunTask(void); void RunTask(void);
virtual bool DrawSurface(void); virtual bool DrawSurface(void);
void BrowserPanel(void); void DrawBrowserPanel(void);
void RefreshServerList(void); void RefreshServerList(void);
void HiddenServersModal(void); void HiddenServersModal(void);
void HostPanel(void); void DrawHostPanel(void);
void UpdateHostingStatus(void); void UpdateHostingStatus(void);
void InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp); void InstallHostingDetails(const bool postFailed, const char* const hostMessage, const char* const hostToken, const string& hostIp);
@ -38,38 +39,38 @@ public:
static void ToggleBrowser_f(); static void ToggleBrowser_f();
private: private:
inline void SetServerListMessage(const char* const message) { m_svServerListMessage = message; }; inline void SetServerListMessage(const char* const message) { m_serverListMessage = message; };
inline void SetHostMessage(const char* const message) { m_svHostMessage = message; } inline void SetHostMessage(const char* const message) { m_hostMessage = message; }
inline void SetHostToken(const char* const message) { m_svHostToken = message; } inline void SetHostToken(const char* const message) { m_hostToken = message; }
private: private:
bool m_bReclaimFocusTokenField; bool m_reclaimFocusOnTokenField;
bool m_bQueryListNonRecursive; // When set, refreshes the server list once the next frame. bool m_queryNewListNonRecursive; // When set, refreshes the server list once the next frame.
bool m_bQueryGlobalBanList; bool m_queryGlobalBanList;
char m_szServerAddressBuffer[128]; char m_serverAddressTextBuf[128];
char m_szServerEncKeyBuffer[30]; char m_serverNetKeyTextBuf[30];
ID3D11ShaderResourceView* m_idLockedIcon; ID3D11ShaderResourceView* m_lockedIconShaderResource;
MODULERESOURCE m_rLockedIconBlob; MODULERESOURCE m_lockedIconDataResource;
//////////////////// ////////////////////
// Server List // // Server List //
//////////////////// ////////////////////
ImGuiTextFilter m_imServerBrowserFilter; ImGuiTextFilter m_serverBrowserTextFilter;
string m_svServerListMessage; string m_serverListMessage;
//////////////////// ////////////////////
// Host Server // // Host Server //
//////////////////// ////////////////////
string m_svHostMessage; string m_hostMessage;
string m_svHostToken; string m_hostToken;
ImVec4 m_HostMessageColor; ImVec4 m_hostMessageColor;
//////////////////// ////////////////////
// Private Server // // Private Server //
//////////////////// ////////////////////
string m_svHiddenServerRequestMessage; string m_hiddenServerRequestMessage;
ImVec4 m_ivHiddenServerMessageColor; ImVec4 m_hiddenServerMessageColor;
}; };
extern CBrowser g_Browser; extern CBrowser g_Browser;

File diff suppressed because it is too large Load Diff

View File

@ -15,28 +15,29 @@ public:
virtual ~CConsole(void); virtual ~CConsole(void);
virtual bool Init(void); virtual bool Init(void);
virtual void Shutdown(void);
virtual void RunFrame(void); virtual void RunFrame(void);
virtual bool DrawSurface(void); virtual bool DrawSurface(void);
private: private:
void OptionsPanel(void); void DrawOptionsPanel(void);
void SuggestPanel(void); void DrawAutoCompletePanel(void);
bool AutoComplete(void); bool RunAutoComplete(void);
void ResetAutoComplete(void); void ResetAutoCompleteData(void);
void FindFromPartial(void); void CreateSuggestionsFromPartial(void);
void ProcessCommand(string svCommand); void ProcessCommand(const char* const inputText);
void BuildSummary(string svConVar = ""); void BuildSummaryText(const char* const inputText);
struct CSuggest; struct ConAutoCompleteSuggest_s;
void BuildInputFromSelected(const CSuggest& suggest, string& svInput); void DetermineInputTextFromSelectedSuggestion(const ConAutoCompleteSuggest_s& suggest, string& svInput);
void BuildSuggestPanelRect(void); void DetermineAutoCompleteWindowRect(void);
bool LoadFlagIcons(void); bool LoadFlagIcons(void);
int GetFlagTextureIndex(int nFlags) const; int GetFlagTextureIndex(const int flags) const;
int TextEditCallback(ImGuiInputTextCallbackData* pData); int TextEditCallback(ImGuiInputTextCallbackData* pData);
static int TextEditCallbackStub(ImGuiInputTextCallbackData* pData); static int TextEditCallbackStub(ImGuiInputTextCallbackData* pData);
@ -66,70 +67,106 @@ private: // Internals.
void ClampHistorySize(void); void ClampHistorySize(void);
private: private:
enum PositionMode_t enum ConAutoCompletePos_e
{ {
// Park means the position is out of screen. // Park means the position is out of screen.
kPark = -1, kPark = -1,
kFirst,
}; };
struct CSuggest struct ConAutoCompleteSuggest_s
{ {
CSuggest(const string& svName, int nFlags) ConAutoCompleteSuggest_s(const string& inText, const int inFlags)
{ {
m_svName = svName; text = inText;
m_nFlags = nFlags; flags = inFlags;
} }
bool operator==(const string& a) const bool operator==(const string& a) const
{ {
return m_svName.compare(a) == 0; return text.compare(a) == 0;
} }
bool operator<(const CSuggest& a) const bool operator<(const ConAutoCompleteSuggest_s& a) const
{ {
return m_svName < a.m_svName; return text < a.text;
} }
string m_svName; string text;
int m_nFlags; int flags;
}; };
private: private:
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
const char* m_pszLoggingLabel; const char* m_loggerLabel;
char m_szInputBuf[512]; char m_inputTextBuf[512];
char m_szSummary[256]; char m_summaryTextBuf[256];
char m_szWindowLabel[128];
string m_svInputConVar; // The selected ConVar from the suggestions in the autocomplete window gets
ssize_t m_nHistoryPos; // copied into this buffer.
ssize_t m_nSuggestPos; string m_selectedSuggestionText;
int m_nScrollBack; int m_selectedSuggestionTextLen;
int m_nSelectBack;
int m_nInputTextLen;
float m_flScrollX;
float m_flScrollY;
bool m_bCopyToClipBoard; // The positions in the history buffer; when there is nothing in the input
bool m_bModifyInput; // text field, the arrow keys would instead iterate over the previously
// submitted commands and show the currently selected one right in the
// input text field.
int m_historyPos;
bool m_bCanAutoComplete; // The position in the autocomplete window; this dictates the current
bool m_bSuggestActive; // (highlighted) suggestion, and copies that one into m_selectedSuggestion
bool m_bSuggestMoved; // once selected.
bool m_bSuggestUpdate; int m_suggestPos;
vector<CSuggest> m_vSuggest; // Scroll and select back amount; if text lines are getting removed to
vector<MODULERESOURCE> m_vFlagIcons; // clamp the size to the maximum allowed, we need to scroll back (and
vector<string> m_vHistory; // if text has been selected, select back this amount) to prevent the
// view or selection from drifting.
int m_scrollBackAmount;
int m_selectBackAmount;
ImVec2 m_ivSuggestWindowPos; // Scroll position of the last drawn frame, after any scroll back has been
ImVec2 m_ivSuggestWindowSize; // applied, this is used as a base for scrolling back when entries are
// getting removed.
ImVec2 m_lastFrameScrollPos;
CTextLogger m_Logger; // Set when the input text has been modified, used to rebuild suggestions
mutable CThreadFastMutex m_Mutex; // shown in the autocomplete window.
bool m_inputTextBufModified;
ImGuiInputTextFlags m_nInputFlags; // Determines whether we can autocomplete and build a list of suggestions,
ImGuiWindowFlags m_nSuggestFlags; // e.g. when you type "map " (with a trailing white space ' '), and "map"
ImGuiWindowFlags m_nLoggingFlags; // happens to be a ConCommand with an autocomplete function, this gets set
// and the autocomplete function of that ConCommand will be called to
// create a list of suggestions to be shown in the autocomplete window.
// This member is always false when the input text is empty.
bool m_canAutoComplete;
// Whether the autocomplete window is active. If this is set, the arrow up
// and down keys will be used for the auto complete window instead of the
// history (previously submitted commands) scroller.
bool m_autoCompleteActive;
// If the position in the autocomplete window had moved, this var will be
// set. This is used to check if we need to adjust the scroll position in
// the autocomplete window to keep the current selection visible.
bool m_autoCompletePosMoved;
// The position and rect of the autocomplete window, the pos is set to that
// of the input text field + an offset to move it under the item.
ImVec2 m_autoCompleteWindowPos;
ImVec2 m_autoCompleteWindowRect;
vector<ConAutoCompleteSuggest_s> m_vecSuggest;
vector<MODULERESOURCE> m_vecFlagIcons;
vector<string> m_vecHistory;
// The color logger in which text gets added, note that the mutex lock
// should always be acquired when using this as this is accessed from
// multiple threads!
CTextLogger m_colorTextLogger;
mutable CThreadFastMutex m_colorTextLoggerMutex;
ImGuiInputTextFlags m_inputTextFieldFlags;
ImGuiWindowFlags m_autoCompleteWindowFlags;
ImGuiWindowFlags m_colorLoggerWindowFlags;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -10,7 +10,9 @@ class CImguiSurface
public: public:
CImguiSurface(); CImguiSurface();
virtual ~CImguiSurface() { }; virtual ~CImguiSurface() { };
virtual bool Init() = 0; virtual bool Init() = 0;
virtual void Shutdown() = 0;
virtual void Animate(); virtual void Animate();
virtual void RunFrame() = 0; virtual void RunFrame() = 0;