diff --git a/src/gameui/imgui_system.cpp b/src/gameui/imgui_system.cpp index e0ef5d2b..cbc480c6 100644 --- a/src/gameui/imgui_system.cpp +++ b/src/gameui/imgui_system.cpp @@ -8,9 +8,6 @@ #include "engine/sys_mainwind.h" #include "windows/id3dx.h" -#include "IBrowser.h" -#include "IConsole.h" - #include "imgui_system.h" //----------------------------------------------------------------------------- @@ -18,7 +15,8 @@ //----------------------------------------------------------------------------- CImguiSystem::CImguiSystem() { - m_systemInitState = ImguiSystemInitStage_e::IM_PENDING_INIT; + m_initialized = false; + m_hasNewFrame = false; } //----------------------------------------------------------------------------- @@ -28,7 +26,7 @@ CImguiSystem::CImguiSystem() bool CImguiSystem::Init() { Assert(ThreadInMainThread(), "CImguiSystem::Init() should only be called from the main thread!"); - Assert(m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT, "CImguiSystem::Init() called recursively?"); + Assert(!IsInitialized(), "CImguiSystem::Init() called recursively?"); /////////////////////////////////////////////////////////////////////////// IMGUI_CHECKVERSION(); @@ -55,12 +53,12 @@ bool CImguiSystem::Init() !ImGui_ImplDX11_Init(D3D11Device(), D3D11DeviceContext())) { Assert(0); - - m_systemInitState = ImguiSystemInitStage_e::IM_INIT_FAILURE; return false; } - m_systemInitState = ImguiSystemInitStage_e::IM_SYSTEM_INIT; + m_initialized = true; + m_hasNewFrame = false; + return true; } @@ -70,23 +68,62 @@ bool CImguiSystem::Init() void CImguiSystem::Shutdown() { Assert(ThreadInMainThread(), "CImguiSystem::Shutdown() should only be called from the main thread!"); - Assert(m_systemInitState != ImguiSystemInitStage_e::IM_PENDING_INIT, "CImguiSystem::Shutdown() called recursively?"); - - // Nothing to shutdown. - if (m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT) - return; + Assert(IsInitialized(), "CImguiSystem::Shutdown() called recursively?"); AUTO_LOCK(m_snapshotBufferMutex); AUTO_LOCK(m_inputEventQueueMutex); - m_systemInitState = ImguiSystemInitStage_e::IM_PENDING_INIT; - ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); - m_snapshotData.Clear(); + + m_initialized = false; + m_hasNewFrame = false; +} + +//----------------------------------------------------------------------------- +// Add an imgui surface. +//----------------------------------------------------------------------------- +void CImguiSystem::AddSurface(CImguiSurface* const surface) +{ + Assert(IsInitialized()); + m_surfaceList.AddToTail(surface); +} + +//----------------------------------------------------------------------------- +// Remove an imgui surface. +//----------------------------------------------------------------------------- +void CImguiSystem::RemoveSurface(CImguiSurface* const surface) +{ + Assert(!IsInitialized()); + m_surfaceList.FindAndRemove(surface); +} + +//----------------------------------------------------------------------------- +// Draws the ImGui panels and applies all queued input events. +//----------------------------------------------------------------------------- +void CImguiSystem::SampleFrame() +{ + Assert(ThreadInMainThread(), "CImguiSystem::SampleFrame() should only be called from the main thread!"); + Assert(IsInitialized()); + + AUTO_LOCK(m_inputEventQueueMutex); + + ImGui_ImplDX11_NewFrame(); + ImGui_ImplWin32_NewFrame(); + + ImGui::NewFrame(); + + FOR_EACH_VEC(m_surfaceList, i) + { + CImguiSurface* const surface = m_surfaceList[i]; + surface->RunFrame(); + } + + ImGui::EndFrame(); + ImGui::Render(); } //----------------------------------------------------------------------------- @@ -97,48 +134,19 @@ void CImguiSystem::Shutdown() void CImguiSystem::SwapBuffers() { Assert(ThreadInMainThread(), "CImguiSystem::SwapBuffers() should only be called from the main thread!"); + Assert(IsInitialized()); - if (m_systemInitState < ImguiSystemInitStage_e::IM_FRAME_SAMPLED) + ImDrawData* const drawData = ImGui::GetDrawData(); + Assert(drawData); + + // Nothing has been drawn, nothing to swap. + if (!drawData->CmdListsCount) return; AUTO_LOCK(m_snapshotBufferMutex); - ImDrawData* const drawData = ImGui::GetDrawData(); - - // Nothing has been drawn, nothing to swap - if (!drawData) - return; m_snapshotData.SnapUsingSwap(drawData, ImGui::GetTime()); - - if (m_systemInitState == ImguiSystemInitStage_e::IM_FRAME_SAMPLED) - m_systemInitState = ImguiSystemInitStage_e::IM_FRAME_SWAPPED; -} - -//----------------------------------------------------------------------------- -// Draws the ImGui panels and applies all queued input events. -//----------------------------------------------------------------------------- -void CImguiSystem::SampleFrame() -{ - Assert(ThreadInMainThread(), "CImguiSystem::SampleFrame() should only be called from the main thread!"); - - if (m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT) - return; - - AUTO_LOCK(m_inputEventQueueMutex); - - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - - ImGui::NewFrame(); - - g_Browser.RunFrame(); - g_Console.RunFrame(); - - ImGui::EndFrame(); - ImGui::Render(); - - if (m_systemInitState == ImguiSystemInitStage_e::IM_SYSTEM_INIT) - m_systemInitState = ImguiSystemInitStage_e::IM_FRAME_SAMPLED; + m_hasNewFrame = true; } //----------------------------------------------------------------------------- @@ -146,16 +154,14 @@ void CImguiSystem::SampleFrame() //----------------------------------------------------------------------------- void CImguiSystem::RenderFrame() { - if (m_systemInitState < ImguiSystemInitStage_e::IM_FRAME_SWAPPED) + Assert(IsInitialized()); + AUTO_LOCK(m_snapshotBufferMutex); + + if (!m_hasNewFrame) return; - { - AUTO_LOCK(m_snapshotBufferMutex); - ImGui_ImplDX11_RenderDrawData(&m_snapshotData.DrawData); - } - - if (m_systemInitState == ImguiSystemInitStage_e::IM_FRAME_SAMPLED) - m_systemInitState = ImguiSystemInitStage_e::IM_FRAME_RENDERED; + ImGui_ImplDX11_RenderDrawData(&m_snapshotData.DrawData); + m_hasNewFrame = false; } //----------------------------------------------------------------------------- @@ -163,7 +169,7 @@ void CImguiSystem::RenderFrame() //----------------------------------------------------------------------------- LRESULT CImguiSystem::MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (ImguiSystem()->m_systemInitState == ImguiSystemInitStage_e::IM_PENDING_INIT) + if (!ImguiSystem()->IsInitialized()) return NULL; AUTO_LOCK(ImguiSystem()->m_inputEventQueueMutex); diff --git a/src/gameui/imgui_system.h b/src/gameui/imgui_system.h index 657b3549..b99e484d 100644 --- a/src/gameui/imgui_system.h +++ b/src/gameui/imgui_system.h @@ -6,6 +6,7 @@ #ifndef IMGUI_SYSTEM_H #define IMGUI_SYSTEM_H #include "imgui/misc/imgui_snapshot.h" +#include "imgui_surface.h" class CImguiSystem { @@ -15,6 +16,9 @@ public: bool Init(); void Shutdown(); + void AddSurface(CImguiSurface* const surface); + void RemoveSurface(CImguiSurface* const surface); + void SwapBuffers(); void SampleFrame(); @@ -24,34 +28,11 @@ public: static LRESULT MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); // inlines: - inline bool IsInitialized() const - { - return m_systemInitState >= ImguiSystemInitStage_e::IM_SYSTEM_INIT; - }; + inline bool IsInitialized() const { return m_initialized; }; private: - enum class ImguiSystemInitStage_e - { - // When the system failed to initialize, the stage would be set to - // this. - IM_INIT_FAILURE = -1, - - IM_PENDING_INIT, - IM_SYSTEM_INIT, - - // State gets set to this when the first frame has been sampled. - IM_FRAME_SAMPLED, - - // State gets set to this then buffers have been swapped for the first - // time. - IM_FRAME_SWAPPED, - - // Rendered for the first time. - IM_FRAME_RENDERED - }; - - ImguiSystemInitStage_e m_systemInitState; ImDrawDataSnapshot m_snapshotData; + CUtlVector m_surfaceList; // Mutex used during swapping and rendering, we draw the windows in the // main thread, and render it in the render thread. The only place this @@ -63,6 +44,9 @@ private: // is ran in thread separate from the main thread, therefore it needs a // lock to control access as main calls SampleFrame(). mutable CThreadMutex m_inputEventQueueMutex; + + bool m_initialized; + bool m_hasNewFrame; }; CImguiSystem* ImguiSystem(); diff --git a/src/materialsystem/cmaterialsystem.cpp b/src/materialsystem/cmaterialsystem.cpp index d0402221..9df9b582 100644 --- a/src/materialsystem/cmaterialsystem.cpp +++ b/src/materialsystem/cmaterialsystem.cpp @@ -139,7 +139,10 @@ void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64 //--------------------------------------------------------------------------------- ssize_t SpinPresent(void) { - ImguiSystem()->RenderFrame(); + CImguiSystem* const imguiSystem = ImguiSystem(); + + if (imguiSystem->IsInitialized()) + imguiSystem->RenderFrame(); const ssize_t val = v_SpinPresent(); return val; @@ -147,8 +150,13 @@ ssize_t SpinPresent(void) void* CMaterialSystem::SwapBuffers(CMaterialSystem* pMatSys) { - ImguiSystem()->SampleFrame(); - ImguiSystem()->SwapBuffers(); + CImguiSystem* const imguiSystem = ImguiSystem(); + + if (imguiSystem->IsInitialized()) + { + imguiSystem->SampleFrame(); + imguiSystem->SwapBuffers(); + } return CMaterialSystem__SwapBuffers(pMatSys); } diff --git a/src/windows/id3dx.cpp b/src/windows/id3dx.cpp index 4e3d2e38..b19572bf 100644 --- a/src/windows/id3dx.cpp +++ b/src/windows/id3dx.cpp @@ -3,6 +3,7 @@ //------------------------------ #define STB_IMAGE_IMPLEMENTATION #include "tier0/threadtools.h" +#include "tier0/commandline.h" #include "tier1/cvar.h" #include "windows/id3dx.h" #include "windows/input.h" @@ -350,8 +351,16 @@ void DirectX_Init() Error(eDLL_T::COMMON, 0xBAD0C0DE, "Failed to detour process: error code = %08x\n", hr); } - if (!ImguiSystem()->Init()) - Error(eDLL_T::COMMON, 0, "ImguiSystem()->Init() failed!\n"); + if (!CommandLine()->CheckParm("-noimgui")) + { + if (ImguiSystem()->Init()) + { + ImguiSystem()->AddSurface(&g_Console); + ImguiSystem()->AddSurface(&g_Browser); + } + else + Error(eDLL_T::COMMON, 0, "ImguiSystem()->Init() failed!\n"); + } } void DirectX_Shutdown() @@ -371,7 +380,13 @@ void DirectX_Shutdown() // Commit the transaction DetourTransactionCommit(); - ImguiSystem()->Shutdown(); + if (ImguiSystem()->IsInitialized()) + { + ImguiSystem()->Shutdown(); + + ImguiSystem()->RemoveSurface(&g_Browser); + ImguiSystem()->RemoveSurface(&g_Console); + } } void VDXGI::GetAdr(void) const