Skip to content

Commit

Permalink
Support additional main viewports
Browse files Browse the repository at this point in the history
  • Loading branch information
exuvo committed May 2, 2021
1 parent 33cdbe9 commit 58f6204
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 17 deletions.
16 changes: 13 additions & 3 deletions backends/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1025,16 +1025,26 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend

ImGui_ImplVulkan_CreateDeviceObjects();

// Our render function expect RendererUserData to be storing the window render buffer we need (for the main viewport we won't use ->Window)
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->RendererUserData = IM_NEW(ImGuiViewportDataVulkan)();
ImGui_ImplVulkan_InitViewport(ImGui::GetMainViewport());

if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplVulkan_InitPlatformInterface();

return true;
}

void ImGui_ImplVulkan_InitViewport(ImGuiViewport* viewport) {
// Our render function expect RendererUserData to be storing the window render buffer we need (for the main viewport we won't use ->Window)
viewport->RendererUserData = IM_NEW(ImGuiViewportDataVulkan)();
}

void ImGui_ImplVulkan_ShutdownViewport(ImGuiViewport* viewport) {
if (ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)viewport->RendererUserData) {
IM_DELETE(data);
viewport->RendererUserData = NULL;
}
}

void ImGui_ImplVulkan_Shutdown()
{
// First destroy objects in all viewports
Expand Down
2 changes: 2 additions & 0 deletions backends/imgui_impl_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ struct ImGui_ImplVulkan_InitInfo

// Called by user code
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
IMGUI_IMPL_API void ImGui_ImplVulkan_InitViewport(ImGuiViewport* viewport);
IMGUI_IMPL_API void ImGui_ImplVulkan_ShutdownViewport(ImGuiViewport* viewport);
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
Expand Down
55 changes: 41 additions & 14 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ static void EndFrameDrawDimmedBackgrounds();

// Viewports
const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter.
static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& platform_pos, const ImVec2& size, ImGuiViewportFlags flags);
ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& platform_pos, const ImVec2& size, ImGuiViewportFlags flags);
static void UpdateViewportsNewFrame();
static void UpdateViewportsEndFrame();
static void UpdateSelectWindowViewport(ImGuiWindow* window);
Expand Down Expand Up @@ -3491,11 +3491,15 @@ ImGuiPlatformIO& ImGui::GetPlatformIO()
}

// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame()
ImDrawData* ImGui::GetDrawData()
ImDrawData* ImGui::GetDrawData(ImGuiViewport* viewport)
{
ImGuiContext& g = *GImGui;
ImGuiViewportP* viewport = g.Viewports[0];
return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL;
IM_ASSERT(viewport != NULL);
ImGuiViewportP* viewportP = (ImGuiViewportP*) viewport;
return viewportP->DrawDataP.Valid ? &viewportP->DrawDataP : NULL;
}

ImDrawData* ImGui::GetDrawData() {
return GetDrawData(ImGui::GetMainViewport());
}

double ImGui::GetTime()
Expand Down Expand Up @@ -11427,8 +11431,17 @@ static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImG
// FIXME: handle 0 to N host viewports
static bool ImGui::UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
return UpdateTryMergeWindowIntoHostViewport(window, g.Viewports[0]);
ImGuiContext& g = *GImGui;

for (ImGuiViewportP* viewport : g.Viewports) {
if (viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) {
if (UpdateTryMergeWindowIntoHostViewport(window, viewport)) {
return true;
}
}
}

return false;
}

// Translate Dear ImGui windows when a Host Viewport has been moved
Expand Down Expand Up @@ -11686,13 +11699,19 @@ static void ImGui::UpdateViewportsEndFrame()
{
ImGuiViewportP* viewport = g.Viewports[i];
viewport->LastPos = viewport->Pos;
if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f)
if (i > 0) // Always include main viewport in the list
continue;

if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f) {
if ((viewport->Flags & (ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows)) == 0)
continue;
}

if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window))
continue;
if (i > 0)
IM_ASSERT(viewport->Window != NULL);

if ((viewport->Flags & (ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows)) == 0) {
IM_ASSERT(viewport->Window != NULL);
}

g.PlatformIO.Viewports.push_back(viewport);
}
g.Viewports[0]->ClearRequestFlags(); // Clear main viewport flags because UpdatePlatformWindows() won't do it and may not even be called
Expand Down Expand Up @@ -11905,6 +11924,10 @@ void ImGui::UpdatePlatformWindows()
for (int i = 1; i < g.Viewports.Size; i++)
{
ImGuiViewportP* viewport = g.Viewports[i];

if (viewport->Flags & ImGuiViewportFlags_OwnedByApp) { // Avoid Create and destroy window for host windows viewports
continue;
}

// Destroy platform window if the viewport hasn't been submitted or if it is hosting a hidden window
// (the implicit/fallback Debug##Default window will be registering its viewport then be disabled, causing a dummy DestroyPlatformWindow to be made each frame)
Expand Down Expand Up @@ -12029,11 +12052,12 @@ void ImGui::UpdatePlatformWindows()
//
void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* renderer_render_arg)
{
// Skip the main viewport (index 0), which is always fully handled by the application!
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int i = 1; i < platform_io.Viewports.Size; i++)
{
ImGuiViewport* viewport = platform_io.Viewports[i];
if (viewport->Flags & ImGuiViewportFlags_OwnedByApp)
continue;
if (viewport->Flags & ImGuiViewportFlags_Minimized)
continue;
if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg);
Expand All @@ -12042,6 +12066,8 @@ void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* render
for (int i = 1; i < platform_io.Viewports.Size; i++)
{
ImGuiViewport* viewport = platform_io.Viewports[i];
if (viewport->Flags & ImGuiViewportFlags_OwnedByApp)
continue;
if (viewport->Flags & ImGuiViewportFlags_Minimized)
continue;
if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg);
Expand Down Expand Up @@ -12130,7 +12156,8 @@ void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
}
else
{
IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL);
if ((viewport->Flags & ImGuiViewportFlags_OwnedByApp) == 0)
IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL);
}
viewport->RendererUserData = viewport->PlatformUserData = viewport->PlatformHandle = NULL;
viewport->ClearRequestFlags();
Expand Down
1 change: 1 addition & 0 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ namespace ImGui
IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all!
IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData().
IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render.
IMGUI_API ImDrawData* GetDrawData(ImGuiViewport* viewport); // valid after Render() and until the next call to NewFrame(). this is what you have to render.

// Demo, Debug, Information
IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!
Expand Down

0 comments on commit 58f6204

Please sign in to comment.