Skip to content

Commit 06bdcdb

Browse files
authored
Rework UI to use injected DirectX hooks (#3)
* Migration to DearImGuiInjection * Remove unused dispatcher and fix ImGui context disposing * Fix cursor visibility, configurations and revert old theme * Clean target frameworks to only target .Net 6 * Update version * Fix conditional compilation for RendererFinder * Migrate DearImGuiInjection to native BepInEx hooks * Merge DearImGuiInjection in one project
1 parent e73b296 commit 06bdcdb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+7347
-44
lines changed
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using DearImGuiInjection.Windows;
4+
using ImGuiNET;
5+
using SharpDX.Direct3D11;
6+
using SharpDX.DXGI;
7+
using Device = SharpDX.Direct3D11.Device;
8+
9+
namespace DearImGuiInjection.Backends;
10+
11+
internal static class ImGuiDX11
12+
{
13+
private static IntPtr _windowHandle;
14+
15+
private static RenderTargetView _renderTargetView;
16+
private static User32.WndProcDelegate _myWindowProc;
17+
private static IntPtr _originalWindowProc;
18+
private const int GWL_WNDPROC = -4;
19+
20+
internal static void Init()
21+
{
22+
RendererFinder.Renderers.DX11Renderer.OnPresent += InitImGui;
23+
24+
RendererFinder.Renderers.DX11Renderer.OnPresent += RenderImGui;
25+
RendererFinder.Renderers.DX11Renderer.PreResizeBuffers += PreResizeBuffers;
26+
RendererFinder.Renderers.DX11Renderer.PostResizeBuffers += PostResizeBuffers;
27+
}
28+
29+
internal static void Dispose()
30+
{
31+
if (!DearImGuiInjection.Initialized)
32+
{
33+
return;
34+
}
35+
36+
RendererFinder.Renderers.DX11Renderer.PostResizeBuffers -= PostResizeBuffers;
37+
RendererFinder.Renderers.DX11Renderer.PreResizeBuffers -= PreResizeBuffers;
38+
RendererFinder.Renderers.DX11Renderer.OnPresent -= RenderImGui;
39+
40+
User32.SetWindowLong(_windowHandle, GWL_WNDPROC, _originalWindowProc);
41+
42+
ImGuiWin32Impl.Shutdown();
43+
44+
_renderTargetView = null;
45+
46+
Log.Info("ImGui.ImGuiImplDX11Shutdown()");
47+
ImGuiDX11Impl.Shutdown();
48+
49+
_windowHandle = IntPtr.Zero;
50+
}
51+
52+
private static unsafe void InitImGui(SwapChain swapChain, uint syncInterval, uint flags)
53+
{
54+
var windowHandle = swapChain.Description.OutputHandle;
55+
56+
if (!DearImGuiInjection.Initialized)
57+
{
58+
DearImGuiInjection.InitImGui();
59+
60+
InitImGuiWin32(windowHandle);
61+
62+
InitImGuiDX11(swapChain);
63+
64+
DearImGuiInjection.Initialized = true;
65+
}
66+
67+
RendererFinder.Renderers.DX11Renderer.OnPresent -= InitImGui;
68+
}
69+
70+
private static unsafe void InitImGuiWin32(IntPtr windowHandle)
71+
{
72+
if (!DearImGuiInjection.Initialized)
73+
{
74+
_windowHandle = windowHandle;
75+
if (_windowHandle == IntPtr.Zero)
76+
return;
77+
78+
Log.Info($"ImGuiImplWin32Init, Window Handle: {windowHandle:X}");
79+
ImGuiWin32Impl.Init(_windowHandle);
80+
81+
_myWindowProc = new User32.WndProcDelegate(WndProcHandler);
82+
_originalWindowProc = User32.SetWindowLong(windowHandle, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(_myWindowProc));
83+
}
84+
}
85+
86+
private static unsafe void InitImGuiDX11(SwapChain swapChain)
87+
{
88+
using var device = InitImGuiDX11Internal(swapChain);
89+
90+
ImGuiDX11Impl.Init((void*)device.NativePointer, (void*)device.ImmediateContext.NativePointer);
91+
}
92+
93+
private static unsafe Device InitImGuiDX11Internal(SwapChain swapChain)
94+
{
95+
var device = swapChain.GetDevice<Device>();
96+
using var backBuffer = swapChain.GetBackBuffer<Texture2D>(0);
97+
_renderTargetView = new RenderTargetView(device, backBuffer);
98+
99+
return device;
100+
}
101+
102+
private static unsafe IntPtr WndProcHandler(IntPtr windowHandle, WindowMessage message, IntPtr wParam, IntPtr lParam)
103+
{
104+
if (DearImGuiInjection.IsCursorVisible && ImGuiWin32Impl.WndProcHandler(windowHandle, message, wParam, lParam))
105+
return IntPtr.Zero;
106+
107+
return User32.CallWindowProc(_originalWindowProc, windowHandle, message, wParam, lParam);
108+
}
109+
110+
private static unsafe void RenderImGui(SwapChain swapChain, uint syncInterval, uint flags)
111+
{
112+
var windowHandle = swapChain.Description.OutputHandle;
113+
114+
if (!IsTargetWindowHandle(windowHandle))
115+
{
116+
// Log.Info($"[DX11] Discarding window handle {windowHandle:X} due to mismatch");
117+
return;
118+
}
119+
120+
ImGuiDX11Impl.NewFrame();
121+
122+
NewFrame();
123+
124+
using var device = swapChain.GetDevice<Device>();
125+
device.ImmediateContext.OutputMerger.SetRenderTargets(_renderTargetView);
126+
127+
var drawData = ImGui.GetDrawData();
128+
ImGuiDX11Impl.RenderDrawData(drawData.NativePtr);
129+
}
130+
131+
private static bool IsTargetWindowHandle(IntPtr windowHandle)
132+
{
133+
if (windowHandle != IntPtr.Zero)
134+
{
135+
return windowHandle == _windowHandle || !DearImGuiInjection.Initialized;
136+
}
137+
138+
return false;
139+
}
140+
141+
private static unsafe void NewFrame()
142+
{
143+
ImGuiWin32Impl.NewFrame();
144+
ImGui.NewFrame();
145+
146+
if (DearImGuiInjection.RenderAction != null)
147+
{
148+
foreach (Action item in DearImGuiInjection.RenderAction.GetInvocationList())
149+
{
150+
try
151+
{
152+
item();
153+
}
154+
catch (Exception e)
155+
{
156+
Log.Error(e);
157+
}
158+
}
159+
}
160+
161+
ImGui.EndFrame();
162+
ImGui.Render();
163+
164+
/*if ((DearImGuiInjection.IO.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) > 0)
165+
{
166+
ImGui.UpdatePlatformWindows();
167+
ImGui.RenderPlatformWindowsDefault(IntPtr.Zero, IntPtr.Zero);
168+
}*/
169+
}
170+
171+
private static void PreResizeBuffers(SwapChain swapChain, uint bufferCount, uint width, uint height, Format newFormat, uint swapchainFlags)
172+
{
173+
if (!DearImGuiInjection.Initialized)
174+
{
175+
return;
176+
}
177+
178+
var windowHandle = swapChain.Description.OutputHandle;
179+
180+
Log.Info($"[DX11 ResizeBuffers] Window Handle {windowHandle:X}");
181+
182+
if (!IsTargetWindowHandle(windowHandle))
183+
{
184+
Log.Info($"[DX11 ResizeBuffers] Discarding window handle {windowHandle:X} due to mismatch");
185+
return;
186+
}
187+
188+
_renderTargetView?.Dispose();
189+
_renderTargetView = null;
190+
ImGuiDX11Impl.InvalidateDeviceObjects();
191+
}
192+
193+
private static void PostResizeBuffers(SwapChain swapChain, uint bufferCount, uint width, uint height, Format newFormat, uint swapchainFlags)
194+
{
195+
if (!DearImGuiInjection.Initialized)
196+
{
197+
return;
198+
}
199+
200+
var windowHandle = swapChain.Description.OutputHandle;
201+
202+
if (!IsTargetWindowHandle(windowHandle))
203+
{
204+
Log.Info($"[DX11 ResizeBuffers] Discarding window handle {windowHandle:X} due to mismatch");
205+
return;
206+
}
207+
208+
ImGuiDX11Impl.CreateDeviceObjects();
209+
210+
using var device = swapChain.GetDevice<Device>();
211+
using var backBuffer = swapChain.GetBackBuffer<Texture2D>(0);
212+
_renderTargetView = new RenderTargetView(device, backBuffer);
213+
}
214+
}

0 commit comments

Comments
 (0)