|
| 1 | +#include <Windows.h> |
| 2 | +#include <d3d11.h> |
| 3 | +#include <dxgi.h> |
| 4 | +#include <imgui.h> |
| 5 | +#include <imgui_impl_dx11.h> |
| 6 | +#include <imgui_impl_win32.h> |
| 7 | + |
| 8 | +#include "omath/hooks/hooks_manager.hpp" |
| 9 | + |
| 10 | +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM); |
| 11 | + |
| 12 | +namespace |
| 13 | +{ |
| 14 | + bool g_initialized = false; |
| 15 | + bool g_init_attempted = false; |
| 16 | + |
| 17 | + ID3D11Device* g_device = nullptr; |
| 18 | + ID3D11DeviceContext* g_context = nullptr; |
| 19 | + ID3D11RenderTargetView* g_render_target_view = nullptr; |
| 20 | + |
| 21 | + void create_render_target(IDXGISwapChain* swap_chain) |
| 22 | + { |
| 23 | + ID3D11Texture2D* back_buffer = nullptr; |
| 24 | + if (FAILED(swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer)))) |
| 25 | + return; |
| 26 | + g_device->CreateRenderTargetView(back_buffer, nullptr, &g_render_target_view); |
| 27 | + back_buffer->Release(); |
| 28 | + } |
| 29 | + |
| 30 | + void init(IDXGISwapChain* swap_chain) |
| 31 | + { |
| 32 | + g_init_attempted = true; |
| 33 | + |
| 34 | + if (FAILED(swap_chain->GetDevice(IID_PPV_ARGS(&g_device)))) |
| 35 | + return; |
| 36 | + |
| 37 | + g_device->GetImmediateContext(&g_context); |
| 38 | + |
| 39 | + DXGI_SWAP_CHAIN_DESC desc{}; |
| 40 | + swap_chain->GetDesc(&desc); |
| 41 | + |
| 42 | + create_render_target(swap_chain); |
| 43 | + |
| 44 | + ImGui::CreateContext(); |
| 45 | + ImGui::StyleColorsDark(); |
| 46 | + ImGui::GetIO().IniFilename = nullptr; |
| 47 | + ImGui::GetIO().LogFilename = nullptr; |
| 48 | + ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange; |
| 49 | + |
| 50 | + ImGui_ImplWin32_Init(desc.OutputWindow); |
| 51 | + ImGui_ImplDX11_Init(g_device, g_context); |
| 52 | + |
| 53 | + auto& mgr = omath::hooks::HooksManager::get(); |
| 54 | + mgr.set_on_wnd_proc([](HWND h, UINT msg, WPARAM wp, LPARAM lp) -> std::optional<LRESULT> { |
| 55 | + if (ImGui_ImplWin32_WndProcHandler(h, msg, wp, lp)) |
| 56 | + return 0; |
| 57 | + return std::nullopt; |
| 58 | + }); |
| 59 | + mgr.hook_wnd_proc(desc.OutputWindow); |
| 60 | + |
| 61 | + g_initialized = true; |
| 62 | + } |
| 63 | + |
| 64 | + void on_present(IDXGISwapChain* swap_chain, UINT, UINT) |
| 65 | + { |
| 66 | + if (!g_initialized) |
| 67 | + { |
| 68 | + if (!g_init_attempted) |
| 69 | + init(swap_chain); |
| 70 | + return; |
| 71 | + } |
| 72 | + |
| 73 | + if (!g_render_target_view) |
| 74 | + create_render_target(swap_chain); |
| 75 | + |
| 76 | + g_context->OMSetRenderTargets(1, &g_render_target_view, nullptr); |
| 77 | + |
| 78 | + ImGui_ImplDX11_NewFrame(); |
| 79 | + ImGui_ImplWin32_NewFrame(); |
| 80 | + ImGui::NewFrame(); |
| 81 | + |
| 82 | + ImGui::SetNextWindowSize({300.f, 80.f}, ImGuiCond_Once); |
| 83 | + ImGui::SetNextWindowPos({10.f, 10.f}, ImGuiCond_Once); |
| 84 | + ImGui::Begin("omath | DX11 hook"); |
| 85 | + ImGui::Text("Hook active"); |
| 86 | + ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate); |
| 87 | + ImGui::End(); |
| 88 | + |
| 89 | + ImGui::Render(); |
| 90 | + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); |
| 91 | + } |
| 92 | + |
| 93 | + void on_resize_buffers(IDXGISwapChain*, UINT, UINT, UINT, DXGI_FORMAT, UINT) |
| 94 | + { |
| 95 | + if (g_render_target_view) |
| 96 | + { |
| 97 | + g_render_target_view->Release(); |
| 98 | + g_render_target_view = nullptr; |
| 99 | + } |
| 100 | + } |
| 101 | +} // namespace |
| 102 | + |
| 103 | +BOOL WINAPI DllMain(HINSTANCE h_instance, DWORD reason, LPVOID) |
| 104 | +{ |
| 105 | + if (reason == DLL_PROCESS_ATTACH) |
| 106 | + { |
| 107 | + DisableThreadLibraryCalls(h_instance); |
| 108 | + CreateThread(nullptr, 0, [](LPVOID) -> DWORD |
| 109 | + { |
| 110 | + while (!GetModuleHandle("d3d11.dll")) |
| 111 | + Sleep(100); |
| 112 | + |
| 113 | + auto& mgr = omath::hooks::HooksManager::get(); |
| 114 | + mgr.set_on_present(on_present); |
| 115 | + mgr.set_on_resize_buffers(on_resize_buffers); |
| 116 | + mgr.hook_dx11(); |
| 117 | + return 0; |
| 118 | + }, nullptr, 0, nullptr); |
| 119 | + } |
| 120 | + else if (reason == DLL_PROCESS_DETACH) |
| 121 | + { |
| 122 | + auto& mgr = omath::hooks::HooksManager::get(); |
| 123 | + mgr.unhook_wnd_proc(); |
| 124 | + mgr.unhook_dx11(); |
| 125 | + |
| 126 | + if (g_initialized) |
| 127 | + { |
| 128 | + ImGui_ImplDX11_Shutdown(); |
| 129 | + ImGui_ImplWin32_Shutdown(); |
| 130 | + ImGui::DestroyContext(); |
| 131 | + } |
| 132 | + |
| 133 | + if (g_render_target_view) { g_render_target_view->Release(); g_render_target_view = nullptr; } |
| 134 | + if (g_context) { g_context->Release(); g_context = nullptr; } |
| 135 | + if (g_device) { g_device->Release(); g_device = nullptr; } |
| 136 | + } |
| 137 | + return TRUE; |
| 138 | +} |
0 commit comments