From 46b61427e1f7c18e90fd43ebc1188ccd8958516a Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 18 Mar 2018 18:44:57 +0100 Subject: [PATCH] Viewport, Platform: Refactored platform interface. Removed need to use imgui_internal.h in backends. Split viewport into public facing ImGuiViewport and internal structure. Exposing enough data to provide custom tweaked renderers. Renamed handlers, fixed lots of inconsistencies. (#1542, #1042) --- examples/directx10_example/main.cpp | 4 +- examples/directx11_example/main.cpp | 4 +- examples/directx12_example/main.cpp | 4 +- examples/imgui_impl_dx10.cpp | 35 ++- examples/imgui_impl_dx11.cpp | 42 ++-- examples/imgui_impl_dx12.cpp | 39 ++- examples/imgui_impl_glfw.cpp | 45 ++-- examples/imgui_impl_opengl3.cpp | 24 +- examples/imgui_impl_sdl2.cpp | 42 ++-- examples/imgui_impl_vulkan.cpp | 43 ++-- examples/imgui_impl_win32.cpp | 31 +-- examples/opengl2_example/main.cpp | 2 +- examples/opengl3_example/main.cpp | 6 +- examples/sdl_opengl3_example/main.cpp | 5 +- examples/sdl_vulkan_example/main.cpp | 6 +- examples/vulkan_example/main.cpp | 6 +- imgui.cpp | 333 ++++++++++++++------------ imgui.h | 131 +++++++--- imgui_internal.h | 70 ++---- 19 files changed, 460 insertions(+), 412 deletions(-) diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index fb034cd8c..6166a60ff 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -208,7 +208,9 @@ int main(int, char**) ImGui::Render(); ImGui_ImplDX10_RenderDrawData(ImGui::GetDrawData()); - ImGui::RenderAdditionalViewports(); + // Update and Render additional Platform Windows + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindows(); g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 6e81b811b..b5211009d 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -226,7 +226,9 @@ int main(int, char**) ImGui::Render(); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - ImGui::RenderAdditionalViewports(); + // Update and Render additional Platform Windows + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindows(); g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp index 20957f012..f3d5d1713 100644 --- a/examples/directx12_example/main.cpp +++ b/examples/directx12_example/main.cpp @@ -401,7 +401,9 @@ int main(int, char**) g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList); - ImGui::RenderAdditionalViewports(); + // Update and Render additional Platform Windows + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindows(); g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index 4636e7da5..9a14b8ffd 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -11,7 +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 ImGuiRendererInterface. +// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2018-XX-XX: DirectX10: Offset projection matrix and clipping rectangle by draw_data->DisplayPos (which will be non-zero for multi-viewport applications). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -498,12 +498,9 @@ void ImGui_ImplDX10_NewFrame() ImGui_ImplDX10_CreateDeviceObjects(); } - -// -------------------------------------------------------------------------------------------------------- -// Platform Windows -// -------------------------------------------------------------------------------------------------------- - -#include "imgui_internal.h" // ImGuiViewport +//-------------------------------------------------------------------------------------------------------- +// Platform Interface (Optional, for multi-viewport support) +//-------------------------------------------------------------------------------------------------------- struct ImGuiPlatformDataDx10 { @@ -514,7 +511,7 @@ struct ImGuiPlatformDataDx10 ~ImGuiPlatformDataDx10() { IM_ASSERT(SwapChain == NULL && RTView == NULL); } }; -static void ImGui_ImplDX10_CreateViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX10_CreateWindow(ImGuiViewport* viewport) { ImGuiPlatformDataDx10* data = IM_NEW(ImGuiPlatformDataDx10)(); viewport->RendererUserData = data; @@ -551,7 +548,7 @@ static void ImGui_ImplDX10_CreateViewport(ImGuiViewport* viewport) } } -static void ImGui_ImplDX10_DestroyViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { if (ImGuiPlatformDataDx10* data = (ImGuiPlatformDataDx10*)viewport->RendererUserData) { @@ -566,7 +563,7 @@ static void ImGui_ImplDX10_DestroyViewport(ImGuiViewport* viewport) viewport->RendererUserData = NULL; } -static void ImGui_ImplDX10_ResizeViewport(ImGuiViewport* viewport, ImVec2 size) +static void ImGui_ImplDX10_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGuiPlatformDataDx10* data = (ImGuiPlatformDataDx10*)viewport->RendererUserData; if (data->RTView) @@ -591,7 +588,7 @@ static void ImGui_ImplDX10_RenderViewport(ImGuiViewport* viewport) g_pd3dDevice->OMSetRenderTargets(1, &data->RTView, NULL); if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) g_pd3dDevice->ClearRenderTargetView(data->RTView, (float*)&clear_color); - ImGui_ImplDX10_RenderDrawData(&viewport->DrawData); + ImGui_ImplDX10_RenderDrawData(viewport->DrawData); } static void ImGui_ImplDX10_SwapBuffers(ImGuiViewport* viewport) @@ -602,18 +599,16 @@ static void ImGui_ImplDX10_SwapBuffers(ImGuiViewport* viewport) void ImGui_ImplDX10_InitPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - io.RendererInterface.CreateViewport = ImGui_ImplDX10_CreateViewport; - io.RendererInterface.DestroyViewport = ImGui_ImplDX10_DestroyViewport; - io.RendererInterface.ResizeViewport = ImGui_ImplDX10_ResizeViewport; - io.RendererInterface.RenderViewport = ImGui_ImplDX10_RenderViewport; - io.RendererInterface.SwapBuffers = ImGui_ImplDX10_SwapBuffers; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Renderer_CreateWindow = ImGui_ImplDX10_CreateWindow; + platform_io.Renderer_DestroyWindow = ImGui_ImplDX10_DestroyWindow; + platform_io.Renderer_SetWindowSize = ImGui_ImplDX10_SetWindowSize; + platform_io.Renderer_RenderWindow = ImGui_ImplDX10_RenderViewport; + platform_io.Renderer_SwapBuffers = ImGui_ImplDX10_SwapBuffers; } void ImGui_ImplDX10_ShutdownPlatformInterface() { - ImGui::DestroyViewportsRendererData(ImGui::GetCurrentContext()); - ImGuiIO& io = ImGui::GetIO(); - memset(&io.RendererInterface, 0, sizeof(io.RendererInterface)); + ImGui::DestroyPlatformWindows(); } diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 09e32d805..244fb6a80 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -11,7 +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 ImGuiRendererInterface. +// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2018-XX-XX: DirectX11: Offset projection matrix and clipping rectangle by draw_data->DisplayPos (which will be non-zero for multi-viewport applications). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -507,11 +507,9 @@ void ImGui_ImplDX11_NewFrame() ImGui_ImplDX11_CreateDeviceObjects(); } -// -------------------------------------------------------------------------------------------------------- -// Platform Windows -// -------------------------------------------------------------------------------------------------------- - -#include "imgui_internal.h" // ImGuiViewport +//-------------------------------------------------------------------------------------------------------- +// Platform Interface (Optional, for multi-viewport support) +//-------------------------------------------------------------------------------------------------------- struct ImGuiPlatformDataDx11 { @@ -522,12 +520,11 @@ struct ImGuiPlatformDataDx11 ~ImGuiPlatformDataDx11() { IM_ASSERT(SwapChain == NULL && RTView == NULL); } }; -static void ImGui_ImplDX11_CreateViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX11_CreateWindow(ImGuiViewport* viewport) { ImGuiPlatformDataDx11* data = IM_NEW(ImGuiPlatformDataDx11)(); viewport->RendererUserData = data; - // FIXME-PLATFORM HWND hwnd = (HWND)viewport->PlatformHandle; IM_ASSERT(hwnd != 0); @@ -559,7 +556,7 @@ static void ImGui_ImplDX11_CreateViewport(ImGuiViewport* viewport) } } -static void ImGui_ImplDX11_DestroyViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX11_DestroyWindow(ImGuiViewport* viewport) { if (ImGuiPlatformDataDx11* data = (ImGuiPlatformDataDx11*)viewport->RendererUserData) { @@ -574,7 +571,7 @@ static void ImGui_ImplDX11_DestroyViewport(ImGuiViewport* viewport) viewport->RendererUserData = NULL; } -static void ImGui_ImplDX11_ResizeViewport(ImGuiViewport* viewport, ImVec2 size) +static void ImGui_ImplDX11_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGuiPlatformDataDx11* data = (ImGuiPlatformDataDx11*)viewport->RendererUserData; if (data->RTView) @@ -592,14 +589,14 @@ static void ImGui_ImplDX11_ResizeViewport(ImGuiViewport* viewport, ImVec2 size) } } -static void ImGui_ImplDX11_RenderViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX11_RenderWindow(ImGuiViewport* viewport) { ImGuiPlatformDataDx11* data = (ImGuiPlatformDataDx11*)viewport->RendererUserData; ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); g_pd3dDeviceContext->OMSetRenderTargets(1, &data->RTView, NULL); if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) g_pd3dDeviceContext->ClearRenderTargetView(data->RTView, (float*)&clear_color); - ImGui_ImplDX11_RenderDrawData(&viewport->DrawData); + ImGui_ImplDX11_RenderDrawData(viewport->DrawData); } static void ImGui_ImplDX11_SwapBuffers(ImGuiViewport* viewport) @@ -608,20 +605,17 @@ static void ImGui_ImplDX11_SwapBuffers(ImGuiViewport* viewport) data->SwapChain->Present(0, 0); // Present without vsync } -void ImGui_ImplDX11_InitPlatformInterface() +static void ImGui_ImplDX11_InitPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - io.RendererInterface.CreateViewport = ImGui_ImplDX11_CreateViewport; - io.RendererInterface.DestroyViewport = ImGui_ImplDX11_DestroyViewport; - io.RendererInterface.ResizeViewport = ImGui_ImplDX11_ResizeViewport; - io.RendererInterface.RenderViewport = ImGui_ImplDX11_RenderViewport; - io.RendererInterface.SwapBuffers = ImGui_ImplDX11_SwapBuffers; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Renderer_CreateWindow = ImGui_ImplDX11_CreateWindow; + platform_io.Renderer_DestroyWindow = ImGui_ImplDX11_DestroyWindow; + platform_io.Renderer_SetWindowSize = ImGui_ImplDX11_SetWindowSize; + platform_io.Renderer_RenderWindow = ImGui_ImplDX11_RenderWindow; + platform_io.Renderer_SwapBuffers = ImGui_ImplDX11_SwapBuffers; } -void ImGui_ImplDX11_ShutdownPlatformInterface() +static void ImGui_ImplDX11_ShutdownPlatformInterface() { - ImGui::DestroyViewportsRendererData(ImGui::GetCurrentContext()); - ImGuiIO& io = ImGui::GetIO(); - memset(&io.RendererInterface, 0, sizeof(io.RendererInterface)); + ImGui::DestroyPlatformWindows(); } - diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index dc7f1d756..98190ebbe 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -634,11 +634,9 @@ void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* command_list) g_pd3dCommandList = command_list; } -// -------------------------------------------------------------------------------------------------------- -// Platform Windows -// -------------------------------------------------------------------------------------------------------- - -#include "imgui_internal.h" // ImGuiViewport +//-------------------------------------------------------------------------------------------------------- +// Platform Interface (Optional, for multi-viewport support) +//-------------------------------------------------------------------------------------------------------- struct ImGuiPlatformDataDx12 { @@ -648,7 +646,7 @@ struct ImGuiPlatformDataDx12 ~ImGuiPlatformDataDx12() { IM_ASSERT(SwapChain == NULL); } }; -static void ImGui_ImplDX12_CreateViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport) { ImGuiPlatformDataDx12* data = IM_NEW(ImGuiPlatformDataDx12)(); viewport->RendererUserData = data; @@ -688,7 +686,7 @@ static void ImGui_ImplDX12_CreateViewport(ImGuiViewport* viewport) */ } -static void ImGui_ImplDX12_DestroyViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport) { if (ImGuiPlatformDataDx12* data = (ImGuiPlatformDataDx12*)viewport->RendererUserData) { @@ -706,11 +704,11 @@ static void ImGui_ImplDX12_DestroyViewport(ImGuiViewport* viewport) viewport->RendererUserData = NULL; } -static void ImGui_ImplDX12_ResizeViewport(ImGuiViewport* viewport, int w, int h) +static void ImGui_ImplDX12_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGuiPlatformDataDx12* data = (ImGuiPlatformDataDx12*)viewport->RendererUserData; IM_ASSERT(0); - (void)data; (void)w; (void)h; + (void)data; (void)size; /* if (data->RTView) { @@ -720,7 +718,7 @@ static void ImGui_ImplDX12_ResizeViewport(ImGuiViewport* viewport, int w, int h) if (data->SwapChain) { ID3D11Texture2D* pBackBuffer = NULL; - data->SwapChain->ResizeBuffers(0, w, h, DXGI_FORMAT_UNKNOWN, 0); + data->SwapChain->ResizeBuffers(0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0); data->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &data->RTView); pBackBuffer->Release(); @@ -728,7 +726,7 @@ static void ImGui_ImplDX12_ResizeViewport(ImGuiViewport* viewport, int w, int h) */ } -static void ImGui_ImplDX12_RenderViewport(ImGuiViewport* viewport) +static void ImGui_ImplDX12_RenderWindow(ImGuiViewport* viewport) { ImGuiPlatformDataDx12* data = (ImGuiPlatformDataDx12*)viewport->RendererUserData; IM_ASSERT(0); @@ -739,7 +737,7 @@ static void ImGui_ImplDX12_RenderViewport(ImGuiViewport* viewport) if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) g_pd3dDeviceContext->ClearRenderTargetView(data->RTView, (float*)&clear_color); */ - ImGui_ImplDX12_RenderDrawData(&viewport->DrawData); + ImGui_ImplDX12_RenderDrawData(viewport->DrawData); } static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport) @@ -754,18 +752,15 @@ static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport) void ImGui_ImplDX12_InitPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - io.RendererInterface.CreateViewport = ImGui_ImplDX12_CreateViewport; - io.RendererInterface.DestroyViewport = ImGui_ImplDX12_DestroyViewport; - io.RendererInterface.ResizeViewport = ImGui_ImplDX12_ResizeViewport; - io.RendererInterface.RenderViewport = ImGui_ImplDX12_RenderViewport; - io.RendererInterface.SwapBuffers = ImGui_ImplDX12_SwapBuffers; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Renderer_CreateWindow = ImGui_ImplDX12_CreateWindow; + platform_io.Renderer_DestroyWindow = ImGui_ImplDX12_DestroyWindow; + platform_io.Renderer_SetWindowSize = ImGui_ImplDX12_SetWindowSize; + platform_io.Renderer_RenderWindow = ImGui_ImplDX12_RenderWindow; + platform_io.Renderer_SwapBuffers = ImGui_ImplDX12_SwapBuffers; } void ImGui_ImplDX12_ShutdownPlatformInterface() { - ImGui::DestroyViewportsRendererData(ImGui::GetCurrentContext()); - ImGuiIO& io = ImGui::GetIO(); - memset(&io.RendererInterface, 0, sizeof(io.RendererInterface)); + ImGui::DestroyPlatformWindows(); } - diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 7197bd5a3..c761b8f95 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -12,7 +12,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 ImGuiPlatformInterface +// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2018-XX-XX: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -25,14 +25,13 @@ #include "imgui.h" #include "imgui_impl_glfw.h" -#include "imgui_internal.h" // FIXME-PLATFORM // GLFW #include #ifdef _WIN32 #undef APIENTRY #define GLFW_EXPOSE_NATIVE_WIN32 -#include // for glfwGetWin32Window +#include // for glfwGetWin32Window #endif #ifdef GLFW_HOVERED #define GLFW_HAS_GLFW_HOVERED 1 @@ -209,10 +208,10 @@ static void ImGui_ImplGlfw_UpdateMouse() g_MouseJustPressed[i] = false; } - const ImVector& viewports = ImGui::GetViewports(); - for (int n = 0; n < viewports.Size; n++) + ImGuiPlatformData* platform_data = ImGui::GetPlatformData(); + for (int n = 0; n < platform_data->Viewports.Size; n++) { - ImGuiViewport* viewport = viewports[n]; + ImGuiViewport* viewport = platform_data->Viewports[n]; GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle; IM_ASSERT(window != NULL); if (glfwGetWindowAttrib(window, GLFW_FOCUSED)) @@ -330,7 +329,7 @@ static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int) viewport->PlatformRequestResize = true; } -static void ImGui_ImplGlfw_CreateViewport(ImGuiViewport* viewport) +static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport) { ImGuiPlatformDataGlfw* data = IM_NEW(ImGuiPlatformDataGlfw)(); viewport->PlatformUserData = data; @@ -349,7 +348,7 @@ static void ImGui_ImplGlfw_CreateViewport(ImGuiViewport* viewport) glfwSetWindowSizeCallback(data->Window, ImGui_ImplGlfw_WindowSizeCallback); } -static void ImGui_ImplGlfw_DestroyViewport(ImGuiViewport* viewport) +static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport) { if (ImGuiPlatformDataGlfw* data = (ImGuiPlatformDataGlfw*)viewport->PlatformUserData) { @@ -449,7 +448,7 @@ static void ImGui_ImplGlfw_SetWindowTitle(ImGuiViewport* viewport, const char* t glfwSetWindowTitle(data->Window, title); } -static void ImGui_ImplGlfw_RenderViewport(ImGuiViewport* viewport) +static void ImGui_ImplGlfw_RenderWindow(ImGuiViewport* viewport) { ImGuiPlatformDataGlfw* data = (ImGuiPlatformDataGlfw*)viewport->PlatformUserData; if (g_ClientApi == GlfwClientApi_OpenGL) @@ -491,19 +490,19 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst static void ImGui_ImplGlfw_InitPlatformInterface() { // Register platform interface (will be coupled with a renderer interface) - ImGuiIO& io = ImGui::GetIO(); - io.PlatformInterface.CreateViewport = ImGui_ImplGlfw_CreateViewport; - io.PlatformInterface.DestroyViewport = ImGui_ImplGlfw_DestroyViewport; - io.PlatformInterface.ShowWindow = ImGui_ImplGlfw_ShowWindow; - io.PlatformInterface.SetWindowPos = ImGui_ImplGlfw_SetWindowPos; - io.PlatformInterface.GetWindowPos = ImGui_ImplGlfw_GetWindowPos; - io.PlatformInterface.SetWindowSize = ImGui_ImplGlfw_SetWindowSize; - io.PlatformInterface.GetWindowSize = ImGui_ImplGlfw_GetWindowSize; - io.PlatformInterface.SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle; - io.PlatformInterface.RenderViewport = ImGui_ImplGlfw_RenderViewport; - io.PlatformInterface.SwapBuffers = ImGui_ImplGlfw_SwapBuffers; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Platform_CreateWindow = ImGui_ImplGlfw_CreateWindow; + platform_io.Platform_DestroyWindow = ImGui_ImplGlfw_DestroyWindow; + platform_io.Platform_ShowWindow = ImGui_ImplGlfw_ShowWindow; + platform_io.Platform_SetWindowPos = ImGui_ImplGlfw_SetWindowPos; + platform_io.Platform_GetWindowPos = ImGui_ImplGlfw_GetWindowPos; + platform_io.Platform_SetWindowSize = ImGui_ImplGlfw_SetWindowSize; + platform_io.Platform_GetWindowSize = ImGui_ImplGlfw_GetWindowSize; + platform_io.Platform_SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle; + platform_io.Platform_RenderWindow = ImGui_ImplGlfw_RenderWindow; + platform_io.Platform_SwapBuffers = ImGui_ImplGlfw_SwapBuffers; #if GLFW_HAS_VULKAN - io.PlatformInterface.CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; + platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif // Register main window handle @@ -516,8 +515,4 @@ static void ImGui_ImplGlfw_InitPlatformInterface() static void ImGui_ImplGlfw_ShutdownPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - ImGuiViewport* main_viewport = ImGui::GetMainViewport(); - main_viewport->PlatformHandle = NULL; - memset(&io.PlatformInterface, 0, sizeof(io.PlatformInterface)); } diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 42f2ccb6d..11083df8e 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -323,13 +323,11 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects() ImGui_ImplOpenGL3_DestroyFontsTexture(); } -// -------------------------------------------------------------------------------------------------------- -// Platform Windows -// -------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------- +// Platform Interface (Optional, for multi-viewport support) +//-------------------------------------------------------------------------------------------------------- -#include "imgui_internal.h" // ImGuiViewport - -static void ImGui_ImplOpenGL3_RenderViewport(ImGuiViewport* viewport) +static void ImGui_ImplOpenGL3_RenderWindow(ImGuiViewport* viewport) { if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) { @@ -337,18 +335,16 @@ static void ImGui_ImplOpenGL3_RenderViewport(ImGuiViewport* viewport) glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); } - ImGui_ImplOpenGL3_RenderDrawData(&viewport->DrawData); + ImGui_ImplOpenGL3_RenderDrawData(viewport->DrawData); } -void ImGui_ImplOpenGL3_InitPlatformInterface() +static void ImGui_ImplOpenGL3_InitPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - io.RendererInterface.RenderViewport = ImGui_ImplOpenGL3_RenderViewport; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Renderer_RenderWindow = ImGui_ImplOpenGL3_RenderWindow; } -void ImGui_ImplOpenGL3_ShutdownPlatformInterface() +static void ImGui_ImplOpenGL3_ShutdownPlatformInterface() { - ImGui::DestroyViewportsRendererData(ImGui::GetCurrentContext()); - ImGuiIO& io = ImGui::GetIO(); - memset(&io.RendererInterface, 0, sizeof(io.RendererInterface)); + ImGui::DestroyPlatformWindows(); } diff --git a/examples/imgui_impl_sdl2.cpp b/examples/imgui_impl_sdl2.cpp index 8fe81f2ac..53a30dfdd 100644 --- a/examples/imgui_impl_sdl2.cpp +++ b/examples/imgui_impl_sdl2.cpp @@ -12,7 +12,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 ImGuiPlatformInterface +// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2018-XX-XX: Misc: ImGui_ImplSDL2_Init() now takes a SDL_GLContext parameter. // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -27,7 +27,6 @@ #include "imgui.h" #include "imgui_impl_sdl2.h" -#include "imgui_internal.h" // FIXME-PLATFORM // SDL #include @@ -271,9 +270,9 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window) ImGui::NewFrame(); } -// -------------------------------------------------------------------------------------------------------- -// Platform Windows -// -------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------- +// Platform Interface (Optional, for multi-viewport support) +//-------------------------------------------------------------------------------------------------------- struct ImGuiPlatformDataSDL2 { @@ -285,7 +284,7 @@ struct ImGuiPlatformDataSDL2 ~ImGuiPlatformDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); } }; -static void ImGui_ImplSDL2_CreateViewport(ImGuiViewport* viewport) +static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport) { ImGuiPlatformDataSDL2* data = IM_NEW(ImGuiPlatformDataSDL2)(); viewport->PlatformUserData = data; @@ -319,7 +318,7 @@ static void ImGui_ImplSDL2_CreateViewport(ImGuiViewport* viewport) viewport->PlatformHandle = (void*)data->Window; } -static void ImGui_ImplSDL2_DestroyViewport(ImGuiViewport* viewport) +static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport) { if (ImGuiPlatformDataSDL2* data = (ImGuiPlatformDataSDL2*)viewport->PlatformUserData) { @@ -401,7 +400,7 @@ static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const char* t SDL_SetWindowTitle(data->Window, title); } -static void ImGui_ImplSDL2_RenderViewport(ImGuiViewport* viewport) +static void ImGui_ImplSDL2_RenderWindow(ImGuiViewport* viewport) { ImGuiPlatformDataSDL2* data = (ImGuiPlatformDataSDL2*)viewport->PlatformUserData; if (data->GLContext) @@ -434,21 +433,22 @@ static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_gl_context) { // Register platform interface (will be coupled with a renderer interface) - ImGuiIO& io = ImGui::GetIO(); - io.PlatformInterface.CreateViewport = ImGui_ImplSDL2_CreateViewport; - io.PlatformInterface.DestroyViewport = ImGui_ImplSDL2_DestroyViewport; - io.PlatformInterface.ShowWindow = ImGui_ImplSDL2_ShowWindow; - io.PlatformInterface.SetWindowPos = ImGui_ImplSDL2_SetWindowPos; - io.PlatformInterface.GetWindowPos = ImGui_ImplSDL2_GetWindowPos; - io.PlatformInterface.SetWindowSize = ImGui_ImplSDL2_SetWindowSize; - io.PlatformInterface.GetWindowSize = ImGui_ImplSDL2_GetWindowSize; - io.PlatformInterface.SetWindowTitle = ImGui_ImplSDL2_SetWindowTitle; - io.PlatformInterface.RenderViewport = ImGui_ImplSDL2_RenderViewport; - io.PlatformInterface.SwapBuffers = ImGui_ImplSDL2_SwapBuffers; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Platform_CreateWindow = ImGui_ImplSDL2_CreateWindow; + platform_io.Platform_DestroyWindow = ImGui_ImplSDL2_DestroyWindow; + platform_io.Platform_ShowWindow = ImGui_ImplSDL2_ShowWindow; + platform_io.Platform_SetWindowPos = ImGui_ImplSDL2_SetWindowPos; + platform_io.Platform_GetWindowPos = ImGui_ImplSDL2_GetWindowPos; + platform_io.Platform_SetWindowSize = ImGui_ImplSDL2_SetWindowSize; + platform_io.Platform_GetWindowSize = ImGui_ImplSDL2_GetWindowSize; + platform_io.Platform_SetWindowTitle = ImGui_ImplSDL2_SetWindowTitle; + platform_io.Platform_RenderWindow = ImGui_ImplSDL2_RenderWindow; + platform_io.Platform_SwapBuffers = ImGui_ImplSDL2_SwapBuffers; #if SDL_HAS_VULKAN - io.PlatformInterface.CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface; + platform_io.Platform_CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface; #endif + ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= SDL_HAS_WINDOW_OPACITY ? ImGuiConfigFlags_PlatformHasWindowAlpha : 0; // Register main window handle @@ -463,6 +463,4 @@ static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_g static void ImGui_ImplSDL2_ShutdownPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - memset(&io.PlatformInterface, 0, sizeof(io.PlatformInterface)); } diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index fe7af6ddf..714f1dcf6 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -23,6 +23,7 @@ #include "imgui.h" #include "imgui_impl_vulkan.h" +#include // Vulkan data static const VkAllocationCallbacks* g_Allocator = NULL; @@ -714,10 +715,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend ImGui_ImplVulkan_CreateDeviceObjects(); io.ConfigFlags |= ImGuiConfigFlags_RendererHasViewports; if (io.ConfigFlags & ImGuiConfigFlags_EnableViewports) - { - IM_ASSERT(io.PlatformInterface.CreateVkSurface != NULL); ImGui_ImplVulkan_InitPlatformInterface(); - } return true; } @@ -734,7 +732,6 @@ void ImGui_ImplVulkan_NewFrame() //------------------------------------------------------------------------- // Miscellaneous Vulkan Helpers -// (Those are currently not strictly needed by the binding, but will be once if we support multi-viewports) //------------------------------------------------------------------------- #include // malloc @@ -1049,11 +1046,10 @@ void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, I } //-------------------------------------------------------------------------------------------------------- -// Platform Windows (OPTIONAL/EXPERIMENTAL) +// Platform Interface (Optional, for multi-viewport support) +// FIXME-PLATFORM: Vulkan support unfinished //-------------------------------------------------------------------------------------------------------- -#include "imgui_internal.h" // ImGuiViewport - struct ImGuiPlatformDataVulkan { ImGui_ImplVulkan_WindowData WindowData; @@ -1062,15 +1058,15 @@ struct ImGuiPlatformDataVulkan ~ImGuiPlatformDataVulkan() { } }; -static void ImGui_ImplVulkan_CreateViewport(ImGuiViewport* viewport) +static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) { ImGuiPlatformDataVulkan* data = IM_NEW(ImGuiPlatformDataVulkan)(); viewport->RendererUserData = data; ImGui_ImplVulkan_WindowData* wd = &data->WindowData; // Create surface - ImGuiIO& io = ImGui::GetIO(); - VkResult err = (VkResult)io.PlatformInterface.CreateVkSurface(viewport, (ImU64)g_Instance, (const void*)g_Allocator, (ImU64*)&wd->Surface); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + VkResult err = (VkResult)platform_io.Platform_CreateVkSurface(viewport, (ImU64)g_Instance, (const void*)g_Allocator, (ImU64*)&wd->Surface); check_vk_result(err); // Check for WSI support @@ -1097,7 +1093,7 @@ static void ImGui_ImplVulkan_CreateViewport(ImGuiViewport* viewport) ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, (int)viewport->Size.x, (int)viewport->Size.y); } -static void ImGui_ImplVulkan_DestroyViewport(ImGuiViewport* viewport) +static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport) { if (ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData) { @@ -1107,7 +1103,7 @@ static void ImGui_ImplVulkan_DestroyViewport(ImGuiViewport* viewport) viewport->RendererUserData = NULL; } -static void ImGui_ImplVulkan_ResizeViewport(ImGuiViewport* viewport, ImVec2 size) +static void ImGui_ImplVulkan_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData; if (data == NULL) // This is NULL for the main viewport (which is left to the user/app to handle) @@ -1116,7 +1112,7 @@ static void ImGui_ImplVulkan_ResizeViewport(ImGuiViewport* viewport, ImVec2 size ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &data->WindowData, g_Allocator, (int)size.x, (int)size.y); } -static void ImGui_ImplVulkan_RenderViewport(ImGuiViewport* viewport) +static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport) { ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData; ImGui_ImplVulkan_WindowData* wd = &data->WindowData; @@ -1160,7 +1156,7 @@ static void ImGui_ImplVulkan_RenderViewport(ImGuiViewport* viewport) } } - ImGui_ImplVulkan_RenderDrawData(wd->Frames[wd->FrameIndex].CommandBuffer, &viewport->DrawData); + ImGui_ImplVulkan_RenderDrawData(wd->Frames[wd->FrameIndex].CommandBuffer, viewport->DrawData); { ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex]; @@ -1210,18 +1206,17 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport) void ImGui_ImplVulkan_InitPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - IM_ASSERT(io.PlatformInterface.CreateVkSurface != NULL); - io.RendererInterface.CreateViewport = ImGui_ImplVulkan_CreateViewport; - io.RendererInterface.DestroyViewport = ImGui_ImplVulkan_DestroyViewport; - io.RendererInterface.ResizeViewport = ImGui_ImplVulkan_ResizeViewport; - io.RendererInterface.RenderViewport = ImGui_ImplVulkan_RenderViewport; - io.RendererInterface.SwapBuffers = ImGui_ImplVulkan_SwapBuffers; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnableViewports) + IM_ASSERT(platform_io.Platform_CreateVkSurface != NULL && "Platform needs to setup the CreateVkSurface handler."); + platform_io.Renderer_CreateWindow = ImGui_ImplVulkan_CreateWindow; + platform_io.Renderer_DestroyWindow = ImGui_ImplVulkan_DestroyWindow; + platform_io.Renderer_SetWindowSize = ImGui_ImplVulkan_SetWindowSize; + platform_io.Renderer_RenderWindow = ImGui_ImplVulkan_RenderWindow; + platform_io.Renderer_SwapBuffers = ImGui_ImplVulkan_SwapBuffers; } void ImGui_ImplVulkan_ShutdownPlatformInterface() { - ImGui::DestroyViewportsRendererData(ImGui::GetCurrentContext()); - ImGuiIO& io = ImGui::GetIO(); - memset(&io.RendererInterface, 0, sizeof(io.RendererInterface)); + ImGui::DestroyPlatformWindows(); } diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 70cb8bd92..744253eb0 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -7,10 +7,8 @@ #include #include -#include "imgui_internal.h" // FIXME-PLATFORM - // CHANGELOG -// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformInterface +// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). @@ -363,7 +361,7 @@ struct ImGuiPlatformDataWin32 ~ImGuiPlatformDataWin32() { IM_ASSERT(Hwnd == NULL); } }; -static void ImGui_ImplWin32_CreateViewport(ImGuiViewport* viewport) +static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport) { ImGuiPlatformDataWin32* data = IM_NEW(ImGuiPlatformDataWin32)(); viewport->PlatformUserData = data; @@ -393,7 +391,7 @@ static void ImGui_ImplWin32_CreateViewport(ImGuiViewport* viewport) viewport->PlatformHandle = data->Hwnd; } -static void ImGui_ImplWin32_DestroyViewport(ImGuiViewport* viewport) +static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport) { if (ImGuiPlatformDataWin32* data = (ImGuiPlatformDataWin32*)viewport->PlatformUserData) { @@ -523,16 +521,16 @@ static void ImGui_ImplWin32_InitPlatformInterface() ::RegisterClassEx(&wcex); // Register platform interface (will be coupled with a renderer interface) - ImGuiIO& io = ImGui::GetIO(); - io.PlatformInterface.CreateViewport = ImGui_ImplWin32_CreateViewport; - io.PlatformInterface.DestroyViewport = ImGui_ImplWin32_DestroyViewport; - io.PlatformInterface.ShowWindow = ImGui_ImplWin32_ShowWindow; - io.PlatformInterface.SetWindowPos = ImGui_ImplWin32_SetWindowPos; - io.PlatformInterface.GetWindowPos = ImGui_ImplWin32_GetWindowPos; - io.PlatformInterface.SetWindowSize = ImGui_ImplWin32_SetWindowSize; - io.PlatformInterface.GetWindowSize = ImGui_ImplWin32_GetWindowSize; - io.PlatformInterface.SetWindowTitle = ImGui_ImplWin32_SetWindowTitle; - io.PlatformInterface.GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Platform_CreateWindow = ImGui_ImplWin32_CreateWindow; + platform_io.Platform_DestroyWindow = ImGui_ImplWin32_DestroyWindow; + platform_io.Platform_ShowWindow = ImGui_ImplWin32_ShowWindow; + platform_io.Platform_SetWindowPos = ImGui_ImplWin32_SetWindowPos; + platform_io.Platform_GetWindowPos = ImGui_ImplWin32_GetWindowPos; + platform_io.Platform_SetWindowSize = ImGui_ImplWin32_SetWindowSize; + platform_io.Platform_GetWindowSize = ImGui_ImplWin32_GetWindowSize; + platform_io.Platform_SetWindowTitle = ImGui_ImplWin32_SetWindowTitle; + platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; // Register main window handle ImGuiViewport* main_viewport = ImGui::GetMainViewport(); @@ -544,8 +542,5 @@ static void ImGui_ImplWin32_InitPlatformInterface() static void ImGui_ImplWin32_ShutdownPlatformInterface() { - ImGuiIO& io = ImGui::GetIO(); - memset(&io.PlatformInterface, 0, sizeof(io.PlatformInterface)); - ::UnregisterClass(_T("ImGui Platform"), ::GetModuleHandle(NULL)); } diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 2ba7a0542..b8372c17a 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -106,13 +106,13 @@ int main(int, char**) } // Rendering + ImGui::Render(); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code. - ImGui::Render(); ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 69ec99a7e..b5c4f17bf 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -115,16 +115,18 @@ int main(int, char**) } // Rendering + ImGui::Render(); int display_w, display_h; glfwMakeContextCurrent(window); glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); - ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - ImGui::RenderAdditionalViewports(); + // Update and Render additional Platform Windows + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindows(); glfwMakeContextCurrent(window); glfwSwapBuffers(window); diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index f1fffcaf6..0e4c40c4e 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -131,7 +131,10 @@ int main(int, char**) glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - ImGui::RenderAdditionalViewports(); + + // Update and Render additional Platform Windows + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindows(); SDL_GL_MakeCurrent(window, gl_context); SDL_GL_SwapWindow(window); diff --git a/examples/sdl_vulkan_example/main.cpp b/examples/sdl_vulkan_example/main.cpp index 08db99ce1..4ec3083b4 100644 --- a/examples/sdl_vulkan_example/main.cpp +++ b/examples/sdl_vulkan_example/main.cpp @@ -468,7 +468,11 @@ int main(int, char**) ImGui::Render(); memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); FrameRender(wd); - ImGui::RenderAdditionalViewports(); + + // Update and Render additional Platform Windows + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindows(); + FramePresent(wd); } diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index cfcc6605f..111613f7a 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -478,7 +478,11 @@ int main(int, char**) ImGui::Render(); memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); FrameRender(wd); - ImGui::RenderAdditionalViewports(); + + // Update and Render additional Platform Windows + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindows(); + FramePresent(wd); } diff --git a/imgui.cpp b/imgui.cpp index 219f6f615..8310917e8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -739,12 +739,13 @@ static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); // Viewport const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using a constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. static inline ImRect GetViewportRect(ImGuiWindow* window) { return window->Viewport->GetRect(); } -static inline ImVec2 ConvertViewportPosToPlatformPos(const ImVec2& imgui_pos, ImGuiViewport* viewport) { return imgui_pos - viewport->Pos + viewport->PlatformPos; } +static inline ImVec2 ConvertViewportPosToPlatformPos(const ImVec2& imgui_pos, ImGuiViewport* viewport) { return imgui_pos - viewport->Pos + viewport->PlatformPos; } static inline ImVec2 ConvertPlatformPosToViewportPos(const ImVec2& platform_pos, ImGuiViewport* viewport) { return platform_pos - viewport->PlatformPos + viewport->Pos; } +static ImGuiViewportP* Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& platform_pos, const ImVec2& size); static void UpdateViewports(); static void UpdateWindowViewport(ImGuiWindow* window, bool window_pos_set_by_api); -static void SetCurrentViewport(ImGuiViewport* viewport); -static void SetWindowViewportTranslateToPreservePlatformPos(ImGuiWindow* window, ImGuiViewport* old_viewport, ImGuiViewport* new_viewport); +static void SetCurrentViewport(ImGuiViewportP* viewport); +static void SetWindowViewportTranslateToPreservePlatformPos(ImGuiWindow* window, ImGuiViewportP* old_viewport, ImGuiViewportP* new_viewport); static void ResizeViewportTranslateWindows(int viewport_idx_min, int viewport_idx_max, float pos_x_delta, int idx_delta, ImGuiViewport* viewport_to_erase); } @@ -891,9 +892,6 @@ ImGuiIO::ImGuiIO() ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; ImeWindowHandle = NULL; - memset(&PlatformInterface, 0, sizeof(PlatformInterface)); - memset(&RendererInterface, 0, sizeof(RendererInterface)); - #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS RenderDrawListsFn = NULL; #endif @@ -2659,6 +2657,12 @@ ImGuiIO& ImGui::GetIO() return GImGui->IO; } +ImGuiPlatformIO& ImGui::GetPlatformIO() +{ + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); + return GImGui->PlatformIO; +} + ImGuiStyle& ImGui::GetStyle() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); @@ -2669,13 +2673,7 @@ ImGuiStyle& ImGui::GetStyle() ImDrawData* ImGui::GetDrawData() { ImGuiContext& g = *GImGui; - return g.Viewports[0]->DrawData.Valid ? &g.Viewports[0]->DrawData : NULL; -} - -ImDrawData* ImGui::GetDrawDataForViewport(ImGuiID viewport_id) -{ - ImGuiViewport* viewport = FindViewportByID(viewport_id); - return viewport && viewport->DrawData.Valid ? &viewport->DrawData : NULL; + return g.Viewports[0]->DrawDataP.Valid ? &g.Viewports[0]->DrawDataP : NULL; } float ImGui::GetTime() @@ -3255,10 +3253,10 @@ static void ImGui::UpdateMovingWindowDropViewport(ImGuiWindow* window) ImRect mouse_viewport_rect = g.MouseViewport->GetRect(); ImVec2 window_pos_in_mouse_viewport = ConvertPlatformPosToViewportPos(ConvertViewportPosToPlatformPos(window->Pos, window->Viewport), g.MouseViewport); ImRect window_rect_in_mouse_viewport = ImRect(window_pos_in_mouse_viewport, window_pos_in_mouse_viewport + window->Size); - if ((g.MouseViewport->Flags & ImGuiViewportFlags_HostOtherWindows) && mouse_viewport_rect.Contains(window_rect_in_mouse_viewport)) + if ((g.MouseViewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && mouse_viewport_rect.Contains(window_rect_in_mouse_viewport)) { // Drop on an existing viewport - ImGuiViewport* old_viewport = window->Viewport; + ImGuiViewportP* old_viewport = window->Viewport; SetWindowViewportTranslateToPreservePlatformPos(window, window->Viewport, g.MouseViewport); // Our current scheme allow any window to land on a viewport, so when that viewport merges, move other windows as well @@ -3272,7 +3270,7 @@ static void ImGui::UpdateMovingWindowDropViewport(ImGuiWindow* window) { // Create new viewport ImVec2 platform_pos = ConvertViewportPosToPlatformPos(window->Pos, window->Viewport); - ImGuiViewport* viewport = Viewport(window, window->ID, 0, platform_pos, window->Size); + ImGuiViewportP* viewport = Viewport(window, window->ID, 0, platform_pos, window->Size); SetWindowViewportTranslateToPreservePlatformPos(window, window->Viewport, viewport); } } @@ -3326,13 +3324,13 @@ static void ImGui::UpdateMovingWindow() // If the back-end doesn't set MouseLastHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs, we do a search ourselves. // This search won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window. -static ImGuiViewport* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos) +static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos) { ImGuiContext& g = *GImGui; - ImGuiViewport* best_candidate = NULL; + ImGuiViewportP* best_candidate = NULL; for (int n = 0; n < g.Viewports.Size; n++) { - ImGuiViewport* viewport = g.Viewports[n]; + ImGuiViewportP* viewport = g.Viewports[n]; ImRect platform_rect = ImRect(viewport->PlatformPos, viewport->PlatformPos + viewport->Size); if (!(viewport->Flags & ImGuiViewportFlags_NoInputs) && platform_rect.Contains(mouse_platform_pos)) if (best_candidate == NULL || best_candidate->LastFrameAsRefViewport < viewport->LastFrameAsRefViewport) @@ -3344,33 +3342,31 @@ static ImGuiViewport* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mo static void ImGui::UpdateViewports() { ImGuiContext& g = *GImGui; + IM_ASSERT(g.PlatformData.Viewports.Size <= g.Viewports.Size); // Mouse handling: latch the expected mouse OS position (if any) before processing viewport erasure - ImGuiViewport* viewport_ref = g.IO.MousePosViewport ? FindViewportByID(g.IO.MousePosViewport) : g.Viewports[0]; + ImGuiViewportP* viewport_ref = g.IO.MousePosViewport ? FindViewportByID(g.IO.MousePosViewport) : g.Viewports[0]; const ImVec2 mouse_platform_pos = ConvertViewportPosToPlatformPos(g.IO.MousePos, viewport_ref); g.CurrentViewport = NULL; for (int n = 0; n < g.Viewports.Size; n++) { // Erase unused viewports - ImGuiViewport* viewport = g.Viewports[n]; + ImGuiViewportP* viewport = g.Viewports[n]; IM_ASSERT(viewport->Idx == n); if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2) { // Translate windows like if we were resizing the viewport to be zero-width ResizeViewportTranslateWindows(n + 1, g.Viewports.Size, viewport->Pos.x - viewport->GetNextX(), -1, viewport); - if (g.IO.RendererInterface.DestroyViewport) - g.IO.RendererInterface.DestroyViewport(viewport); - if (g.IO.PlatformInterface.DestroyViewport) - g.IO.PlatformInterface.DestroyViewport(viewport); - viewport->PlatformUserData = viewport->PlatformHandle = viewport->RendererUserData = NULL; g.Viewports.erase(g.Viewports.Data + n); // Destroy if (viewport == viewport_ref) viewport_ref = NULL; if (viewport == g.MouseViewport) g.MouseViewport = NULL; if (viewport == g.MouseLastHoveredViewport) g.MouseLastHoveredViewport = NULL; + IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL); + IM_ASSERT(g.PlatformData.Viewports.contains(viewport) == false); IM_DELETE(viewport); n--; continue; @@ -3384,16 +3380,18 @@ static void ImGui::UpdateViewports() ResizeViewportTranslateWindows(viewport->Idx + 1, g.Viewports.Size, dx, 0, NULL); } - // Apply Platform Size to ImGui Size if requested - // We do it here instead of UpdatePlatformWindows() to allow the platform back-end to set PlatformRequestResize early - // (e.g. in their own message handler before NewFrame) and not have a frame of lag with it. + // Apply Position and Size (from Platform Window to ImGui) if requested + // We do it here early in the frame instead of UpdatePlatformWindows() to allow the platform back-end to set PlatformRequestResize early + // (e.g. in their own message handler before NewFrame) and not have a frame of lag. + if (viewport->PlatformRequestMove) + viewport->PlatformPos = g.PlatformIO.Platform_GetWindowPos(viewport); if (viewport->PlatformRequestResize) - viewport->Size = g.IO.PlatformInterface.GetWindowSize(viewport); + viewport->Size = g.PlatformIO.Platform_GetWindowSize(viewport); // Update DPI Scale float new_dpi_scale; - if (g.IO.PlatformInterface.GetWindowDpiScale) - new_dpi_scale = g.IO.PlatformInterface.GetWindowDpiScale(viewport); + if (g.PlatformIO.Platform_GetWindowDpiScale) + new_dpi_scale = g.PlatformIO.Platform_GetWindowDpiScale(viewport); else new_dpi_scale = (viewport->DpiScale != 0.0f) ? viewport->DpiScale : 1.0f; if (viewport->DpiScale != 0.0f && new_dpi_scale != viewport->DpiScale) @@ -3402,7 +3400,7 @@ static void ImGui::UpdateViewports() if (g.IO.ConfigFlags & ImGuiConfigFlags_EnableDpiScaleViewports) ScaleWindowsInViewport(viewport, scale_factor); //if (viewport == GetMainViewport()) - // g.IO.PlatformInterface.SetWindowSize(viewport, viewport->Size * scale_factor); + // g.PlatformInterface.SetWindowSize(viewport, viewport->Size * scale_factor); // FIXME-DPI: We need to preserve our pivots //if (g.MovingWindow) @@ -3412,12 +3410,12 @@ static void ImGui::UpdateViewports() } // Update main viewport with current size (and OS window position, if known) - ImGuiViewport* main_viewport = g.Viewports[0]; + ImGuiViewportP* main_viewport = g.Viewports[0]; IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID); ImVec2 main_viewport_platform_pos = ImVec2(0.0f, 0.0f); if ((g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) - main_viewport_platform_pos = g.IO.PlatformInterface.GetWindowPos(main_viewport); - Viewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, ImGuiViewportFlags_MainViewport | ImGuiViewportFlags_HostOtherWindows, main_viewport_platform_pos, g.IO.DisplaySize); + main_viewport_platform_pos = g.PlatformIO.Platform_GetWindowPos(main_viewport); + Viewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, ImGuiViewportFlags_CanHostOtherWindows, main_viewport_platform_pos, g.IO.DisplaySize); if (!(g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) { @@ -3426,7 +3424,7 @@ static void ImGui::UpdateViewports() } // Mouse handling: decide on the actual mouse viewport for this frame between the active/focused viewport and the hovered viewport. - ImGuiViewport* viewport_hovered = NULL; + ImGuiViewportP* viewport_hovered = NULL; if (g.IO.ConfigFlags & ImGuiConfigFlags_PlatformHasMouseHoveredViewport) { viewport_hovered = g.IO.MouseHoveredViewport ? FindViewportByID(g.IO.MouseHoveredViewport) : NULL; @@ -3474,52 +3472,75 @@ static void ImGui::UpdateViewports() IM_ASSERT(g.MouseViewport != NULL); } -static void UpdatePlatformWindows() +ImGuiPlatformData* ImGui::GetPlatformData() +{ + return &GImGui->PlatformData; +} + +void ImGui::UpdatePlatformWindows() { - // Create/resize windows ImGuiContext& g = *GImGui; - for (int i = 0; i < g.Viewports.Size; i++) + IM_ASSERT(g.FrameCountEnded == g.FrameCount && "Forgot to call Render() or EndFrame() before UpdatePlatformWindows()?"); + IM_ASSERT(g.FrameCountPlatformEnded < g.FrameCount); + g.FrameCountPlatformEnded = g.FrameCount; + + g.PlatformData.MainViewport = g.Viewports[0]; + g.PlatformData.Viewports.resize(0); + g.PlatformData.Viewports.push_back(g.Viewports[0]); + if (!(g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) + return; + + // Create/resize/destroy platform windows and update the list that the user can process + for (int i = 1; i < g.Viewports.Size; i++) { - ImGuiViewport* viewport = g.Viewports[i]; - if ((viewport->Flags & ImGuiViewportFlags_MainViewport) || (viewport->LastFrameActive < g.FrameCount)) + ImGuiViewportP* viewport = g.Viewports[i]; + if (viewport->LastFrameActive < g.FrameCount) + { + if (viewport->LastFrameActive < g.FrameCount - 1) + { + if (g.PlatformIO.Renderer_DestroyWindow) + g.PlatformIO.Renderer_DestroyWindow(viewport); + if (g.PlatformIO.Platform_DestroyWindow) + g.PlatformIO.Platform_DestroyWindow(viewport); + IM_ASSERT(viewport->RendererUserData == NULL); + IM_ASSERT(viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL); + } continue; + } + + g.PlatformData.Viewports.push_back(viewport); IM_ASSERT(viewport->Window != NULL); - if (viewport->PlatformRequestMove) - viewport->PlatformPos = g.IO.PlatformInterface.GetWindowPos(viewport); - - bool is_new_window = viewport->PlatformHandle == NULL && viewport->PlatformUserData == NULL && viewport->RendererUserData == NULL; + bool is_new_window = (viewport->PlatformHandle == NULL && viewport->PlatformUserData == NULL && viewport->RendererUserData == NULL); if (is_new_window && viewport->PlatformHandle == NULL && viewport->PlatformUserData == NULL) + g.PlatformIO.Platform_CreateWindow(viewport); + if (is_new_window && viewport->RendererUserData == NULL && g.PlatformIO.Renderer_CreateWindow != NULL) { - g.IO.PlatformInterface.CreateViewport(viewport); - } - if (is_new_window && viewport->RendererUserData == NULL && g.IO.RendererInterface.CreateViewport != NULL) - { - g.IO.RendererInterface.CreateViewport(viewport); + g.PlatformIO.Renderer_CreateWindow(viewport); viewport->RendererLastSize = viewport->Size; } - // Update Pos/Size for Platform + // Apply Position and Size (from ImGui to Platform Window) if (!viewport->PlatformRequestMove) - g.IO.PlatformInterface.SetWindowPos(viewport, viewport->PlatformPos); + g.PlatformIO.Platform_SetWindowPos(viewport, viewport->PlatformPos); if (!viewport->PlatformRequestResize) - g.IO.PlatformInterface.SetWindowSize(viewport, viewport->Size); + g.PlatformIO.Platform_SetWindowSize(viewport, viewport->Size); // Update Size for Renderer - if (g.IO.RendererInterface.ResizeViewport && (viewport->RendererLastSize.x != viewport->Size.x || viewport->RendererLastSize.y != viewport->Size.y)) - g.IO.RendererInterface.ResizeViewport(viewport, viewport->Size); + if (g.PlatformIO.Renderer_SetWindowSize && (viewport->RendererLastSize.x != viewport->Size.x || viewport->RendererLastSize.y != viewport->Size.y)) + g.PlatformIO.Renderer_SetWindowSize(viewport, viewport->Size); viewport->RendererLastSize = viewport->Size; // Update title bar const char* title_begin = viewport->Window->Name; const char* title_end = ImGui::FindRenderedTextEnd(title_begin); const ImGuiID title_hash = ImHash(title_begin, (int)(title_end - title_begin)); - if (viewport->LastNameHash != title_hash ) + if (viewport->LastNameHash != title_hash) { viewport->LastNameHash = title_hash; char* title_displayed = ImStrdup(viewport->Window->Name); title_displayed[title_end - title_begin] = 0; - g.IO.PlatformInterface.SetWindowTitle(viewport, title_displayed); + g.PlatformIO.Platform_SetWindowTitle(viewport, title_displayed); ImGui::MemFree(title_displayed); } @@ -3528,43 +3549,47 @@ static void UpdatePlatformWindows() { if (g.FrameCount < 2) viewport->Flags |= ImGuiViewportFlags_NoFocusOnAppearing; - g.IO.PlatformInterface.ShowWindow(viewport); + g.PlatformIO.Platform_ShowWindow(viewport); } // Clear request flags - viewport->PlatformRequestClose = false; - viewport->PlatformRequestMove = false; - viewport->PlatformRequestResize = false; + viewport->PlatformRequestClose = viewport->PlatformRequestMove = viewport->PlatformRequestResize = false; } } -void ImGui::RenderAdditionalViewports() +// This is a default/basic function for performing the rendering/swap of multiple platform windows. +// Custom renderers may prefer to not call this function at all, and instead iterate the platform data and handle rendering/sync themselves. +// The Render/Swap functions stored in ImGuiPlatformInterface are merely here to allow for this helper to exist, but you can do it yourself: +// +// ImGuiPlatformData* data = ImGui::GetPlatformData(); +// for (int i = 1; i < data->Viewports.Size; i++) +// MyRenderFunction(data->Viewports[i], my_args); +// for (int i = 1; i < data->Viewports.Size; i++) +// MySwapBufferFunction(data->Viewports[i], my_args); +// +// Note how we intentionally skip the main viewport (index 0) which is generally rendered as part of our main application. +void ImGui::RenderPlatformWindows() { - ImGuiContext& g = *GImGui; - if (!(g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) + if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnableViewports)) return; - - for (int i = 0; i < g.Viewports.Size; i++) - { - ImGuiViewport* viewport = g.Viewports[i]; - if ((viewport->Flags & ImGuiViewportFlags_MainViewport) || (viewport->LastFrameActive < g.FrameCount)) - continue; - if (g.IO.PlatformInterface.RenderViewport) - g.IO.PlatformInterface.RenderViewport(viewport); - if (g.IO.RendererInterface.RenderViewport) - g.IO.RendererInterface.RenderViewport(viewport); - } - // Swap - for (int i = 0; i < g.Viewports.Size; i++) + ImGuiPlatformData* data = ImGui::GetPlatformData(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + for (int i = 1; i < data->Viewports.Size; i++) { - ImGuiViewport* viewport = g.Viewports[i]; - if ((viewport->Flags & ImGuiViewportFlags_MainViewport) || (viewport->LastFrameActive < g.FrameCount)) - continue; - if (g.IO.PlatformInterface.SwapBuffers) - g.IO.PlatformInterface.SwapBuffers(viewport); - if (g.IO.RendererInterface.SwapBuffers) - g.IO.RendererInterface.SwapBuffers(viewport); + ImGuiViewport* viewport = data->Viewports[i]; + if (platform_io.Platform_RenderWindow) + platform_io.Platform_RenderWindow(viewport); + if (platform_io.Renderer_RenderWindow) + platform_io.Renderer_RenderWindow(viewport); + } + for (int i = 1; i < data->Viewports.Size; i++) + { + ImGuiViewport* viewport = data->Viewports[i]; + if (platform_io.Platform_SwapBuffers) + platform_io.Platform_SwapBuffers(viewport); + if (platform_io.Renderer_SwapBuffers) + platform_io.Renderer_SwapBuffers(viewport); } } @@ -3574,7 +3599,7 @@ void ImGui::NewFrame() ImGuiContext& g = *GImGui; // Check user data - // (We pass an error message in the assert expression as a trick to get it visible to programmers who are not using a debugger, as most assert handlers display their argument) + // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) IM_ASSERT(g.Initialized); IM_ASSERT(g.IO.DeltaTime >= 0.0f && "Need a positive DeltaTime (zero is tolerated but will cause some timing issues)"); IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value"); @@ -3586,21 +3611,22 @@ void ImGui::NewFrame() for (int n = 0; n < ImGuiKey_COUNT; n++) IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); - // Do a simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was super recently added in 1.60 WIP) + // Perform simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP) if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); + // Perform simple checks for multi-viewport and platform windows support if (g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports) { if ((g.IO.ConfigFlags & ImGuiConfigFlags_PlatformHasViewports) && (g.IO.ConfigFlags & ImGuiConfigFlags_RendererHasViewports)) { + IM_ASSERT(g.FrameCount == 0 || g.FrameCountPlatformEnded == g.FrameCount && "Forgot to call UpdatePlatformWindows() at the end of the previous frame?"); + IM_ASSERT(g.PlatformIO.Platform_CreateWindow != NULL && "Platform init didn't install handlers?"); + IM_ASSERT(g.PlatformIO.Platform_DestroyWindow != NULL && "Platform init didn't install handlers?"); + IM_ASSERT(g.Viewports[0]->PlatformUserData != NULL && "Platform init didn't setup main viewport."); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS IM_ASSERT(g.IO.RenderDrawListsFn == NULL); // Call ImGui::Render() then pass ImGui::GetDrawData() yourself to your render function! #endif - IM_ASSERT(g.IO.PlatformInterface.CreateViewport != NULL); - IM_ASSERT(g.IO.PlatformInterface.DestroyViewport != NULL); - //IM_ASSERT(g.IO.PlatformInterface.RenderViewport != NULL || g.IO.RendererInterface.RenderViewport != NULL); // Missing rendering function - IM_ASSERT(g.Viewports[0]->PlatformUserData != NULL); // Platform init function didn't setup main viewport } else { @@ -3641,7 +3667,10 @@ void ImGui::NewFrame() // Mark rendering data as invalid to prevent user who may have a handle on it to use it for (int n = 0; n < g.Viewports.Size; n++) - g.Viewports[n]->DrawData.Clear(); + { + g.Viewports[n]->DrawData = NULL; + g.Viewports[n]->DrawDataP.Clear(); + } // Clear reference to active widget if the widget isn't alive anymore if (!g.HoveredIdPreviousFrame) @@ -3955,24 +3984,23 @@ void ImGui::Initialize(ImGuiContext* context) g.SettingsHandlers.push_front(ini_handler); // Create default viewport - ImGuiViewport* viewport = IM_NEW(ImGuiViewport)(IMGUI_VIEWPORT_DEFAULT_ID, 0); + ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); + viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID; + viewport->Idx = 0; g.Viewports.push_back(viewport); g.Initialized = true; } -void ImGui::DestroyViewportsPlaformData(ImGuiContext* context) +void ImGui::DestroyPlatformWindows() { - if (context->IO.PlatformInterface.DestroyViewport) - for (int i = 0; i < context->Viewports.Size; i++) - context->IO.PlatformInterface.DestroyViewport(context->Viewports[i]); -} - -void ImGui::DestroyViewportsRendererData(ImGuiContext* context) -{ - if (context->IO.RendererInterface.DestroyViewport) - for (int i = 0; i < context->Viewports.Size; i++) - context->IO.RendererInterface.DestroyViewport(context->Viewports[i]); + ImGuiContext& g = *GImGui; + if (g.PlatformIO.Renderer_DestroyWindow) + for (int i = 0; i < g.Viewports.Size; i++) + g.PlatformIO.Renderer_DestroyWindow(g.Viewports[i]); + if (g.PlatformIO.Platform_DestroyWindow) + for (int i = 0; i < g.Viewports.Size; i++) + g.PlatformIO.Platform_DestroyWindow(g.Viewports[i]); } // This function is merely here to free heap allocations. @@ -3990,6 +4018,12 @@ void ImGui::Shutdown(ImGuiContext* context) SaveIniSettingsToDisk(g.IO.IniFilename); + // Destroy platform windows + ImGuiContext* backup_context = ImGui::GetCurrentContext(); + SetCurrentContext(context); + DestroyPlatformWindows(); + SetCurrentContext(backup_context); + // Clear everything else for (int i = 0; i < g.Windows.Size; i++) IM_DELETE(g.Windows[i]); @@ -4011,14 +4045,8 @@ void ImGui::Shutdown(ImGuiContext* context) g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); g.CurrentViewport = g.MouseViewport = g.MouseLastViewport = g.MouseLastHoveredViewport = NULL; - DestroyViewportsPlaformData(context); - DestroyViewportsRendererData(context); for (int i = 0; i < g.Viewports.Size; i++) - { - ImGuiViewport* viewport = g.Viewports[i]; - viewport->PlatformUserData = viewport->PlatformHandle = viewport->RendererUserData = NULL; - IM_DELETE(viewport); - } + IM_DELETE(g.Viewports[i]); g.Viewports.clear(); g.OverlayDrawList.ClearFreeMemory(); g.PrivateClipboard.clear(); @@ -4291,18 +4319,20 @@ void ImDrawDataBuilder::FlattenIntoSingleLayer() } } -static void SetupViewportDrawData(ImGuiViewport* viewport, ImVector* draw_lists) +static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector* draw_lists) { - viewport->DrawData.Valid = true; - viewport->DrawData.CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; - viewport->DrawData.CmdListsCount = draw_lists->Size; - viewport->DrawData.TotalVtxCount = viewport->DrawData.TotalIdxCount = 0; - viewport->DrawData.DisplayPos = viewport->Pos; - viewport->DrawData.DisplaySize = viewport->Size; + ImDrawData* draw_data = &viewport->DrawDataP; + viewport->DrawData = draw_data; // Make publicly accessible + draw_data->Valid = true; + draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; + draw_data->CmdListsCount = draw_lists->Size; + draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; + draw_data->DisplayPos = viewport->Pos; + draw_data->DisplaySize = viewport->Size; for (int n = 0; n < draw_lists->Size; n++) { - viewport->DrawData.TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size; - viewport->DrawData.TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size; + draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size; + draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size; } } @@ -4412,9 +4442,6 @@ void ImGui::EndFrame() memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); g.FrameCountEnded = g.FrameCount; - - if (g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports) - UpdatePlatformWindows(); } void ImGui::Render() @@ -4461,22 +4488,28 @@ void ImGui::Render() g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0; for (int n = 0; n < g.Viewports.Size; n++) { - ImGuiViewport* viewport = g.Viewports[n]; + ImGuiViewportP* viewport = g.Viewports[n]; viewport->DrawDataBuilder.FlattenIntoSingleLayer(); AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], &g.OverlayDrawList); SetupViewportDrawData(viewport, &viewport->DrawDataBuilder.Layers[0]); - g.IO.MetricsRenderVertices += viewport->DrawData.TotalVtxCount; - g.IO.MetricsRenderIndices += viewport->DrawData.TotalIdxCount; + g.IO.MetricsRenderVertices += viewport->DrawData->TotalVtxCount; + g.IO.MetricsRenderIndices += viewport->DrawData->TotalIdxCount; } // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - if (g.Viewports[0]->DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) - g.IO.RenderDrawListsFn(&g.Viewports[0]->DrawData); + if (g.Viewports[0]->DrawData->CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) + g.IO.RenderDrawListsFn(g.Viewports[0]->DrawData); #endif } -ImGuiViewport* ImGui::FindViewportByID(ImGuiID id) +ImGuiViewport* ImGui::GetMainViewport() +{ + ImGuiContext& g = *GImGui; + return g.Viewports[0]; +} + +ImGuiViewportP* ImGui::FindViewportByID(ImGuiID id) { ImGuiContext& g = *GImGui; for (int n = 0; n < g.Viewports.Size; n++) @@ -4531,9 +4564,9 @@ static void ImGui::ResizeViewportTranslateWindows(int viewport_idx_min, int view } } -void ImGui::SetCurrentViewport(ImGuiViewport* viewport) +void ImGui::SetCurrentViewport(ImGuiViewportP* viewport) { - // Notify platform interface of viewport changes + // Notify platform layer of viewport changes // FIXME-DPI: This is only currently used for experimenting with handling of multiple DPI ImGuiContext& g = *GImGui; if (viewport) @@ -4541,16 +4574,16 @@ void ImGui::SetCurrentViewport(ImGuiViewport* viewport) if (g.CurrentViewport == viewport) return; g.CurrentViewport = viewport; - if (g.CurrentViewport && g.IO.PlatformInterface.ChangedViewport) - g.IO.PlatformInterface.ChangedViewport(g.CurrentViewport); + if (g.CurrentViewport && g.PlatformIO.Platform_OnChangedViewport) + g.PlatformIO.Platform_OnChangedViewport(g.CurrentViewport); } -ImGuiViewport* ImGui::Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& platform_pos, const ImVec2& size) +ImGuiViewportP* ImGui::Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& platform_pos, const ImVec2& size) { ImGuiContext& g = *GImGui; IM_ASSERT(id != 0); - ImGuiViewport* viewport = FindViewportByID(id); + ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id); if (viewport) { // We defer translating windows to the beginning of the frame. @@ -4560,7 +4593,9 @@ ImGuiViewport* ImGui::Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFla else { // New viewport - viewport = IM_NEW(ImGuiViewport)(id, g.Viewports.Size); + viewport = IM_NEW(ImGuiViewportP)(); + viewport->ID = id; + viewport->Idx = g.Viewports.Size; viewport->Pos = ImVec2(g.Viewports.back()->GetNextX(), 0.0f); viewport->Size = size; g.Viewports.push_back(viewport); @@ -4573,8 +4608,8 @@ ImGuiViewport* ImGui::Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFla viewport->LastFrameActive = g.FrameCount; // Request an initial DpiScale before the OS platform window creation - if (g.IO.PlatformInterface.GetWindowDpiScale) - viewport->DpiScale = g.IO.PlatformInterface.GetWindowDpiScale(viewport); + if (g.PlatformIO.Platform_GetWindowDpiScale) + viewport->DpiScale = g.PlatformIO.Platform_GetWindowDpiScale(viewport); return viewport; } @@ -5922,7 +5957,7 @@ static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& co *out_size = size_constrained; } -static void ImGui::SetWindowViewportTranslateToPreservePlatformPos(ImGuiWindow* window, ImGuiViewport* prev_viewport, ImGuiViewport* curr_viewport) +static void ImGui::SetWindowViewportTranslateToPreservePlatformPos(ImGuiWindow* window, ImGuiViewportP* prev_viewport, ImGuiViewportP* curr_viewport) { if (prev_viewport == curr_viewport) return; @@ -5948,8 +5983,8 @@ static void ImGui::UpdateWindowViewport(ImGuiWindow* window, bool window_pos_set ImGuiWindowFlags flags = window->Flags; (void)window_pos_set_by_api; - // Restore main viewport if multi viewports are not supported by the back-end - ImGuiViewport* main_viewport = g.Viewports[0]; + // Restore main viewport if multi-viewport is not supported by the back-end + ImGuiViewportP* main_viewport = g.Viewports[0]; if (!(g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) { window->Viewport = main_viewport; @@ -5976,13 +6011,13 @@ static void ImGui::UpdateWindowViewport(ImGuiWindow* window, bool window_pos_set else if (window_follow_mouse_viewport && IsMousePosValid()) { // Calculate mouse position in OS/platform coordinates - ImGuiViewport* current_viewport = window->Viewport; + ImGuiViewportP* current_viewport = window->Viewport; if (!window_is_mouse_tooltip && !current_viewport->GetRect().Contains(window->Rect())) { // Create an undecorated, temporary OS/platform window ImVec2 platform_pos = ConvertViewportPosToPlatformPos(g.IO.MousePos - g.ActiveIdClickOffset, g.MouseViewport); ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs; - ImGuiViewport* viewport = Viewport(window, window->ID, viewport_flags, platform_pos, window->Size); + ImGuiViewportP* viewport = Viewport(window, window->ID, viewport_flags, platform_pos, window->Size); window->Flags |= ImGuiWindowFlags_FullViewport; window->Viewport = viewport; created_viewport = true; @@ -6021,7 +6056,7 @@ static void ImGui::UpdateWindowViewport(ImGuiWindow* window, bool window_pos_set { if (window->ViewportPlatformPos.x != FLT_MAX && window->ViewportPlatformPos.y != FLT_MAX) { - ImGuiViewport* viewport = Viewport(window, window->ID, ImGuiViewportFlags_NoDecoration, window->ViewportPlatformPos, window->Size); + ImGuiViewportP* viewport = Viewport(window, window->ID, ImGuiViewportFlags_NoDecoration, window->ViewportPlatformPos, window->Size); window->Flags |= ImGuiWindowFlags_FullViewport; window->Viewport = viewport; created_viewport = true; @@ -6352,7 +6387,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetCurrentWindow(window); flags = window->Flags; - if (p_open != NULL && window->Viewport->PlatformRequestClose && !(window->Viewport->Flags & ImGuiViewportFlags_MainViewport)) + if (p_open != NULL && window->Viewport->PlatformRequestClose && window->Viewport != GetMainViewport()) { window->Viewport->PlatformRequestClose = false; *p_open = false; @@ -6360,7 +6395,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Lock window rounding, border size and padding for the frame (so that altering them doesn't cause inconsistencies) window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding; - if (window->Viewport != GetMainViewport()) + if (window->Flags & ImGuiWindowFlags_FullViewport) window->WindowRounding = 0.0f; window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; window->WindowPadding = style.WindowPadding; @@ -13827,7 +13862,7 @@ static void ScaleWindow(ImGuiWindow* window, float scale) } // Scale all windows (position, size). Use when e.g. changing DPI. (This is a lossy operation!) -void ImGui::ScaleWindowsInViewport(ImGuiViewport* viewport, float scale) +void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale) { ImGuiContext& g = *GImGui; if (g.IO.MousePosViewport == viewport->ID) @@ -13857,7 +13892,7 @@ void ImGui::ShowViewportThumbnails() ImVec2 p = window->DC.CursorPos; for (int n = 0; n < g.Viewports.Size; n++) { - ImGuiViewport* viewport = g.Viewports[n]; + ImGuiViewportP* viewport = g.Viewports[n]; if (n > 0) ImGui::SameLine(); ImRect bb(p + (viewport->Pos) * SCALE, p + (viewport->Pos + viewport->Size) * SCALE); @@ -14015,7 +14050,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); for (int i = 0; i < g.Viewports.Size; i++) { - ImGuiViewport* viewport = g.Viewports[i]; + ImGuiViewportP* viewport = g.Viewports[i]; ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once); if (ImGui::TreeNode((void*)(intptr_t)viewport->ID, "Viewport #%d, ID: 0x%08X, DrawLists: %d, Size: (%.0f,%.0f)", i, viewport->ID, viewport->DrawDataBuilder.GetDrawListCount(), viewport->Size.x, viewport->Size.y)) { diff --git a/imgui.h b/imgui.h index e28a0f193..a7415342a 100644 --- a/imgui.h +++ b/imgui.h @@ -73,6 +73,8 @@ struct ImGuiSizeCallbackData; // Structure used to constraint window size struct ImGuiListClipper; // Helper to manually clip large list of items struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiViewport; // Viewport (generally ~1 per window to output to at the OS level. Need per-platform support to use multiple viewports) +struct ImGuiPlatformIO; // Multi-viewport support: interface for Platform/Renderer back-ends +struct ImGuiPlatformData; // Multi-viewport support: list of viewports to render struct ImGuiContext; // ImGui context (opaque) #ifndef ImTextureID @@ -103,6 +105,7 @@ typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ +typedef int ImGuiViewportFlags; // flags: for ImGuiViewport // enum ImGuiViewportFlags_ typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); @@ -150,9 +153,7 @@ namespace ImGui IMGUI_API ImGuiStyle& GetStyle(); IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data. (Obsolete: optionally call io.RenderDrawListsFn if set. Nowadays, prefer calling your render function yourself.) - IMGUI_API void RenderAdditionalViewports(); IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. (Obsolete: this used to be passed to your io.RenderDrawListsFn() function.) - IMGUI_API ImDrawData* GetDrawDataForViewport(ImGuiID viewport_id);// ImDrawData filtered to hold only the ImDrawList covering a given viewport. valid after Render() and until the next call to NewFrame() IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! // Demo, Debug, Information @@ -543,6 +544,15 @@ namespace ImGui IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); + // (Optional) Platform interface for multi-viewport support + IMGUI_API ImGuiPlatformIO& GetPlatformIO(); // Platform/Renderer functions. + IMGUI_API ImGuiPlatformData* GetPlatformData(); // List of viewports. + IMGUI_API ImGuiViewport* GetMainViewport(); // GetPlatformData()->MainViewport + IMGUI_API void UpdatePlatformWindows(); // Call in main loop. Create/Destroy/Resize platform windows so there's one for each viewport + IMGUI_API void RenderPlatformWindows(); // Call in main loop. Call RenderWindow/SwapBuffers from the ImGuiPlatformIO structure. May be reimplemented by user. + IMGUI_API void DestroyPlatformWindows(); // Call in back-end shutdown. + IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); + // Memory Utilities // All those functions are not reliant on the current context. // If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again. @@ -958,39 +968,6 @@ enum ImGuiCond_ #endif }; -// (Optional) Setup required only if (io.ConfigFlags & ImGuiConfigFlags_EnableMultiViewport) is enabled -struct ImGuiPlatformInterface -{ - void (*CreateViewport)(ImGuiViewport* viewport); - void (*DestroyViewport)(ImGuiViewport* viewport); - void (*ShowWindow)(ImGuiViewport* viewport); - void (*SetWindowPos)(ImGuiViewport* viewport, ImVec2 pos); - ImVec2 (*GetWindowPos)(ImGuiViewport* viewport); - void (*SetWindowSize)(ImGuiViewport* viewport, ImVec2 size); - ImVec2 (*GetWindowSize)(ImGuiViewport* viewport); - void (*SetWindowTitle)(ImGuiViewport* viewport, const char* name); - void (*SetWindowAlpha)(ImGuiViewport* viewport, float alpha); - void (*RenderViewport)(ImGuiViewport* viewport); - void (*SwapBuffers)(ImGuiViewport* viewport); - - // FIXME-VIEWPORT: Experimenting with back-end abstraction. This probably shouldn't stay as is. - int (*CreateVkSurface)(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface); - - // FIXME-DPI - float (*GetWindowDpiScale)(ImGuiViewport* viewport); // (Optional) - void (*ChangedViewport)(ImGuiViewport* viewport); // (Optional) Called during Begin() every time the viewport we are outputting into changes (viewport = next viewport) -}; - -// (Optional) Setup required only if (io.ConfigFlags & ImGuiConfigFlags_EnableMultiViewport) is enabled -struct ImGuiRendererInterface -{ - void (*CreateViewport)(ImGuiViewport* viewport); - void (*DestroyViewport)(ImGuiViewport* viewport); - void (*ResizeViewport)(ImGuiViewport* viewport, ImVec2 size); - void (*RenderViewport)(ImGuiViewport* viewport); // Setup render output, clear targets, call Renderer_RenderDrawData - void (*SwapBuffers)(ImGuiViewport* viewport); // Call Present/SwapBuffers -}; - // You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame(). // During the frame, use ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors. struct ImGuiStyle @@ -1072,10 +1049,6 @@ struct ImGuiIO void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; - // Optional: platform interface to use multiple viewports - ImGuiPlatformInterface PlatformInterface; - ImGuiRendererInterface RendererInterface; - // Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows) // (default to use native imm32 api on Windows) void (*ImeSetInputScreenPosFn)(int x, int y); @@ -1883,6 +1856,86 @@ struct ImFont #endif }; +//----------------------------------------------------------------------------- +// [BETA] Platform interface for multi-viewport support +// - completely optional, for advanced users! +// - this is used for back-ends aiming to support the seamless creation of multiple viewport (= multiple Platform/OS windows) +// dear imgui manages the viewports, and the back-end create one Platform/OS windows for each secondary viewport. +// - if you are new to dear imgui and trying to integrate it into your engine, you should probably ignore this for now. +//----------------------------------------------------------------------------- + +// (Optional) Setup required only if (io.ConfigFlags & ImGuiConfigFlags_EnableViewports) is enabled +// This is designed so we can mix and match two imgui_impl_xxxx files, one for the Platform (~ Windowing), one for Renderer. +// Custom engine back-ends will often provide both Platform and Renderer interfaces and thus may not need to use all functions. +// Platform functions are typically called before their Renderer counterpart, apart from Destroy which are called the other way. +struct ImGuiPlatformIO +{ + // Platform (e.g. Win32, GLFW, SDL2) + void (*Platform_CreateWindow)(ImGuiViewport* vp); // Create a new platform window for the given viewport + void (*Platform_DestroyWindow)(ImGuiViewport* vp); + void (*Platform_ShowWindow)(ImGuiViewport* vp); // Newly created windows are initially hidden so we have a chance to call SetWindowPos/Size/Title on them. + void (*Platform_SetWindowPos)(ImGuiViewport* vp, ImVec2 pos); + ImVec2 (*Platform_GetWindowPos)(ImGuiViewport* vp); + void (*Platform_SetWindowSize)(ImGuiViewport* vp, ImVec2 size); + ImVec2 (*Platform_GetWindowSize)(ImGuiViewport* vp); + void (*Platform_SetWindowTitle)(ImGuiViewport* vp, const char* title); + void (*Platform_SetWindowAlpha)(ImGuiViewport* vp, float alpha); // (Optional) Setup window transparency + void (*Platform_RenderWindow)(ImGuiViewport* vp); // (Optional) Setup for render (platform side) + void (*Platform_SwapBuffers)(ImGuiViewport* vp); // (Optional) Call Present/SwapBuffers (platform side) + float (*Platform_GetWindowDpiScale)(ImGuiViewport* vp); // (Optional) DPI handling: Return DPI scale for this viewport. 1.0f = 96 DPI. (FIXME-DPI) + void (*Platform_OnChangedViewport)(ImGuiViewport* vp); // (Optional) DPI handling: Called during Begin() every time the viewport we are outputting into changes, so back-end has a chance to swap fonts to adjust style. + int (*Platform_CreateVkSurface)(ImGuiViewport* vp, ImU64 vk_inst, const void* vk_allocators, ImU64* out_vk_surface); // (Optional) For Renderer to call into Platform code + + // Renderer (e.g. DirectX, OpenGL3, Vulkan) + void (*Renderer_CreateWindow)(ImGuiViewport* vp); // Create swap chains, frame buffers etc. + void (*Renderer_DestroyWindow)(ImGuiViewport* vp); + void (*Renderer_SetWindowSize)(ImGuiViewport* vp, ImVec2 size); // Resize swap chain, frame buffers etc. + void (*Renderer_RenderWindow)(ImGuiViewport* vp); // (Optional) Clear targets, Render viewport->DrawData + void (*Renderer_SwapBuffers)(ImGuiViewport* vp); // (Optional) Call Present/SwapBuffers (renderer side) +}; + +// List of viewports to render as platform window (updated by ImGui::UpdatePlatformWindows) +struct ImGuiPlatformData +{ + // Viewports[0] is guaranteed to be _always_ the same as MainViewport. Following it are the secondary viewports. + // The main viewport is included in the list because it is more convenient for looping code. + ImGuiViewport* MainViewport; + ImVector Viewports; + + ImGuiPlatformData() { MainViewport = NULL; } +}; + +// Flags stored in ImGuiViewport::Flags, giving indications to the platform back-ends +enum ImGuiViewportFlags_ +{ + ImGuiViewportFlags_NoDecoration = 1 << 0, // Platform Window: Disable platform title bar, borders, etc. + ImGuiViewportFlags_NoFocusOnAppearing = 1 << 1, // Platform Window: Don't take focus when created. + ImGuiViewportFlags_NoInputs = 1 << 2, // Platform Window: Make mouse pass through so we can drag this window while peaking behind it. + ImGuiViewportFlags_NoRendererClear = 1 << 3 // Platform Window: Renderer doesn't need to clear the framebuffer ahead. +}; + +// The viewports created and managed by imgui. The role of the platform back-end is to create the platform/OS windows corresponding to each viewport. +struct ImGuiViewport +{ + ImGuiID ID; + ImGuiViewportFlags Flags; + ImVec2 Pos; // Position of viewport in imgui virtual space (all viewports Pos.y == 0.0f, main viewport Pos.x == 0.0f) + ImVec2 Size; // Size of viewport in pixel + float DpiScale; // 1.0f = 96 DPI = No extra scale + ImDrawData* DrawData; // The ImDrawData corresponding to this viewport. Valid after Render() and until the next call to NewFrame(). + + ImVec2 PlatformPos; // Position in OS desktop/native space + void* PlatformUserData; // void* to hold custom data structure for the platform (e.g. windowing info, render context) + void* PlatformHandle; // void* for FindViewportByPlatformHandle(). (e.g. HWND, GlfwWindow*, SDL_Window*) + bool PlatformRequestClose; // Platform window requested closure + bool PlatformRequestMove; // Platform window requested move (e.g. window was moved using OS windowing facility) + bool PlatformRequestResize; // Platform window requested resize (e.g. window was resize using OS windowing facility) + void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, frame-buffers etc.) + + ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; RendererUserData = NULL; } + ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); } +}; + #if defined(__clang__) #pragma clang diagnostic pop #endif diff --git a/imgui_internal.h b/imgui_internal.h index 629d97e7a..b605c7d5a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -40,7 +40,6 @@ struct ImGuiMenuColumns; struct ImGuiDrawContext; struct ImGuiTextEditState; struct ImGuiPopupRef; -struct ImGuiViewport; struct ImGuiWindow; struct ImGuiWindowSettings; @@ -52,7 +51,6 @@ typedef int ImGuiNavHighlightFlags; // flags: for RenderNavHighlight() typedef int ImGuiNavDirSourceFlags; // flags: for GetNavInputAmount2d() // enum ImGuiNavDirSourceFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ -typedef int ImGuiViewportFlags; // flags: for Viewport() // enum ImGuiViewportFlags_ //------------------------------------------------------------------------- // STB libraries @@ -506,45 +504,26 @@ struct ImDrawDataBuilder IMGUI_API void FlattenIntoSingleLayer(); }; -enum ImGuiViewportFlags_ +enum ImGuiViewportFlagsPrivate_ { - ImGuiViewportFlags_MainViewport = 1 << 0, - ImGuiViewportFlags_HostOtherWindows = 1 << 1, - ImGuiViewportFlags_NoRendererClear = 1 << 2, // Platform Window: Renderer doesn't need to clear the framebuffer ahead. - ImGuiViewportFlags_NoDecoration = 1 << 3, // Platform Window: Disable platform title bar, borders, etc. - ImGuiViewportFlags_NoFocusOnAppearing = 1 << 4, // Platform Window: Don't take focus when created. - ImGuiViewportFlags_NoInputs = 1 << 5 // Platform Window: Make mouse pass through so we can drag this window while peaking behind it. + ImGuiViewportFlags_CanHostOtherWindows = 1 << 10, // Normal viewports are associated to a single window. The main viewport can host multiple windows. }; -struct ImGuiViewport +// ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!) +struct ImGuiViewportP : public ImGuiViewport { - ImGuiID ID; int Idx; - ImGuiViewportFlags Flags; - int LastFrameActive; - int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef + int LastFrameActive; // Last frame number this viewport was activated by a window + int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef ImGuiID LastNameHash; ImGuiWindow* Window; - ImVec2 Pos; // Position in imgui virtual space (Pos.y == 0.0) - ImVec2 Size; - float DpiScale; - ImDrawData DrawData; + ImDrawData DrawDataP; ImDrawDataBuilder DrawDataBuilder; - - // [Optional] OS/Platform Layer data. This is to allow the creation/manipulate of multiple OS/Platform windows. Not all back-ends will allow this. - ImVec2 PlatformPos; // Position in OS desktop/native space - void* PlatformUserData; // void* to hold custom data structure for the platform (e.g. windowing info, render context) - void* PlatformHandle; // void* for FindViewportByPlatformHandle(). (e.g. HWND, GlfwWindow*) - bool PlatformRequestClose; // Platform window requested closure - bool PlatformRequestMove; // Platform window requested move (e.g. window was moved using OS windowing facility) - bool PlatformRequestResize; // Platform window requested resize (e.g. window was resize using OS windowing facility) - void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. framebuffer) ImVec2 RendererLastSize; - ImGuiViewport(ImGuiID id, int idx) { ID = id; Idx = idx; Flags = 0; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Window = NULL; DpiScale = 0.0f; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; RendererUserData = NULL; RendererLastSize = ImVec2(-1.0f,-1.0f); } - ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); } - ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } - float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; } + ImGuiViewportP() { Idx = 1; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Window = NULL; DrawData = NULL; RendererLastSize = ImVec2(-1.0f,-1.0f); } + ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } + float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; } }; struct ImGuiNavMoveResult @@ -608,6 +587,7 @@ struct ImGuiContext bool Initialized; bool FontAtlasOwnedByContext; // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it. ImGuiIO IO; + ImGuiPlatformIO PlatformIO; ImGuiStyle Style; ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. @@ -617,6 +597,7 @@ struct ImGuiContext float Time; int FrameCount; int FrameCountEnded; + int FrameCountPlatformEnded; int FrameCountRendered; ImVector Windows; ImVector WindowsSortBuffer; @@ -651,11 +632,12 @@ struct ImGuiContext ImGuiCond NextTreeNodeOpenCond; // Viewports - ImVectorViewports; - ImGuiViewport* CurrentViewport; - ImGuiViewport* MouseViewport; - ImGuiViewport* MouseLastViewport; - ImGuiViewport* MouseLastHoveredViewport; + ImVector Viewports; + ImGuiPlatformData PlatformData; // This is essentially the public facing version of the Viewports vector (it is updated in UpdatePlatformWindows and exclude the viewports about to be destroyed) + ImGuiViewportP* CurrentViewport; + ImGuiViewportP* MouseViewport; + ImGuiViewportP* MouseLastViewport; + ImGuiViewportP* MouseLastHoveredViewport; // Navigation data (for gamepad/keyboard) ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' @@ -756,10 +738,11 @@ struct ImGuiContext FontSize = FontBaseSize = 0.0f; FontAtlasOwnedByContext = shared_font_atlas ? false : true; IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); + memset(&PlatformIO, 0, sizeof(PlatformIO)); Time = 0.0f; FrameCount = 0; - FrameCountEnded = FrameCountRendered = -1; + FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1; WindowsActiveCount = 0; CurrentWindow = NULL; HoveredWindow = NULL; @@ -950,7 +933,7 @@ struct IMGUI_API ImGuiWindow char* Name; ImGuiID ID; // == ImHash(Name) ImGuiWindowFlags Flags, FlagsPreviousFrame; // See enum ImGuiWindowFlags_ - ImGuiViewport* Viewport; // Always set in Begin(), only inactive windows may have a NULL value here + ImGuiViewportP* Viewport; // Always set in Begin(), only inactive windows may have a NULL value here ImGuiID ViewportId; // Inactive windows preserve their last viewport id (since the viewport may disappear with the window inactivity) ImVec2 ViewportPlatformPos; ImVec2 PosFloat; @@ -1082,17 +1065,12 @@ namespace ImGui IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). // Viewports - IMGUI_API ImGuiViewport* Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& platform_pos, const ImVec2& size); - inline ImVector&GetViewports() { return GImGui->Viewports; } - inline ImGuiViewport* GetMainViewport() { return GImGui->Viewports[0]; } - IMGUI_API ImGuiViewport* FindViewportByID(ImGuiID id); - IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); + IMGUI_API ImGuiViewportP* FindViewportByID(ImGuiID id); IMGUI_API void SetNextWindowViewport(ImGuiID id); - IMGUI_API void ScaleWindowsInViewport(ImGuiViewport* viewport, float scale); + IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale); IMGUI_API void ShowViewportThumbnails(); - IMGUI_API void DestroyViewportsPlaformData(ImGuiContext* context); - IMGUI_API void DestroyViewportsRendererData(ImGuiContext* context); + // Settings IMGUI_API void MarkIniSettingsDirty(); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);