Viewports Added ImGui::GetMainViewport() as a way to get the bounds and work area of the host display. (#3789, #1542)

Viewports: Backport a few constructs from 'docking' branch.
Viewports: Added ImGuiViewportFlags_IsPlatformWindow, ImGuiViewportFlags_IsPlatformMonitor, ImGuiViewportFlags_OwnedByApp (none of them were in docking branch yet). ImGuiViewportFlags_IsPlatformMonitor is merely there to convey future intent, not yet used.
Reduce uses of io.DisplaySize.
MainMenuBar: Backport work area handling code from 'docking' branch.
Metrics: Backported "Viewports" debug visualizer from 'docking' branch.
Demo: Rework 'Examples->Fullscreen Window'.
Demo: 'Simple Overlay' demo now moves under main menu-bar (if any) using GetMainViewport()'s work area.
This commit is contained in:
ocornut 2021-02-10 14:54:59 +01:00
parent 3b4d3a9b73
commit f14042ca78
6 changed files with 443 additions and 122 deletions

View File

@ -52,6 +52,21 @@ Breaking Changes:
Other Changes: Other Changes:
- Viewports Added ImGui::GetMainViewport() as a way to get the bounds and work area of the host display. (#3789, #1542)
- In 'master' branch or without multi-viewports feature enabled:
- GetMainViewport()->Pos is always == (0,0)
- GetMainViewport()->Size is always == io.DisplaySize
- In 'docking' branch and with the multi-viewports feature enabled:
- GetMainViewport() will return information from your host Platform Window.
- In the future, we will support a "no main viewport" mode and this may return bounds of your main monitor.
- For forward compatibility with multi-viewports/multi-monitors:
- Code using (0,0) as a way to signify "upper-left of the host window" should use GetMainViewport()->Pos.
- Code using io.DisplaySize as a way to signify "size of the host window" should use GetMainViewport()->Size.
- We are also exposing a work area in ImGuiViewport ('WorkPos', 'WorkSize' vs 'Pos', 'Size' for full area):
- For a Platform Window, the work area is generally the full area minus space used by menu-bars.
- For a Platform Monitor, the work area is generally the full area minus space used by task-bars.
- All of this has been the case in 'docking' branch for a long time. What we've done is merely merging
a small chunk of the multi-viewport logic into 'master' to standardize some concepts ahead of time.
- Tables: Fixed PopItemWidth() or multi-components items not restoring per-colum ItemWidth correctly. (#3760) - Tables: Fixed PopItemWidth() or multi-components items not restoring per-colum ItemWidth correctly. (#3760)
- Window: Fixed minor title bar text clipping issue when FramePadding is small/zero and there are no - Window: Fixed minor title bar text clipping issue when FramePadding is small/zero and there are no
close button in the window. (#3731) close button in the window. (#3731)
@ -80,7 +95,9 @@ Other Changes:
Would lead to a buffer read overflow. Would lead to a buffer read overflow.
- ImDrawList: Clarified PathArcTo() need for a_min <= a_max with an assert. - ImDrawList: Clarified PathArcTo() need for a_min <= a_max with an assert.
- ImDrawList: Fixed PathArcToFast() handling of a_min > a_max. - ImDrawList: Fixed PathArcToFast() handling of a_min > a_max.
- Demo: Added 'Examples->Fullscreen Window' demo. (#3789) - Metrics: Backported "Viewports" debug visualizer from 'docking' branch.
- Demo: Added 'Examples->Fullscreen Window' demo using GetMainViewport() values. (#3789)
- Demo: 'Simple Overlay' demo now moves under main menu-bar (if any) using GetMainViewport()'s work area.
- Backends: Win32: Dynamically loading XInput DLL instead of linking with it, facilite compiling with - Backends: Win32: Dynamically loading XInput DLL instead of linking with it, facilite compiling with
old WindowSDK versions or running on Windows 7. (#3646, #3645, #3248, #2716) [@Demonese] old WindowSDK versions or running on Windows 7. (#3646, #3645, #3248, #2716) [@Demonese]
- Backends: Vulkan: Add support for custom Vulkan function loader and VK_NO_PROTOTYPES. (#3759, #3227) [@Hossein-Noroozpour] - Backends: Vulkan: Add support for custom Vulkan function loader and VK_NO_PROTOTYPES. (#3759, #3227) [@Hossein-Noroozpour]

362
imgui.cpp
View File

@ -75,6 +75,7 @@ CODE
// [SECTION] DRAG AND DROP // [SECTION] DRAG AND DROP
// [SECTION] LOGGING/CAPTURING // [SECTION] LOGGING/CAPTURING
// [SECTION] SETTINGS // [SECTION] SETTINGS
// [SECTION] VIEWPORTS
// [SECTION] PLATFORM DEPENDENT HELPERS // [SECTION] PLATFORM DEPENDENT HELPERS
// [SECTION] METRICS/DEBUGGER WINDOW // [SECTION] METRICS/DEBUGGER WINDOW
@ -309,10 +310,11 @@ CODE
// We are using scissoring to clip some objects. All low-level graphics API should supports it. // We are using scissoring to clip some objects. All low-level graphics API should supports it.
// - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
// (some elements visible outside their bounds) but you can fix that once everything else works! // (some elements visible outside their bounds) but you can fix that once everything else works!
// - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize) // - Clipping coordinates are provided in imgui coordinates space:
// In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize. // - For a given viewport, draw_data->DisplayPos == viewport->Pos and draw_data->DisplaySize == viewport->Size
// However, in the interest of supporting multi-viewport applications in the future (see 'viewport' branch on github), // - In a single viewport application, draw_data->DisplayPos == (0,0) and draw_data->DisplaySize == io.DisplaySize, but always use GetMainViewport()->Pos/Size instead of hardcoding those values.
// always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space. // - In the interest of supporting multi-viewport applications (see 'docking' branch on github),
// always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
// - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min) // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
ImVec2 pos = draw_data->DisplayPos; ImVec2 pos = draw_data->DisplayPos;
MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y)); MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y));
@ -852,8 +854,6 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* wind
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list); static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window); static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
static ImRect GetViewportRect();
// Settings // Settings
static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*); static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name); static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
@ -900,6 +900,9 @@ static void RenderWindowOuterBorders(ImGuiWindow* window);
static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size); static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
// Viewports
static void UpdateViewportsNewFrame();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -3391,7 +3394,8 @@ ImGuiIO& ImGui::GetIO()
ImDrawData* ImGui::GetDrawData() ImDrawData* ImGui::GetDrawData()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.DrawData.Valid ? &g.DrawData : NULL; ImGuiViewportP* viewport = g.Viewports[0];
return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL;
} }
double ImGui::GetTime() double ImGui::GetTime()
@ -3404,14 +3408,50 @@ int ImGui::GetFrameCount()
return GImGui->FrameCount; return GImGui->FrameCount;
} }
static ImDrawList* GetViewportDrawList(ImGuiViewportP* viewport, size_t drawlist_no, const char* drawlist_name)
{
// Create the draw list on demand, because they are not frequently used for all viewports
ImGuiContext& g = *GImGui;
IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->DrawLists));
ImDrawList* draw_list = viewport->DrawLists[drawlist_no];
if (draw_list == NULL)
{
draw_list = IM_NEW(ImDrawList)(&g.DrawListSharedData);
draw_list->_OwnerName = drawlist_name;
viewport->DrawLists[drawlist_no] = draw_list;
}
// Our ImDrawList system requires that there is always a command
if (viewport->DrawListsLastFrame[drawlist_no] != g.FrameCount)
{
draw_list->_ResetForNewFrame();
draw_list->PushTextureID(g.IO.Fonts->TexID);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->DrawListsLastFrame[drawlist_no] = g.FrameCount;
}
return draw_list;
}
ImDrawList* ImGui::GetBackgroundDrawList(ImGuiViewport* viewport)
{
return GetViewportDrawList((ImGuiViewportP*)viewport, 0, "##Background");
}
ImDrawList* ImGui::GetBackgroundDrawList() ImDrawList* ImGui::GetBackgroundDrawList()
{ {
return &GImGui->BackgroundDrawList; ImGuiContext& g = *GImGui;
return GetBackgroundDrawList(g.Viewports[0]);
}
ImDrawList* ImGui::GetForegroundDrawList(ImGuiViewport* viewport)
{
return GetViewportDrawList((ImGuiViewportP*)viewport, 1, "##Foreground");
} }
ImDrawList* ImGui::GetForegroundDrawList() ImDrawList* ImGui::GetForegroundDrawList()
{ {
return &GImGui->ForegroundDrawList; ImGuiContext& g = *GImGui;
return GetForegroundDrawList(g.Viewports[0]);
} }
ImDrawListSharedData* ImGui::GetDrawListSharedData() ImDrawListSharedData* ImGui::GetDrawListSharedData()
@ -3493,7 +3533,8 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
if (g.NavWindow && g.NavWindow->Appearing) if (g.NavWindow && g.NavWindow->Appearing)
return; return;
// Click on empty space to focus window and start moving (after we're done with all our widgets) // Click on empty space to focus window and start moving
// (after we're done with all our widgets)
if (g.IO.MouseClicked[0]) if (g.IO.MouseClicked[0])
{ {
// Handle the edge case of a popup being closed while clicking in its empty space. // Handle the edge case of a popup being closed while clicking in its empty space.
@ -3826,11 +3867,16 @@ void ImGui::NewFrame()
g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX;
UpdateViewportsNewFrame();
// Setup current font and draw list shared data // Setup current font and draw list shared data
g.IO.Fonts->Locked = true; g.IO.Fonts->Locked = true;
SetCurrentFont(GetDefaultFont()); SetCurrentFont(GetDefaultFont());
IM_ASSERT(g.Font->IsLoaded()); IM_ASSERT(g.Font->IsLoaded());
g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
for (int n = 0; n < g.Viewports.Size; n++)
virtual_space.Add(g.Viewports[n]->GetMainRect());
g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
g.DrawListSharedData.SetCircleSegmentMaxError(g.Style.CircleSegmentMaxError); g.DrawListSharedData.SetCircleSegmentMaxError(g.Style.CircleSegmentMaxError);
g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
@ -3843,16 +3889,12 @@ void ImGui::NewFrame()
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
g.BackgroundDrawList._ResetForNewFrame();
g.BackgroundDrawList.PushTextureID(g.IO.Fonts->TexID);
g.BackgroundDrawList.PushClipRectFullScreen();
g.ForegroundDrawList._ResetForNewFrame();
g.ForegroundDrawList.PushTextureID(g.IO.Fonts->TexID);
g.ForegroundDrawList.PushClipRectFullScreen();
// Mark rendering data as invalid to prevent user who may have a handle on it to use it. // Mark rendering data as invalid to prevent user who may have a handle on it to use it.
g.DrawData.Clear(); for (int n = 0; n < g.Viewports.Size; n++)
{
ImGuiViewportP* viewport = g.Viewports[n];
viewport->DrawDataP.Clear();
}
// Drag and drop keep the source ID alive so even if the source disappear our state is consistent // Drag and drop keep the source ID alive so even if the source disappear our state is consistent
if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId) if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
@ -4039,6 +4081,10 @@ void ImGui::Initialize(ImGuiContext* context)
TableSettingsInstallHandler(context); TableSettingsInstallHandler(context);
#endif // #ifdef IMGUI_HAS_TABLE #endif // #ifdef IMGUI_HAS_TABLE
// Create default viewport
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
g.Viewports.push_back(viewport);
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
#endif // #ifdef IMGUI_HAS_DOCK #endif // #ifdef IMGUI_HAS_DOCK
@ -4090,9 +4136,10 @@ void ImGui::Shutdown(ImGuiContext* context)
g.FontStack.clear(); g.FontStack.clear();
g.OpenPopupStack.clear(); g.OpenPopupStack.clear();
g.BeginPopupStack.clear(); g.BeginPopupStack.clear();
g.DrawDataBuilder.ClearFreeMemory();
g.BackgroundDrawList._ClearFreeMemory(); for (int i = 0; i < g.Viewports.Size; i++)
g.ForegroundDrawList._ClearFreeMemory(); IM_DELETE(g.Viewports[i]);
g.Viewports.clear();
g.TabBars.Clear(); g.TabBars.Clear();
g.CurrentTabBarStack.clear(); g.CurrentTabBarStack.clear();
@ -4187,25 +4234,25 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
out_list->push_back(draw_list); out_list->push_back(draw_list);
} }
static void AddWindowToDrawData(ImVector<ImDrawList*>* out_render_list, ImGuiWindow* window) static void AddWindowToDrawData(ImGuiWindow* window, int layer)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiViewportP* viewport = g.Viewports[0];
g.IO.MetricsRenderWindows++; g.IO.MetricsRenderWindows++;
AddDrawListToDrawData(out_render_list, window->DrawList); AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[layer], window->DrawList);
for (int i = 0; i < window->DC.ChildWindows.Size; i++) for (int i = 0; i < window->DC.ChildWindows.Size; i++)
{ {
ImGuiWindow* child = window->DC.ChildWindows[i]; ImGuiWindow* child = window->DC.ChildWindows[i];
if (IsWindowActiveAndVisible(child)) // clipped children may have been marked not active if (IsWindowActiveAndVisible(child)) // Clipped children may have been marked not active
AddWindowToDrawData(out_render_list, child); AddWindowToDrawData(child, layer);
} }
} }
// Layer is locked for the root window, however child windows may use a different viewport (e.g. extruding menu) // Layer is locked for the root window, however child windows may use a different viewport (e.g. extruding menu)
static void AddRootWindowToDrawData(ImGuiWindow* window) static void AddRootWindowToDrawData(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui;
int layer = (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0; int layer = (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0;
AddWindowToDrawData(&g.DrawDataBuilder.Layers[layer], window); AddWindowToDrawData(window, layer);
} }
void ImDrawDataBuilder::FlattenIntoSingleLayer() void ImDrawDataBuilder::FlattenIntoSingleLayer()
@ -4226,15 +4273,16 @@ void ImDrawDataBuilder::FlattenIntoSingleLayer()
} }
} }
static void SetupDrawData(ImVector<ImDrawList*>* draw_lists, ImDrawData* draw_data) static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector<ImDrawList*>* draw_lists)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImDrawData* draw_data = &viewport->DrawDataP;
draw_data->Valid = true; draw_data->Valid = true;
draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL;
draw_data->CmdListsCount = draw_lists->Size; draw_data->CmdListsCount = draw_lists->Size;
draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
draw_data->DisplayPos = ImVec2(0.0f, 0.0f); draw_data->DisplayPos = viewport->Pos;
draw_data->DisplaySize = io.DisplaySize; draw_data->DisplaySize = viewport->Size;
draw_data->FramebufferScale = io.DisplayFramebufferScale; draw_data->FramebufferScale = io.DisplayFramebufferScale;
for (int n = 0; n < draw_lists->Size; n++) for (int n = 0; n < draw_lists->Size; n++)
{ {
@ -4355,13 +4403,17 @@ void ImGui::Render()
EndFrame(); EndFrame();
g.FrameCountRendered = g.FrameCount; g.FrameCountRendered = g.FrameCount;
g.IO.MetricsRenderWindows = 0; g.IO.MetricsRenderWindows = 0;
g.DrawDataBuilder.Clear();
CallContextHooks(&g, ImGuiContextHookType_RenderPre); CallContextHooks(&g, ImGuiContextHookType_RenderPre);
// Add background ImDrawList // Add background ImDrawList (for each active viewport)
if (!g.BackgroundDrawList.VtxBuffer.empty()) for (int n = 0; n != g.Viewports.Size; n++)
AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.BackgroundDrawList); {
ImGuiViewportP* viewport = g.Viewports[n];
viewport->DrawDataBuilder.Clear();
if (viewport->DrawLists[0] != NULL)
AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
}
// Add ImDrawList to render // Add ImDrawList to render
ImGuiWindow* windows_to_render_top_most[2]; ImGuiWindow* windows_to_render_top_most[2];
@ -4376,20 +4428,27 @@ void ImGui::Render()
for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++) for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++)
if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window
AddRootWindowToDrawData(windows_to_render_top_most[n]); AddRootWindowToDrawData(windows_to_render_top_most[n]);
g.DrawDataBuilder.FlattenIntoSingleLayer();
// Draw software mouse cursor if requested // Setup ImDrawData structures for end-user
if (g.IO.MouseDrawCursor) g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0;
RenderMouseCursor(&g.ForegroundDrawList, g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48)); for (int n = 0; n < g.Viewports.Size; n++)
{
ImGuiViewportP* viewport = g.Viewports[n];
viewport->DrawDataBuilder.FlattenIntoSingleLayer();
// Add foreground ImDrawList // Draw software mouse cursor if requested by io.MouseDrawCursor flag
if (!g.ForegroundDrawList.VtxBuffer.empty()) if (g.IO.MouseDrawCursor)
AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.ForegroundDrawList); RenderMouseCursor(GetForegroundDrawList(viewport), g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48));
// Setup ImDrawData structure for end-user // Add foreground ImDrawList (for each active viewport)
SetupDrawData(&g.DrawDataBuilder.Layers[0], &g.DrawData); if (viewport->DrawLists[1] != NULL)
g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount;
SetupViewportDrawData(viewport, &viewport->DrawDataBuilder.Layers[0]);
ImDrawData* draw_data = &viewport->DrawDataP;
g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
}
CallContextHooks(&g, ImGuiContextHookType_RenderPost); CallContextHooks(&g, ImGuiContextHookType_RenderPost);
} }
@ -4838,12 +4897,6 @@ ImVec2 ImGui::GetItemRectSize()
return window->DC.LastItemRect.GetSize(); return window->DC.LastItemRect.GetSize();
} }
static ImRect GetViewportRect()
{
ImGuiContext& g = *GImGui;
return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
}
bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags) bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -5008,7 +5061,8 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
g.WindowsById.SetVoidPtr(window->ID, window); g.WindowsById.SetVoidPtr(window->ID, window);
// Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
window->Pos = ImVec2(60, 60); const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
window->Pos = main_viewport->Pos + ImVec2(60, 60);
// User can disable loading and saving of settings. Tooltip and child windows also don't store settings. // User can disable loading and saving of settings. Tooltip and child windows also don't store settings.
if (!(flags & ImGuiWindowFlags_NoSavedSettings)) if (!(flags & ImGuiWindowFlags_NoSavedSettings))
@ -5116,7 +5170,10 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont
ImVec2 size_min = style.WindowMinSize; ImVec2 size_min = style.WindowMinSize;
if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups)
size_min = ImMin(size_min, ImVec2(4.0f, 4.0f)); size_min = ImMin(size_min, ImVec2(4.0f, 4.0f));
ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f));
// FIXME-VIEWPORT-WORKAREA: May want to use GetWorkSize() instead of Size depending on the type of windows?
ImVec2 avail_size = ImGui::GetMainViewport()->Size;
ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, avail_size - style.DisplaySafeAreaPadding * 2.0f));
// When the window cannot fit all contents (either because of constraints, either because screen is too small), // When the window cannot fit all contents (either because of constraints, either because screen is too small),
// we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding. // we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding.
@ -5877,9 +5934,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Calculate the range of allowed position for that window (to be movable and visible past safe area padding) // Calculate the range of allowed position for that window (to be movable and visible past safe area padding)
// When clamping to stay visible, we will enforce that window->Pos stays inside of visibility_rect. // When clamping to stay visible, we will enforce that window->Pos stays inside of visibility_rect.
ImRect viewport_rect(GetViewportRect()); ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport();
ImRect viewport_rect(viewport->GetMainRect());
ImRect viewport_work_rect(viewport->GetWorkRect());
ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
ImRect visibility_rect(viewport_rect.Min + visibility_padding, viewport_rect.Max - visibility_padding); ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding);
// Clamp position/size so window stays visible within its viewport or monitor // Clamp position/size so window stays visible within its viewport or monitor
// Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
@ -8163,7 +8222,10 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla
// (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves) // (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves)
// FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window. // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); {
const ImGuiViewport* viewport = GetMainViewport();
SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
}
flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse; flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse;
const bool is_open = Begin(name, p_open, flags); const bool is_open = Begin(name, p_open, flags);
@ -8256,6 +8318,9 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flag
// r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.) // r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.)
// r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it. // r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it.
// (r_outer is usually equivalent to the viewport rectangle minus padding, but when multi-viewports are enabled and monitor
// information are available, it may represent the entire platform monitor from the frame of reference of the current viewport.
// this allows us to have tooltips/popups displayed out of the parent viewport.)
ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy) ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
{ {
ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size); ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
@ -8330,11 +8395,13 @@ ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& s
return pos; return pos;
} }
// Note that this is used for popups, which can overlap the non work-area of individual viewports.
ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow* window) ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui;
IM_UNUSED(window); IM_UNUSED(window);
ImVec2 padding = GImGui->Style.DisplaySafeAreaPadding; ImRect r_screen = ((ImGuiViewportP*)(void*)GetMainViewport())->GetMainRect();
ImRect r_screen = GetViewportRect(); ImVec2 padding = g.Style.DisplaySafeAreaPadding;
r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f)); r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
return r_screen; return r_screen;
} }
@ -8778,8 +8845,8 @@ static ImVec2 ImGui::NavCalcPreferredRefPos()
// When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item. // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item.
const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
ImRect visible_rect = GetViewportRect(); ImGuiViewport* viewport = GetMainViewport();
return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. return ImFloor(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta.
} }
} }
@ -9082,7 +9149,7 @@ static void ImGui::NavUpdate()
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
ImRect nav_rect_rel = g.NavWindow ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0); ImRect nav_rect_rel = g.NavWindow ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect(); g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : ImRect(0, 0, 0, 0);
g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y); g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y);
g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x); g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x);
g.NavScoringRect.Max.x = g.NavScoringRect.Min.x; g.NavScoringRect.Max.x = g.NavScoringRect.Min.x;
@ -9512,8 +9579,9 @@ void ImGui::NavUpdateWindowingOverlay()
if (g.NavWindowingListWindow == NULL) if (g.NavWindowingListWindow == NULL)
g.NavWindowingListWindow = FindWindowByName("###NavWindowingList"); g.NavWindowingListWindow = FindWindowByName("###NavWindowingList");
SetNextWindowSizeConstraints(ImVec2(g.IO.DisplaySize.x * 0.20f, g.IO.DisplaySize.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); const ImGuiViewport* viewport = GetMainViewport();
SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f); PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f);
Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--) for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
@ -10378,9 +10446,41 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] VIEWPORTS, PLATFORM WINDOWS // [SECTION] VIEWPORTS, PLATFORM WINDOWS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// - GetMainViewport()
// - UpdateViewportsNewFrame() [Internal]
// (this section is more complete in the 'docking' branch)
//-----------------------------------------------------------------------------
// (this section is filled in the 'docking' branch) ImGuiViewport* ImGui::GetMainViewport()
{
ImGuiContext& g = *GImGui;
return g.Viewports[0];
}
// Update viewports and monitor infos
static void ImGui::UpdateViewportsNewFrame()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.Viewports.Size == 1);
// Update main viewport with current platform position.
// FIXME-VIEWPORT: Size is driven by backend/user code for backward-compatibility but we should aim to make this more consistent.
ImGuiViewportP* main_viewport = g.Viewports[0];
main_viewport->Flags = ImGuiViewportFlags_IsPlatformWindow | ImGuiViewportFlags_OwnedByApp;
main_viewport->Pos = ImVec2(0.0f, 0.0f);
main_viewport->Size = g.IO.DisplaySize;
for (int n = 0; n < g.Viewports.Size; n++)
{
ImGuiViewportP* viewport = g.Viewports[n];
// Lock down space taken by menu bars and status bars, reset the offset for fucntions like BeginMainMenuBar() to alter them again.
viewport->WorkOffsetMin = viewport->CurrWorkOffsetMin;
viewport->WorkOffsetMax = viewport->CurrWorkOffsetMax;
viewport->CurrWorkOffsetMin = viewport->CurrWorkOffsetMax = ImVec2(0.0f, 0.0f);
viewport->UpdateWorkRect();
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] DOCKING // [SECTION] DOCKING
@ -10552,6 +10652,8 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] METRICS/DEBUGGER WINDOW // [SECTION] METRICS/DEBUGGER WINDOW
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// - RenderViewportThumbnail() [Internal]
// - RenderViewportsThumbnails() [Internal]
// - MetricsHelpMarker() [Internal] // - MetricsHelpMarker() [Internal]
// - ShowMetricsWindow() // - ShowMetricsWindow()
// - DebugNodeColumns() [Internal] // - DebugNodeColumns() [Internal]
@ -10559,6 +10661,7 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
// - DebugNodeDrawCmdShowMeshAndBoundingBox() [Internal] // - DebugNodeDrawCmdShowMeshAndBoundingBox() [Internal]
// - DebugNodeStorage() [Internal] // - DebugNodeStorage() [Internal]
// - DebugNodeTabBar() [Internal] // - DebugNodeTabBar() [Internal]
// - DebugNodeViewport() [Internal]
// - DebugNodeWindow() [Internal] // - DebugNodeWindow() [Internal]
// - DebugNodeWindowSettings() [Internal] // - DebugNodeWindowSettings() [Internal]
// - DebugNodeWindowsList() [Internal] // - DebugNodeWindowsList() [Internal]
@ -10566,6 +10669,57 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
#ifndef IMGUI_DISABLE_METRICS_WINDOW #ifndef IMGUI_DISABLE_METRICS_WINDOW
void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 scale = bb.GetSize() / viewport->Size;
ImVec2 off = bb.Min - viewport->Pos * scale;
float alpha_mul = 1.0f;
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f));
for (int i = 0; i != g.Windows.Size; i++)
{
ImGuiWindow* thumb_window = g.Windows[i];
if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow))
continue;
ImRect thumb_r = thumb_window->Rect();
ImRect title_r = thumb_window->TitleBarRect();
thumb_r = ImRect(ImFloor(off + thumb_r.Min * scale), ImFloor(off + thumb_r.Max * scale));
title_r = ImRect(ImFloor(off + title_r.Min * scale), ImFloor(off + ImVec2(title_r.Max.x, title_r.Min.y) * scale) + ImVec2(0,5)); // Exaggerate title bar height
thumb_r.ClipWithFull(bb);
title_r.ClipWithFull(bb);
const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight);
window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul));
window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul));
window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name));
}
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
}
static void RenderViewportsThumbnails()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
// We don't display full monitor bounds (we could, but it often looks awkward), instead we display just enough to cover all of our viewports.
float SCALE = 1.0f / 8.0f;
ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
for (int n = 0; n < g.Viewports.Size; n++)
bb_full.Add(g.Viewports[n]->GetMainRect());
ImVec2 p = window->DC.CursorPos;
ImVec2 off = p - bb_full.Min * SCALE;
for (int n = 0; n < g.Viewports.Size; n++)
{
ImGuiViewportP* viewport = g.Viewports[n];
ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
}
ImGui::Dummy(bb_full.GetSize() * SCALE);
}
// Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds. // Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds.
static void MetricsHelpMarker(const char* desc) static void MetricsHelpMarker(const char* desc)
{ {
@ -10593,7 +10747,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
// Basic info // Basic info
Text("Dear ImGui %s", ImGui::GetVersion()); Text("Dear ImGui %s", GetVersion());
Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3); Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows); Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
@ -10724,13 +10878,34 @@ void ImGui::ShowMetricsWindow(bool* p_open)
TreePop(); TreePop();
} }
// Contents // Windows
DebugNodeWindowsList(&g.Windows, "Windows"); DebugNodeWindowsList(&g.Windows, "Windows");
//DebugNodeWindowList(&g.WindowsFocusOrder, "WindowsFocusOrder"); //DebugNodeWindowsList(&g.WindowsFocusOrder, "WindowsFocusOrder");
if (TreeNode("DrawLists", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size))
// DrawLists
int drawlist_count = 0;
for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++)
drawlist_count += g.Viewports[viewport_i]->DrawDataBuilder.GetDrawListCount();
if (TreeNode("DrawLists", "DrawLists (%d)", drawlist_count))
{ {
for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++)
DebugNodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList"); {
ImGuiViewportP* viewport = g.Viewports[viewport_i];
for (int layer_i = 0; layer_i < IM_ARRAYSIZE(viewport->DrawDataBuilder.Layers); layer_i++)
for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[layer_i].Size; draw_list_i++)
DebugNodeDrawList(NULL, viewport->DrawDataBuilder.Layers[layer_i][draw_list_i], "DrawList");
}
TreePop();
}
// Viewports
if (TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size))
{
Indent(GetTreeNodeToLabelSpacing());
RenderViewportsThumbnails();
Unindent(GetTreeNodeToLabelSpacing());
for (int i = 0; i < g.Viewports.Size; i++)
DebugNodeViewport(g.Viewports[i]);
TreePop(); TreePop();
} }
@ -10973,7 +11148,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list,
pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf);
if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list) if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list)
DebugNodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes); DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes);
if (!pcmd_node_open) if (!pcmd_node_open)
continue; continue;
@ -10994,7 +11169,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list,
ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
Selectable(buf); Selectable(buf);
if (IsItemHovered() && fg_draw_list) if (IsItemHovered() && fg_draw_list)
DebugNodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, true, false); DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false);
// Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
ImGuiListClipper clipper; ImGuiListClipper clipper;
@ -11027,33 +11202,32 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list,
} }
// [DEBUG] Display mesh/aabb of a ImDrawCmd // [DEBUG] Display mesh/aabb of a ImDrawCmd
void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb) void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb)
{ {
IM_ASSERT(show_mesh || show_aabb); IM_ASSERT(show_mesh || show_aabb);
ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset; ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset;
// Draw wire-frame version of all triangles // Draw wire-frame version of all triangles
ImRect clip_rect = draw_cmd->ClipRect; ImRect clip_rect = draw_cmd->ClipRect;
ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
ImDrawListFlags backup_flags = fg_draw_list->Flags; ImDrawListFlags backup_flags = out_draw_list->Flags;
fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
for (unsigned int idx_n = draw_cmd->IdxOffset; idx_n < draw_cmd->IdxOffset + draw_cmd->ElemCount; ) for (unsigned int idx_n = draw_cmd->IdxOffset; idx_n < draw_cmd->IdxOffset + draw_cmd->ElemCount; )
{ {
ImVec2 triangle[3]; ImVec2 triangle[3];
for (int n = 0; n < 3; n++, idx_n++) for (int n = 0; n < 3; n++, idx_n++)
vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos)); vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
if (show_mesh) if (show_mesh)
fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles
} }
// Draw bounding boxes // Draw bounding boxes
if (show_aabb) if (show_aabb)
{ {
fg_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU out_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU
fg_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles out_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles
} }
fg_draw_list->Flags = backup_flags; out_draw_list->Flags = backup_flags;
} }
// [DEBUG] Display contents of ImGuiStorage // [DEBUG] Display contents of ImGuiStorage
@ -11105,6 +11279,26 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
} }
} }
void ImGui::DebugNodeViewport(ImGuiViewportP* viewport)
{
SetNextItemOpen(true, ImGuiCond_Once);
if (TreeNode("viewport0", "Viewport #%d", 0))
{
ImGuiWindowFlags flags = viewport->Flags;
BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f",
viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y,
viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y);
BulletText("Flags: 0x%04X =%s%s%s", viewport->Flags,
(flags & ImGuiViewportFlags_IsPlatformWindow) ? " IsPlatformWindow" : "",
(flags & ImGuiViewportFlags_IsPlatformMonitor) ? " IsPlatformMonitor" : "",
(flags & ImGuiViewportFlags_OwnedByApp) ? " OwnedByApp" : "");
for (int layer_i = 0; layer_i < IM_ARRAYSIZE(viewport->DrawDataBuilder.Layers); layer_i++)
for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[layer_i].Size; draw_list_i++)
DebugNodeDrawList(NULL, viewport->DrawDataBuilder.Layers[layer_i][draw_list_i], "DrawList");
TreePop();
}
}
void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
{ {
if (window == NULL) if (window == NULL)
@ -11162,7 +11356,6 @@ void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings)
settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed); settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
} }
void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label) void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label)
{ {
if (!TreeNode(label, "%s (%d)", label, windows->Size)) if (!TreeNode(label, "%s (%d)", label, windows->Size))
@ -11182,12 +11375,13 @@ void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* la
void ImGui::ShowMetricsWindow(bool*) {} void ImGui::ShowMetricsWindow(bool*) {}
void ImGui::DebugNodeColumns(ImGuiOldColumns*) {} void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {} void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {}
void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow*, const ImDrawList*, const ImDrawCmd*, bool, bool) {} void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {} void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}
void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {} void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {}
void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {} void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}
void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {} void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {}
void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*, const char*) {} void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*, const char*) {}
void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
#endif #endif

61
imgui.h
View File

@ -31,6 +31,7 @@ Index of this file:
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor) // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport)
*/ */
@ -59,7 +60,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.81 WIP" #define IMGUI_VERSION "1.81 WIP"
#define IMGUI_VERSION_NUM 18003 #define IMGUI_VERSION_NUM 18004
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
@ -143,6 +144,7 @@ struct ImGuiTableSortSpecs; // Sorting specifications for a table (often
struct ImGuiTableColumnSortSpecs; // Sorting specification for one column of a table struct ImGuiTableColumnSortSpecs; // Sorting specification for one column of a table
struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder) struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder)
struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbbb][,ccccc]") struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbbb][,ccccc]")
struct ImGuiViewport; // A Platform Window (always only one in 'master' branch), in the future may represent Platform Monitor
// Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) // Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file)
// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists!
@ -181,6 +183,7 @@ typedef int ImGuiTableFlags; // -> enum ImGuiTableFlags_ // Flags: F
typedef int ImGuiTableColumnFlags; // -> enum ImGuiTableColumnFlags_// Flags: For TableSetupColumn() typedef int ImGuiTableColumnFlags; // -> enum ImGuiTableColumnFlags_// Flags: For TableSetupColumn()
typedef int ImGuiTableRowFlags; // -> enum ImGuiTableRowFlags_ // Flags: For TableNextRow() typedef int ImGuiTableRowFlags; // -> enum ImGuiTableRowFlags_ // Flags: For TableNextRow()
typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode(), TreeNodeEx(), CollapsingHeader() typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode(), TreeNodeEx(), CollapsingHeader()
typedef int ImGuiViewportFlags; // -> enum ImGuiViewportFlags_ // Flags: for ImGuiViewport
typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild() typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild()
// Other types // Other types
@ -414,8 +417,8 @@ namespace ImGui
IMGUI_API void SetCursorPosX(float local_x); // GetWindowPos() + GetCursorPos() == GetCursorScreenPos() etc.) IMGUI_API void SetCursorPosX(float local_x); // GetWindowPos() + GetCursorPos() == GetCursorScreenPos() etc.)
IMGUI_API void SetCursorPosY(float local_y); // IMGUI_API void SetCursorPosY(float local_y); //
IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position in window coordinates IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position in window coordinates
IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates (useful to work with ImDrawList API). generally top-left == GetMainViewport()->Pos == (0,0) in single viewport mode, and bottom-right == GetMainViewport()->Pos+Size == io.DisplaySize in single-viewport mode.
IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute coordinates
IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item) IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item)
IMGUI_API float GetTextLineHeight(); // ~ FontSize IMGUI_API float GetTextLineHeight(); // ~ FontSize
IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text)
@ -787,6 +790,12 @@ namespace ImGui
IMGUI_API ImVec2 GetItemRectSize(); // get size of last item IMGUI_API ImVec2 GetItemRectSize(); // get size of last item
IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area.
// Viewports
// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
// - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports.
// - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode.
IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport.
// Miscellaneous Utilities // Miscellaneous Utilities
IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped.
IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side.
@ -1736,7 +1745,7 @@ struct ImGuiIO
ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc. ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc.
ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend. ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend.
ImVec2 DisplaySize; // <unset> // Main display size, in pixels. ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size)
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory. const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory.
@ -2334,7 +2343,8 @@ enum ImDrawListFlags_
// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to // Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to
// access the current window draw list and draw custom primitives. // access the current window draw list and draw custom primitives.
// You can interleave normal ImGui:: calls and adding primitives to the current draw list. // You can interleave normal ImGui:: calls and adding primitives to the current draw list.
// All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), but you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well) // In single viewport mode, top-left is == GetMainViewport()->Pos (generally 0,0), bottom-right is == GetMainViewport()->Pos+Size (generally io.DisplaySize).
// You are totally free to apply whatever transformation matrix to want to the data (depending on the use of the transformation you may want to apply it to ClipRect as well!)
// Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects. // Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects.
struct ImDrawList struct ImDrawList
{ {
@ -2465,8 +2475,8 @@ struct ImDrawData
int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size
int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size
ImDrawList** CmdLists; // Array of ImDrawList* to render. The ImDrawList are owned by ImGuiContext and only pointed to from here. ImDrawList** CmdLists; // Array of ImDrawList* to render. The ImDrawList are owned by ImGuiContext and only pointed to from here.
ImVec2 DisplayPos; // Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use) ImVec2 DisplayPos; // Top-left position of the viewport to render (== top-left of the orthogonal projection matrix to use) (== GetMainViewport()->Pos for the main viewport, == (0.0) in most single-viewport applications)
ImVec2 DisplaySize; // Size of the viewport to render (== io.DisplaySize for the main viewport) (DisplayPos + DisplaySize == lower-right of the orthogonal projection matrix to use) ImVec2 DisplaySize; // Size of the viewport to render (== GetMainViewport()->Size for the main viewport, == io.DisplaySize in most single-viewport applications)
ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display. ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display.
// Functions // Functions
@ -2724,6 +2734,43 @@ struct ImFont
IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last); IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last);
}; };
//-----------------------------------------------------------------------------
// [SECTION] Viewports
//-----------------------------------------------------------------------------
// Flags stored in ImGuiViewport::Flags
enum ImGuiViewportFlags_
{
ImGuiViewportFlags_None = 0,
ImGuiViewportFlags_IsPlatformWindow = 1 << 0, // Represent a Platform Window
ImGuiViewportFlags_IsPlatformMonitor = 1 << 1, // Represent a Platform Monitor (unused yet)
ImGuiViewportFlags_OwnedByApp = 1 << 2 // Platform Window: is created/managed by the application (rather than a dear imgui backend)
};
// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
// - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports.
// - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode.
// - About Main Area vs Work Area:
// - Main Area = entire viewport.
// - Work Area = entire viewport minus sections used by main menu bars (for platform windows), or by task bar (for platform monitor).
// - Windows are generally trying to stay within the Work Area of their host viewport.
struct ImGuiViewport
{
ImGuiViewportFlags Flags; // See ImGuiViewportFlags_
ImVec2 Pos; // Main Area: Position of the viewport (Dear Imgui coordinates are the same as OS desktop/native coordinates)
ImVec2 Size; // Main Area: Size of the viewport.
ImVec2 WorkPos; // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos)
ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size)
ImGuiViewport() { memset(this, 0, sizeof(*this)); }
// Helpers
ImVec2 GetCenter() const { return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); }
ImVec2 GetWorkCenter() const { return ImVec2(WorkPos.x + WorkSize.x * 0.5f, WorkPos.y + WorkSize.y * 0.5f); }
};
//-----------------------------------------------------------------------------
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#elif defined(__GNUC__) #elif defined(__GNUC__)

View File

@ -253,6 +253,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
// Examples Apps (accessible from the "Examples" menu) // Examples Apps (accessible from the "Examples" menu)
static bool show_app_main_menu_bar = false; static bool show_app_main_menu_bar = false;
static bool show_app_documents = false; static bool show_app_documents = false;
static bool show_app_console = false; static bool show_app_console = false;
static bool show_app_log = false; static bool show_app_log = false;
static bool show_app_layout = false; static bool show_app_layout = false;
@ -320,7 +321,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
// We specify a default position/size in case there's no data in the .ini file. // We specify a default position/size in case there's no data in the .ini file.
// We only do it to make the demo applications a little more welcoming, but typically this isn't required. // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
// Main body of the Demo window starts here. // Main body of the Demo window starts here.
@ -3231,7 +3233,7 @@ static void ShowDemoWindowPopups()
ImGui::OpenPopup("Delete?"); ImGui::OpenPopup("Delete?");
// Always center this window when appearing // Always center this window when appearing
ImVec2 center(ImGui::GetIO().DisplaySize.x * 0.5f, ImGui::GetIO().DisplaySize.y * 0.5f); ImVec2 center = ImGui::GetMainViewport()->GetCenter();
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
@ -6983,16 +6985,22 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
// + a context-menu to choose which corner of the screen to use. // + a context-menu to choose which corner of the screen to use.
static void ShowExampleAppSimpleOverlay(bool* p_open) static void ShowExampleAppSimpleOverlay(bool* p_open)
{ {
const float DISTANCE = 10.0f; const float PAD = 10.0f;
static int corner = 0; static int corner = 0;
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
if (corner != -1) if (corner != -1)
{ {
window_flags |= ImGuiWindowFlags_NoMove; const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImVec2 window_pos = ImVec2((corner & 1) ? io.DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? io.DisplaySize.y - DISTANCE : DISTANCE); ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); ImVec2 work_size = viewport->WorkSize;
ImVec2 window_pos, window_pos_pivot;
window_pos.x = (corner & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
window_pos.y = (corner & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
window_pos_pivot.x = (corner & 1) ? 1.0f : 0.0f;
window_pos_pivot.y = (corner & 2) ? 1.0f : 0.0f;
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
window_flags |= ImGuiWindowFlags_NoMove;
} }
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
if (ImGui::Begin("Example: Simple overlay", p_open, window_flags)) if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
@ -7024,12 +7032,21 @@ static void ShowExampleAppSimpleOverlay(bool* p_open)
// Demonstrate creating a window covering the entire screen/viewport // Demonstrate creating a window covering the entire screen/viewport
static void ShowExampleAppFullscreen(bool* p_open) static void ShowExampleAppFullscreen(bool* p_open)
{ {
ImGuiIO& io = ImGui::GetIO(); static bool use_work_area = true;
static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings; static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
ImGui::SetNextWindowPos(ImVec2(0, 0));
ImGui::SetNextWindowSize(io.DisplaySize); // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
// Based on your use case you may want one of the other.
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
if (ImGui::Begin("Example: Fullscreen window", p_open, flags)) if (ImGui::Begin("Example: Fullscreen window", p_open, flags))
{ {
ImGui::Checkbox("Use work area instead of main area", &use_work_area);
ImGui::SameLine();
HelpMarker("Main Area = entire viewport,\nWork Area = entire viewport minus sections used by the main menu bars, task bars etc.\n\nEnable the main-menu bar in Examples menu to see the difference.");
ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground); ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground);
ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration); ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration);
ImGui::Indent(); ImGui::Indent();
@ -7037,6 +7054,9 @@ static void ShowExampleAppFullscreen(bool* p_open)
ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse); ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse);
ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar); ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar);
ImGui::Unindent(); ImGui::Unindent();
if (p_open && ImGui::Button("Close this window"))
*p_open = false;
} }
ImGui::End(); ImGui::End();
} }
@ -7050,16 +7070,19 @@ static void ShowExampleAppFullscreen(bool* p_open)
// Read FAQ section "How can I have multiple widgets with the same label?" for details. // Read FAQ section "How can I have multiple widgets with the same label?" for details.
static void ShowExampleAppWindowTitles(bool*) static void ShowExampleAppWindowTitles(bool*)
{ {
const ImGuiViewport* viewport = ImGui::GetMainViewport();
const ImVec2 base_pos = viewport->Pos;
// By default, Windows are uniquely identified by their title. // By default, Windows are uniquely identified by their title.
// You can use the "##" and "###" markers to manipulate the display/ID. // You can use the "##" and "###" markers to manipulate the display/ID.
// Using "##" to display same title but have unique identifier. // Using "##" to display same title but have unique identifier.
ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 100), ImGuiCond_FirstUseEver);
ImGui::Begin("Same title as another window##1"); ImGui::Begin("Same title as another window##1");
ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique."); ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
ImGui::End(); ImGui::End();
ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 200), ImGuiCond_FirstUseEver);
ImGui::Begin("Same title as another window##2"); ImGui::Begin("Same title as another window##2");
ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique."); ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
ImGui::End(); ImGui::End();
@ -7067,7 +7090,7 @@ static void ShowExampleAppWindowTitles(bool*)
// Using "###" to display a changing title but keep a static identifier "AnimatedTitle" // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
char buf[128]; char buf[128];
sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount()); sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 300), ImGuiCond_FirstUseEver);
ImGui::Begin(buf); ImGui::Begin(buf);
ImGui::Text("This window has a changing title."); ImGui::Text("This window has a changing title.");
ImGui::End(); ImGui::End();

View File

@ -652,8 +652,9 @@ struct ImDrawDataBuilder
{ {
ImVector<ImDrawList*> Layers[2]; // Global layers for: regular, tooltip ImVector<ImDrawList*> Layers[2]; // Global layers for: regular, tooltip
void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); }
void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); } void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); }
int GetDrawListCount() const { int count = 0; for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) count += Layers[n].Size; return count; }
IMGUI_API void FlattenIntoSingleLayer(); IMGUI_API void FlattenIntoSingleLayer();
}; };
@ -1146,9 +1147,26 @@ struct ImGuiOldColumns
// [SECTION] Viewport support // [SECTION] Viewport support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef IMGUI_HAS_VIEWPORT // ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!)
// <this is filled in 'docking' branch> // Every instance of ImGuiViewport is in fact a ImGuiViewportP.
#endif // #ifdef IMGUI_HAS_VIEWPORT struct ImGuiViewportP : public ImGuiViewport
{
int DrawListsLastFrame[2]; // Last frame number the background (0) and foreground (1) draw lists were used
ImDrawList* DrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
ImDrawData DrawDataP;
ImDrawDataBuilder DrawDataBuilder;
ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!)
ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height).
ImVec2 CurrWorkOffsetMin; // Work Area: Offset being built/increased during current frame
ImVec2 CurrWorkOffsetMax; // Work Area: Offset being built/decreased during current frame
ImGuiViewportP() { DrawListsLastFrame[0] = DrawListsLastFrame[1] = -1; DrawLists[0] = DrawLists[1] = NULL; }
~ImGuiViewportP() { if (DrawLists[0]) IM_DELETE(DrawLists[0]); if (DrawLists[1]) IM_DELETE(DrawLists[1]); }
ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); }
void UpdateWorkRect() { WorkPos = ImVec2(Pos.x + WorkOffsetMin.x, Pos.y + WorkOffsetMin.y); WorkSize = ImVec2(ImMax(0.0f, Size.x - WorkOffsetMin.x + WorkOffsetMax.x), ImMax(0.0f, Size.y - WorkOffsetMin.y + WorkOffsetMax.y)); }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Settings support // [SECTION] Settings support
@ -1332,6 +1350,9 @@ struct ImGuiContext
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent) ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
// Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
// Gamepad/keyboard Navigation // Gamepad/keyboard Navigation
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow'
ImGuiID NavId; // Focused item for navigation ImGuiID NavId; // Focused item for navigation
@ -1389,11 +1410,7 @@ struct ImGuiContext
bool FocusTabPressed; // bool FocusTabPressed; //
// Render // Render
ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user
ImDrawDataBuilder DrawDataBuilder;
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
ImDrawList BackgroundDrawList; // First draw list to be rendered.
ImDrawList ForegroundDrawList; // Last draw list to be rendered. This is where we the render software mouse cursor (if io.MouseDrawCursor is set) and most debug overlays.
ImGuiMouseCursor MouseCursor; ImGuiMouseCursor MouseCursor;
// Drag and Drop // Drag and Drop
@ -1491,7 +1508,7 @@ struct ImGuiContext
int WantTextInputNextFrame; int WantTextInputNextFrame;
char TempBuffer[1024 * 3 + 1]; // Temporary text buffer char TempBuffer[1024 * 3 + 1]; // Temporary text buffer
ImGuiContext(ImFontAtlas* shared_font_atlas) : BackgroundDrawList(&DrawListSharedData), ForegroundDrawList(&DrawListSharedData) ImGuiContext(ImFontAtlas* shared_font_atlas)
{ {
Initialized = false; Initialized = false;
FontAtlasOwnedByContext = shared_font_atlas ? false : true; FontAtlasOwnedByContext = shared_font_atlas ? false : true;
@ -1580,8 +1597,6 @@ struct ImGuiContext
FocusTabPressed = false; FocusTabPressed = false;
DimBgRatio = 0.0f; DimBgRatio = 0.0f;
BackgroundDrawList._OwnerName = "##Background"; // Give it a name for debugging
ForegroundDrawList._OwnerName = "##Foreground"; // Give it a name for debugging
MouseCursor = ImGuiMouseCursor_Arrow; MouseCursor = ImGuiMouseCursor_Arrow;
DragDropActive = DragDropWithinSource = DragDropWithinTarget = false; DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
@ -2185,7 +2200,9 @@ namespace ImGui
// Fonts, drawing // Fonts, drawing
IMGUI_API void SetCurrentFont(ImFont* font); IMGUI_API void SetCurrentFont(ImFont* font);
inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); ImGuiContext& g = *GImGui; return &g.ForegroundDrawList; } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches.
IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport); // get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents.
IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents.
// Init // Init
IMGUI_API void Initialize(ImGuiContext* context); IMGUI_API void Initialize(ImGuiContext* context);
@ -2486,7 +2503,7 @@ namespace ImGui
IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns);
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label); IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label);
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb); IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label); IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label); IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
IMGUI_API void DebugNodeTable(ImGuiTable* table); IMGUI_API void DebugNodeTable(ImGuiTable* table);
@ -2494,6 +2511,8 @@ namespace ImGui
IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label);
IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings);
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label); IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);
IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport);
IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb);
} // namespace ImGui } // namespace ImGui

View File

@ -6569,18 +6569,39 @@ void ImGui::EndMenuBar()
window->DC.MenuBarAppending = false; window->DC.MenuBarAppending = false;
} }
// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
bool ImGui::BeginMainMenuBar() bool ImGui::BeginMainMenuBar()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport();
ImGuiWindow* menu_bar_window = FindWindowByName("##MainMenuBar");
// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)); g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
SetNextWindowPos(ImVec2(0.0f, 0.0f));
SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y)); // Get our rectangle at the top of the work area
if (menu_bar_window == NULL || menu_bar_window->BeginCount == 0)
{
// Set window position
// We don't attempt to calculate our height ahead, as it depends on the per-viewport font size.
// However menu-bar will affect the minimum window size so we'll get the right height.
ImVec2 menu_bar_pos = viewport->Pos + viewport->CurrWorkOffsetMin;
ImVec2 menu_bar_size = ImVec2(viewport->Size.x - viewport->CurrWorkOffsetMin.x + viewport->CurrWorkOffsetMax.x, 1.0f);
SetNextWindowPos(menu_bar_pos);
SetNextWindowSize(menu_bar_size);
}
// Create window
PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint, however the presence of a menu-bar will give us the minimum height we want.
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar(); bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar();
PopStyleVar(2); PopStyleVar(2);
// Report our size into work area (for next frame) using actual window size
menu_bar_window = GetCurrentWindow();
if (menu_bar_window->BeginCount == 1)
viewport->CurrWorkOffsetMin.y += menu_bar_window->Size.y;
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
if (!is_open) if (!is_open)
{ {