Examples: DirectX9: Added support for multi-viewport (#2394)

This commit is contained in:
Gilad Reich 2019-03-06 21:34:37 +01:00 committed by omar
parent e91d275b10
commit 0a6c5bc234
3 changed files with 154 additions and 1 deletions

View File

@ -49,6 +49,10 @@ void ResetDevice()
ImGui_ImplDX9_CreateDeviceObjects();
}
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0 // From Windows SDK 8.1+ headers
#endif
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@ -72,12 +76,23 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_DPICHANGED:
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
{
//const int dpi = HIWORD(wParam);
//printf("WM_DPICHANGED to %d (%.0f%%)\n", dpi, (float)dpi / 96.0f * 100.0f);
const RECT* suggested_rect = (RECT*)lParam;
::SetWindowPos(hWnd, NULL, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int main(int, char**)
{
ImGui_ImplWin32_EnableDpiAwareness();
// Create application window
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
RegisterClassEx(&wc);
@ -109,6 +124,14 @@ int main(int, char**)
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer bindings
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX9_Init(g_pd3dDevice);
@ -205,6 +228,14 @@ int main(int, char**)
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
g_pd3dDevice->EndScene();
}
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
// Handle loss of D3D9 device

View File

@ -3,6 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
@ -10,6 +11,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
@ -41,6 +43,10 @@ struct CUSTOMVERTEX
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
// Forward Declarations
static void ImGui_ImplDX9_InitPlatformInterface();
static void ImGui_ImplDX9_ShutdownPlatformInterface();
// Render function.
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
@ -203,16 +209,22 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
io.BackendRendererName = "imgui_impl_dx9";
g_pd3dDevice = device;
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX9_InitPlatformInterface();
return true;
}
void ImGui_ImplDX9_Shutdown()
{
ImGui_ImplDX9_ShutdownPlatformInterface();
ImGui_ImplDX9_InvalidateDeviceObjects();
g_pd3dDevice = NULL;
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
static bool ImGui_ImplDX9_CreateFontsTexture()
@ -278,3 +290,112 @@ void ImGui_ImplDX9_NewFrame()
if (!g_FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the back-end to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
struct ImGuiViewportDataDx9
{
IDirect3DSwapChain9* SwapChain;
D3DPRESENT_PARAMETERS d3dpp;
ImGuiViewportDataDx9() { SwapChain = NULL; ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); }
~ImGuiViewportDataDx9() { IM_ASSERT(SwapChain == NULL); }
};
static void ImGui_ImplDX9_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataDx9* data = IM_NEW(ImGuiViewportDataDx9)();
viewport->RendererUserData = data;
HWND hWnd = (HWND)viewport->PlatformHandle;
IM_ASSERT(hWnd != 0);
ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
data->d3dpp.Windowed = TRUE;
data->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
data->d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
data->d3dpp.hDeviceWindow = hWnd;
data->d3dpp.EnableAutoDepthStencil = TRUE;
data->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
data->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync
g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain);
IM_ASSERT(data->SwapChain != NULL);
}
static void ImGui_ImplDX9_DestroyWindow(ImGuiViewport* viewport)
{
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if (ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData)
{
if (data->SwapChain)
data->SwapChain->Release();
data->SwapChain = NULL;
ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
}
static void ImGui_ImplDX9_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
if (data->SwapChain)
{
data->SwapChain->Release();
data->SwapChain = NULL;
data->d3dpp.BackBufferWidth = (UINT)size.x;
data->d3dpp.BackBufferHeight = (UINT)size.y;
g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain);
}
}
static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
LPDIRECT3DSURFACE9 render_target = NULL;
LPDIRECT3DSURFACE9 last_render_target = NULL;
data->SwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &render_target);
g_pd3dDevice->GetRenderTarget(0, &last_render_target);
g_pd3dDevice->SetRenderTarget(0, render_target);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
{
D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*255.0f), (int)(clear_color.y*255.0f), (int)(clear_color.z*255.0f), (int)(clear_color.w*255.0f));
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0);
}
ImGui_ImplDX9_RenderDrawData(viewport->DrawData);
// Restore render target
g_pd3dDevice->SetRenderTarget(0, last_render_target);
render_target->Release();
last_render_target->Release();
}
static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
data->SwapChain->Present(NULL, NULL, data->d3dpp.hDeviceWindow, NULL, NULL);
}
static void ImGui_ImplDX9_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_CreateWindow = ImGui_ImplDX9_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplDX9_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplDX9_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplDX9_RenderWindow;
platform_io.Renderer_SwapBuffers = ImGui_ImplDX9_SwapBuffers;
}
static void ImGui_ImplDX9_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}

View File

@ -3,6 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.