From 16557fef843d51a8e54106dd6b01095d0db8086b Mon Sep 17 00:00:00 2001 From: WSSDude <41929176+WSSDude@users.noreply.github.com> Date: Sat, 1 Mar 2025 08:52:11 +0100 Subject: [PATCH] Fix ImGui spam of ShowCursor/HideCursor --- src/d3d12/D3D12.cpp | 25 +++-------------- src/d3d12/D3D12_Functions.cpp | 4 ++- src/d3d12/D3D12_Hooks.cpp | 14 ++-------- src/overlay/Overlay.cpp | 51 ++--------------------------------- src/overlay/Overlay.h | 9 ------- src/reverse/Addresses.h | 4 +-- 6 files changed, 13 insertions(+), 94 deletions(-) diff --git a/src/d3d12/D3D12.cpp b/src/d3d12/D3D12.cpp index 1e141e9d..c436e95e 100644 --- a/src/d3d12/D3D12.cpp +++ b/src/d3d12/D3D12.cpp @@ -9,28 +9,11 @@ void D3D12::SetTrapInputInImGui(const bool acEnabled) { - // Must have an out-condition to this otherwise infinite loop - static int constexpr maxCursorDepth = 8; - int showCursorTries = 0; - int showCursorState; - if (acEnabled) - do - { - showCursorState = ShowCursor(TRUE); - } while (showCursorState < 0 && showCursorTries++ < maxCursorDepth); - else - do - { - showCursorState = ShowCursor(FALSE); - } while (showCursorState >= 0 && showCursorTries++ < maxCursorDepth); - - // Turn off software cursor - if (showCursorTries < maxCursorDepth || acEnabled == false) - ImGui::GetIO().MouseDrawCursor = false; + static const RED4ext::CName cReason = "ImGui"; + static RED4ext::UniversalRelocFunc + forceCursor(CyberEngineTweaks::AddressHashes::InputSystemWin32Base_ForceCursor); - // Enable software cursor as fallback if necessary - else - ImGui::GetIO().MouseDrawCursor = acEnabled; + forceCursor(RED4ext::CGameEngine::Get()->unkD0, cReason, acEnabled); m_trapInputInImGui = acEnabled; } diff --git a/src/d3d12/D3D12_Functions.cpp b/src/d3d12/D3D12_Functions.cpp index 60b5d0fc..7f848046 100644 --- a/src/d3d12/D3D12_Functions.cpp +++ b/src/d3d12/D3D12_Functions.cpp @@ -81,7 +81,7 @@ bool D3D12::Initialize() D3D12_DESCRIPTOR_HEAP_DESC srvdesc = {}; srvdesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - srvdesc.NumDescriptors = buffersCounts; + srvdesc.NumDescriptors = 200; // Same number as is used in scripting/Texture srvdesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; if (FAILED(m_pd3d12Device->CreateDescriptorHeap(&srvdesc, IID_PPV_ARGS(&m_pd3dSrvDescHeap)))) { @@ -313,6 +313,8 @@ bool D3D12::InitializeImGui(size_t aBuffersCounts) ImGui::GetStyle() = m_styleReference; ImGui::GetStyle().ScaleAllSizes(scaleFromReference); + ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange; // Do not modify cursor from ImGui backend + if (!ImGui_ImplWin32_Init(m_window.GetWindow())) { Log::Error("D3D12::InitializeImGui() - ImGui_ImplWin32_Init call failed!"); diff --git a/src/d3d12/D3D12_Hooks.cpp b/src/d3d12/D3D12_Hooks.cpp index a90a3886..280d35e6 100644 --- a/src/d3d12/D3D12_Hooks.cpp +++ b/src/d3d12/D3D12_Hooks.cpp @@ -8,17 +8,6 @@ #include -void* ApplyHook(void** vtable, size_t index, void* target) -{ - DWORD oldProtect; - VirtualProtect(vtable + index, 8, PAGE_EXECUTE_READWRITE, &oldProtect); - const auto ret = vtable[index]; - vtable[index] = target; - VirtualProtect(vtable + index, 8, oldProtect, nullptr); - - return ret; -} - void* D3D12::CRenderNode_Present_InternalPresent(int32_t* apDeviceIndex, uint8_t aSomeSync, UINT aSyncInterval) { auto& d3d12 = CET::Get().GetD3D12(); @@ -80,10 +69,11 @@ ID3D12Device* D3D12::GetDevice() const std::tuple D3D12::CreateTextureDescriptor() { const UINT handle_increment = m_pd3d12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - static std::atomic descriptor_index = 1; + static std::atomic descriptor_index = 1; // 0 is used for ImGui font texture const auto index = descriptor_index++; + // We allocate 200 descriptors if (index >= 200) return {{}, {}}; diff --git a/src/overlay/Overlay.cpp b/src/overlay/Overlay.cpp index d2585a04..51a55121 100644 --- a/src/overlay/Overlay.cpp +++ b/src/overlay/Overlay.cpp @@ -18,7 +18,6 @@ void Overlay::PostInitialize() auto& d3d12 = CET::Get().GetD3D12(); d3d12.DelayedSetTrapInputInImGui(true); - ClipToCenter(RED4ext::CGameEngine::Get()->unkD0); } else { @@ -194,8 +193,6 @@ void Overlay::Update() auto& d3d12 = CET::Get().GetD3D12(); d3d12.DelayedSetTrapInputInImGui(m_enabled); - auto* pEngine = RED4ext::CGameEngine::Get(); - ClipToCenter(pEngine->unkD0); m_toggled = false; } } @@ -211,9 +208,9 @@ void Overlay::Update() ImGui::RenderNotifications(); //——————————————————————————————— WARNING ——————————————————————————————— - // Argument MUST match the amount of ImGui::PushStyleVar() calls + // Argument MUST match the amount of ImGui::PushStyleVar() calls ImGui::PopStyleVar(2); - // Argument MUST match the amount of ImGui::PushStyleColor() calls + // Argument MUST match the amount of ImGui::PushStyleColor() calls ImGui::PopStyleColor(1); if (!m_enabled) @@ -240,48 +237,6 @@ bool Overlay::IsInitialized() const noexcept return m_initialized; } -BOOL Overlay::ClipToCenter(RED4ext::CGameEngine::UnkD0* apThis) -{ - const auto wnd = static_cast(apThis->hWnd); - const HWND foreground = GetForegroundWindow(); - - if (wnd == foreground && apThis->unk174 && !apThis->unk164 && !CET::Get().GetOverlay().IsEnabled()) - { - RECT rect; - GetClientRect(wnd, &rect); - ClientToScreen(wnd, reinterpret_cast(&rect.left)); - ClientToScreen(wnd, reinterpret_cast(&rect.right)); - rect.left = (rect.left + rect.right) / 2; - rect.right = rect.left; - rect.bottom = (rect.bottom + rect.top) / 2; - rect.top = rect.bottom; - apThis->isClipped = true; - ShowCursor(FALSE); - return ClipCursor(&rect); - } - - if (apThis->isClipped) - { - apThis->isClipped = false; - return ClipCursor(nullptr); - } - - return 1; -} - -void Overlay::Hook() -{ - const RED4ext::UniversalRelocPtr func(CyberEngineTweaks::AddressHashes::CWinapi_ClipToCenter); - - if (auto* pLocation = func.GetAddr()) - { - if (MH_CreateHook(pLocation, reinterpret_cast(&ClipToCenter), reinterpret_cast(&m_realClipToCenter)) != MH_OK || MH_EnableHook(pLocation) != MH_OK) - Log::Error("Could not hook mouse clip function!"); - else - Log::Info("Hook mouse clip function!"); - } -} - Overlay::Overlay(VKBindings& aBindings, Options& aOptions, PersistentState& aPersistentState, LuaVM& aVm) : m_console(aOptions, aPersistentState, aVm) , m_bindings(aBindings, aVm) @@ -291,8 +246,6 @@ Overlay::Overlay(VKBindings& aBindings, Options& aOptions, PersistentState& aPer , m_persistentState(aPersistentState) , m_vm(aVm) { - Hook(); - GameMainThread::Get().AddBaseInitializationTask( [this] { diff --git a/src/overlay/Overlay.h b/src/overlay/Overlay.h index 2bc9e7fb..ad7c9b73 100644 --- a/src/overlay/Overlay.h +++ b/src/overlay/Overlay.h @@ -7,8 +7,6 @@ #include "widgets/GameLog.h" #include "widgets/ImGuiDebug.h" -using TClipToCenter = HWND(RED4ext::CGameEngine::UnkD0*); - struct Overlay { Overlay(VKBindings& aBindings, Options& aOptions, PersistentState& aPersistentState, LuaVM& aVm); @@ -27,11 +25,6 @@ struct Overlay void Update(); -protected: - void Hook(); - - static BOOL ClipToCenter(RED4ext::CGameEngine::UnkD0* apThis); - private: void DrawToolbar(); @@ -42,8 +35,6 @@ struct Overlay GameLog m_gameLog; ImGuiDebug m_imguiDebug; - TClipToCenter* m_realClipToCenter{nullptr}; - std::atomic_bool m_enabled{false}; std::atomic_bool m_toggled{false}; bool m_initialized{false}; diff --git a/src/reverse/Addresses.h b/src/reverse/Addresses.h index b29adb0d..3130b8ba 100644 --- a/src/reverse/Addresses.h +++ b/src/reverse/Addresses.h @@ -59,8 +59,8 @@ constexpr uint32_t CScript_TweakDBLoad = 3602585178UL; // game::data:: constexpr uint32_t CShutdownState_OnTick = 4069332669UL; // red::GameAppShutdownState::OnTick #pragma endregion -#pragma region CWinapi -constexpr uint32_t CWinapi_ClipToCenter = 261693736UL; // input::InputSystemWin32Base::Update +#pragma region InputSystemWin32Base +constexpr uint32_t InputSystemWin32Base_ForceCursor = 2130646213UL; // input::InputSystemWin32Base::ForceCursor #pragma endregion #pragma region gameIGameSystem