|
|
@@ -1161,6 +1161,7 @@ ImGuiStyle::ImGuiStyle()
|
|
|
WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
|
|
|
WindowMinSize = ImVec2(32,32); // Minimum window size
|
|
|
WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
|
|
|
+ WindowMenuButtonPosition= ImGuiDir_Left; // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left.
|
|
|
ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
|
|
|
ChildBorderSize = 1.0f; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
|
|
|
PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
|
|
|
@@ -3059,7 +3060,7 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
|
|
|
|
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
if (wrap_pos_x == 0.0f)
|
|
|
- wrap_pos_x = GetWorkRectMax().x;
|
|
|
+ wrap_pos_x = GetContentRegionMaxAbs().x;
|
|
|
else if (wrap_pos_x > 0.0f)
|
|
|
wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
|
|
|
|
|
|
@@ -3118,7 +3119,7 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx)
|
|
|
// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui.
|
|
|
// Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit
|
|
|
// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. your user code
|
|
|
-// may see different structures thanwhat imgui.cpp sees, which is problematic.
|
|
|
+// may see different structures than what imgui.cpp sees, which is problematic.
|
|
|
// We usually require settings to be in imconfig.h to make sure that they are accessible to all compilation units involved with Dear ImGui.
|
|
|
bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx)
|
|
|
{
|
|
|
@@ -3378,7 +3379,7 @@ static void TranslateWindow(ImGuiWindow* window, const ImVec2& delta)
|
|
|
window->Pos += delta;
|
|
|
window->ClipRect.Translate(delta);
|
|
|
window->OuterRectClipped.Translate(delta);
|
|
|
- window->InnerMainRect.Translate(delta);
|
|
|
+ window->InnerRect.Translate(delta);
|
|
|
window->DC.CursorPos += delta;
|
|
|
window->DC.CursorStartPos += delta;
|
|
|
window->DC.CursorMaxPos += delta;
|
|
|
@@ -3593,6 +3594,8 @@ void ImGui::NewFrame()
|
|
|
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
|
|
|
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!");
|
|
|
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
|
|
|
+ IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
|
|
|
+
|
|
|
for (int n = 0; n < ImGuiKey_COUNT; n++)
|
|
|
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
|
|
|
|
|
|
@@ -3683,6 +3686,13 @@ void ImGui::NewFrame()
|
|
|
virtual_space.Add(g.Viewports[n]->GetRect());
|
|
|
g.DrawListSharedData.ClipRectFullscreen = ImVec4(virtual_space.Min.x, virtual_space.Min.y, virtual_space.Max.x, virtual_space.Max.y);
|
|
|
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
|
|
|
+ g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
|
|
|
+ if (g.Style.AntiAliasedLines)
|
|
|
+ g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
|
|
|
+ if (g.Style.AntiAliasedFill)
|
|
|
+ g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
|
|
|
+ if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
|
|
|
+ g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
|
|
|
|
|
|
// Mark rendering data as invalid to prevent user who may have a handle on it to use it.
|
|
|
for (int n = 0; n < g.Viewports.Size; n++)
|
|
|
@@ -3986,19 +3996,28 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. May trigger for you if you are using PrimXXX functions incorrectly.
|
|
|
+ // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
|
|
+ // May trigger for you if you are using PrimXXX functions incorrectly.
|
|
|
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
|
|
|
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
|
|
|
- IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
|
|
|
+ if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset))
|
|
|
+ IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
|
|
|
|
|
|
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
|
|
|
// If this assert triggers because you are drawing lots of stuff manually:
|
|
|
- // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents.
|
|
|
- // B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes.
|
|
|
- // You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing:
|
|
|
- // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
|
|
- // Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API.
|
|
|
- // C) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists.
|
|
|
+ // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
|
|
+ // Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents.
|
|
|
+ // - If you want large meshes with more than 64K vertices, you can either:
|
|
|
+ // (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
|
|
|
+ // Most example back-ends already support this from 1.71. Pre-1.71 back-ends won't.
|
|
|
+ // Some graphics API such as GL ES 1/2 don't have a way to offset the starting vertex so it is not supported for them.
|
|
|
+ // (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
|
|
|
+ // Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time:
|
|
|
+ // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
|
|
+ // Your own engine or render API may use different parameters or function calls to specify index sizes.
|
|
|
+ // 2 and 4 bytes indices are generally supported by most graphics API.
|
|
|
+ // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
|
|
+ // the 64K limit to split your draw commands in multiple draw lists.
|
|
|
if (sizeof(ImDrawIdx) == 2)
|
|
|
IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
|
|
|
|
|
|
@@ -5323,6 +5342,8 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Draw background and borders
|
|
|
+// Draw and handle scrollbars
|
|
|
void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, bool handle_borders_and_resize_grips, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
@@ -5434,30 +5455,55 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Render title text, collapse button, close button
|
|
|
+// When inside a dock node, this is handled in DockNodeUpdateTabBar() instead.
|
|
|
void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiStyle& style = g.Style;
|
|
|
ImGuiWindowFlags flags = window->Flags;
|
|
|
|
|
|
- // Close & collapse button are on layer 1 (same as menus) and don't default focus
|
|
|
+ const bool has_close_button = (p_open != NULL);
|
|
|
+ const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse);
|
|
|
+
|
|
|
+ // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer)
|
|
|
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
|
|
|
window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
|
|
|
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
|
|
|
window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
|
|
|
|
|
|
- // Collapse button
|
|
|
- if (!(flags & ImGuiWindowFlags_NoCollapse))
|
|
|
- if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos, NULL))
|
|
|
- window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
|
|
|
+ // Layout buttons
|
|
|
+ // FIXME: Would be nice to generalize the subtleties expressed here into reusable code.
|
|
|
+ float pad_l = style.FramePadding.x;
|
|
|
+ float pad_r = style.FramePadding.x;
|
|
|
+ float button_sz = g.FontSize;
|
|
|
+ ImVec2 close_button_pos;
|
|
|
+ ImVec2 collapse_button_pos;
|
|
|
+ if (has_close_button)
|
|
|
+ {
|
|
|
+ pad_r += button_sz;
|
|
|
+ close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y);
|
|
|
+ }
|
|
|
+ if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right)
|
|
|
+ {
|
|
|
+ pad_r += button_sz;
|
|
|
+ collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y);
|
|
|
+ }
|
|
|
+ if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left)
|
|
|
+ {
|
|
|
+ collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l - style.FramePadding.x, title_bar_rect.Min.y);
|
|
|
+ pad_l += button_sz;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Collapse button (submitting first so it gets priority when choosing a navigation init fallback)
|
|
|
+ if (has_collapse_button)
|
|
|
+ if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos, NULL))
|
|
|
+ window->WantCollapseToggle = true; // Defer actual collapsing to next frame as we are too far in the Begin() function
|
|
|
|
|
|
// Close button
|
|
|
- if (p_open != NULL)
|
|
|
- {
|
|
|
- const float rad = g.FontSize * 0.5f;
|
|
|
- if (CloseButton(window->GetID("#CLOSE"), ImVec2(window->Pos.x + window->Size.x - style.FramePadding.x - rad, window->Pos.y + style.FramePadding.y + rad), rad + 1))
|
|
|
+ if (has_close_button)
|
|
|
+ if (CloseButton(window->GetID("#CLOSE"), close_button_pos))
|
|
|
*p_open = false;
|
|
|
- }
|
|
|
|
|
|
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
|
|
|
window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
|
|
|
@@ -5466,23 +5512,32 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
|
|
|
// Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
|
|
|
// FIXME: Refactor text alignment facilities along with RenderText helpers, this is too much code..
|
|
|
const char* UNSAVED_DOCUMENT_MARKER = "*";
|
|
|
- float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
|
|
|
- ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
|
|
|
- ImRect text_r = title_bar_rect;
|
|
|
- float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
|
|
|
- float pad_right = (p_open == NULL) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
|
|
|
- if (style.WindowTitleAlign.x > 0.0f)
|
|
|
- pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);
|
|
|
- text_r.Min.x += pad_left;
|
|
|
- text_r.Max.x -= pad_right;
|
|
|
- ImRect clip_rect = text_r;
|
|
|
- clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton()
|
|
|
- RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);
|
|
|
+ const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
|
|
|
+ const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
|
|
|
+
|
|
|
+ // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button,
|
|
|
+ // while uncentered title text will still reach edges correct.
|
|
|
+ if (pad_l > style.FramePadding.x)
|
|
|
+ pad_l += g.Style.ItemInnerSpacing.x;
|
|
|
+ if (pad_r > style.FramePadding.x)
|
|
|
+ pad_r += g.Style.ItemInnerSpacing.x;
|
|
|
+ if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f)
|
|
|
+ {
|
|
|
+ float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f); // 0.0f on either edges, 1.0f on center
|
|
|
+ float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x);
|
|
|
+ pad_l = ImMax(pad_l, pad_extend * centerness);
|
|
|
+ pad_r = ImMax(pad_r, pad_extend * centerness);
|
|
|
+ }
|
|
|
+
|
|
|
+ ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y);
|
|
|
+ ImRect clip_r(layout_r.Min.x, layout_r.Min.y, layout_r.Max.x + g.Style.ItemInnerSpacing.x, layout_r.Max.y);
|
|
|
+ //if (g.IO.KeyCtrl) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]
|
|
|
+ RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
|
|
|
if (flags & ImGuiWindowFlags_UnsavedDocument)
|
|
|
{
|
|
|
- ImVec2 marker_pos = ImVec2(ImMax(text_r.Min.x, text_r.Min.x + (text_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, text_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
|
|
|
+ ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
|
|
|
ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f));
|
|
|
- RenderTextClipped(marker_pos + off, text_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_rect);
|
|
|
+ RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -5970,49 +6025,55 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
// Store a backup of SizeFull which we will use next frame to decide if we need scrollbars.
|
|
|
window->SizeFullAtLastBegin = window->SizeFull;
|
|
|
|
|
|
- // UPDATE RECTANGLES
|
|
|
+ // UPDATE RECTANGLES (1- THOSE NOT AFFECTED BY SCROLLING)
|
|
|
+ // Update various regions. Variables they depends on should be set above in this function.
|
|
|
+ // We set this up after processing the resize grip so that our rectangles doesn't lag by a frame.
|
|
|
|
|
|
- // Update various regions. Variables they depends on are set above in this function.
|
|
|
- // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
|
|
|
- // NB: WindowBorderSize is included in WindowPadding _and_ ScrollbarSizes so we need to cancel one out.
|
|
|
- window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
|
|
|
- window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();
|
|
|
- window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x + ImMin(window->ScrollbarSizes.x, window->WindowBorderSize)));
|
|
|
- window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y + ImMin(window->ScrollbarSizes.y, window->WindowBorderSize)));
|
|
|
-
|
|
|
- // Inner rectangle
|
|
|
- // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
|
|
|
- // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
|
|
|
- const ImRect title_bar_rect = window->TitleBarRect();
|
|
|
- window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
|
|
|
- window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
|
|
|
- window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - ImMax(window->ScrollbarSizes.x, window->WindowBorderSize);
|
|
|
- window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - ImMax(window->ScrollbarSizes.y, window->WindowBorderSize);
|
|
|
-
|
|
|
- // Outer host rectangle for drawing background and borders
|
|
|
+ // Outer rectangle
|
|
|
+ // Not affected by window border size. Used by:
|
|
|
+ // - FindHoveredWindow() (w/ extra padding when border resize is enabled)
|
|
|
+ // - Begin() initial clipping rect for drawing window background and borders.
|
|
|
+ // - Begin() clipping whole child
|
|
|
ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
|
|
|
-
|
|
|
- // Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
|
|
|
window->OuterRectClipped = window->Rect();
|
|
|
if (window->DockIsActive)
|
|
|
window->OuterRectClipped.Min.y += window->TitleBarHeight();
|
|
|
window->OuterRectClipped.ClipWith(host_rect);
|
|
|
|
|
|
- // Inner work/clipping rectangle will extend a little bit outside the work region.
|
|
|
+ // Inner rectangle
|
|
|
+ // Used by:
|
|
|
+ // - NavScrollToBringItemIntoView()
|
|
|
+ // - NavUpdatePageUpPageDown()
|
|
|
+ // - Scrollbar()
|
|
|
+ const ImRect title_bar_rect = window->TitleBarRect();
|
|
|
+ window->InnerRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
|
|
|
+ window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
|
|
|
+ window->InnerRect.Max.x = window->Pos.x + window->Size.x - ImMax(window->ScrollbarSizes.x, window->WindowBorderSize);
|
|
|
+ window->InnerRect.Max.y = window->Pos.y + window->Size.y - ImMax(window->ScrollbarSizes.y, window->WindowBorderSize);
|
|
|
+
|
|
|
+ // Work rectangle.
|
|
|
+ // Affected by window padding and border size. Used by:
|
|
|
+ // - Columns() for right-most edge
|
|
|
+ // - BeginTabBar() for right-most edge
|
|
|
+ window->WorkRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
|
|
+ window->WorkRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y);
|
|
|
+ window->WorkRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
|
|
+ window->WorkRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y);
|
|
|
+
|
|
|
+ // Inner clipping rectangle.
|
|
|
+ // Will extend a little bit outside the normal work region.
|
|
|
// This is to allow e.g. Selectable or CollapsingHeader or some separators to cover that space.
|
|
|
// Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
|
|
|
- window->InnerWorkRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
|
|
- window->InnerWorkRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
|
|
|
- window->InnerWorkRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
|
|
- window->InnerWorkRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
|
|
|
- window->InnerWorkRectClipped = window->InnerWorkRect;
|
|
|
- window->InnerWorkRectClipped.ClipWithFull(host_rect);
|
|
|
+ // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
|
|
|
+ // Affected by window/frame border size. Used by:
|
|
|
+ // - Begin() initial clip rect
|
|
|
+ window->InnerClipRect = window->WorkRect;
|
|
|
+ window->InnerClipRect.ClipWithFull(host_rect);
|
|
|
|
|
|
// DRAWING
|
|
|
|
|
|
// Setup draw list and outer clipping rectangle
|
|
|
window->DrawList->Clear();
|
|
|
- window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
|
|
|
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
|
|
PushClipRect(host_rect.Min, host_rect.Max, false);
|
|
|
|
|
|
@@ -6038,6 +6099,19 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
const bool title_bar_is_highlight = want_focus || (window_to_highlight && (window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight || (window->DockNode && window->DockNode == window_to_highlight->DockNode)));
|
|
|
RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips, resize_grip_count, resize_grip_col, resize_grip_draw_size);
|
|
|
|
|
|
+ // UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING)
|
|
|
+
|
|
|
+ // [LEGACY] Contents Region
|
|
|
+ // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
|
|
|
+ // NB: WindowBorderSize is included in WindowPadding _and_ ScrollbarSizes so we need to cancel one out when we have both.
|
|
|
+ // Used by:
|
|
|
+ // - Mouse wheel scrolling
|
|
|
+ // - ... (many things)
|
|
|
+ window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
|
|
|
+ window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();
|
|
|
+ window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x + ImMin(window->ScrollbarSizes.x, window->WindowBorderSize)));
|
|
|
+ window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y + ImMin(window->ScrollbarSizes.y, window->WindowBorderSize)));
|
|
|
+
|
|
|
// Setup drawing context
|
|
|
// (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.)
|
|
|
window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
|
|
|
@@ -6161,7 +6235,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
}
|
|
|
|
|
|
if (!(flags & ImGuiWindowFlags_DockNodeHost))
|
|
|
- PushClipRect(window->InnerWorkRectClipped.Min, window->InnerWorkRectClipped.Max, true);
|
|
|
+ PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
|
|
|
|
|
|
// Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
|
|
|
if (first_begin_of_the_frame)
|
|
|
@@ -6433,7 +6507,7 @@ float ImGui::CalcItemWidth()
|
|
|
w = window->DC.ItemWidth;
|
|
|
if (w < 0.0f)
|
|
|
{
|
|
|
- float region_max_x = GetWorkRectMax().x;
|
|
|
+ float region_max_x = GetContentRegionMaxAbs().x;
|
|
|
w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w);
|
|
|
}
|
|
|
w = (float)(int)w;
|
|
|
@@ -6450,7 +6524,7 @@ ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h)
|
|
|
|
|
|
ImVec2 region_max;
|
|
|
if (size.x < 0.0f || size.y < 0.0f)
|
|
|
- region_max = GetWorkRectMax();
|
|
|
+ region_max = GetContentRegionMaxAbs();
|
|
|
|
|
|
if (size.x == 0.0f)
|
|
|
size.x = default_w;
|
|
|
@@ -7094,7 +7168,7 @@ ImVec2 ImGui::GetContentRegionMax()
|
|
|
}
|
|
|
|
|
|
// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features.
|
|
|
-ImVec2 ImGui::GetWorkRectMax()
|
|
|
+ImVec2 ImGui::GetContentRegionMaxAbs()
|
|
|
{
|
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
ImVec2 mx = window->ContentsRegionRect.Max;
|
|
|
@@ -7106,7 +7180,7 @@ ImVec2 ImGui::GetWorkRectMax()
|
|
|
ImVec2 ImGui::GetContentRegionAvail()
|
|
|
{
|
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
|
- return GetWorkRectMax() - window->DC.CursorPos;
|
|
|
+ return GetContentRegionMaxAbs() - window->DC.CursorPos;
|
|
|
}
|
|
|
|
|
|
// In window space (not screen space!)
|
|
|
@@ -8458,7 +8532,7 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput
|
|
|
// NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated.
|
|
|
static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect)
|
|
|
{
|
|
|
- ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1));
|
|
|
+ ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1));
|
|
|
//GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
|
|
|
if (window_rect.Contains(item_rect))
|
|
|
return;
|
|
|
@@ -8732,7 +8806,7 @@ static void ImGui::NavUpdate()
|
|
|
if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0)
|
|
|
{
|
|
|
ImGuiWindow* window = g.NavWindow;
|
|
|
- ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1,1), window->InnerMainRect.Max - window->Pos + ImVec2(1,1));
|
|
|
+ ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1,1), window->InnerRect.Max - window->Pos + ImVec2(1,1));
|
|
|
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
|
|
|
{
|
|
|
float pad = window->CalcFontSize() * 0.5f;
|
|
|
@@ -8833,14 +8907,14 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
|
|
{
|
|
|
// Fallback manual-scroll when window has no navigable item
|
|
|
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
|
|
- SetWindowScrollY(window, window->Scroll.y - window->InnerMainRect.GetHeight());
|
|
|
+ SetWindowScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
|
|
|
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
|
|
- SetWindowScrollY(window, window->Scroll.y + window->InnerMainRect.GetHeight());
|
|
|
+ SetWindowScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
|
|
- const float page_offset_y = ImMax(0.0f, window->InnerMainRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
|
|
+ const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
|
|
float nav_scoring_rect_offset_y = 0.0f;
|
|
|
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
|
|
{
|
|
|
@@ -9328,7 +9402,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
|
|
|
window->DC.CurrentColumns = columns;
|
|
|
|
|
|
// Set state for first column
|
|
|
- const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerWorkRect.Max.x - window->Pos.x);
|
|
|
+ const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->WorkRect.Max.x - window->Pos.x);
|
|
|
columns->OffMinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range
|
|
|
columns->OffMaxX = ImMax(content_region_width - window->Scroll.x, columns->OffMinX + 1.0f);
|
|
|
columns->HostCursorPosY = window->DC.CursorPos.y;
|
|
|
@@ -11028,18 +11102,16 @@ struct ImGuiDockPreviewData
|
|
|
// Persistent Settings data, stored contiguously in SettingsNodes (sizeof() ~32 bytes)
|
|
|
struct ImGuiDockNodeSettings
|
|
|
{
|
|
|
- ImGuiID ID;
|
|
|
- ImGuiID ParentID;
|
|
|
- ImGuiID SelectedTabID;
|
|
|
- signed char SplitAxis;
|
|
|
- char Depth;
|
|
|
- char IsDockSpace;
|
|
|
- char IsCentralNode;
|
|
|
- char IsHiddenTabBar;
|
|
|
- ImVec2ih Pos;
|
|
|
- ImVec2ih Size;
|
|
|
- ImVec2ih SizeRef;
|
|
|
- ImGuiDockNodeSettings() { ID = ParentID = SelectedTabID = 0; SplitAxis = ImGuiAxis_None; Depth = 0; IsDockSpace = IsCentralNode = IsHiddenTabBar = 0; }
|
|
|
+ ImGuiID ID;
|
|
|
+ ImGuiID ParentID;
|
|
|
+ ImGuiID SelectedTabID;
|
|
|
+ signed char SplitAxis;
|
|
|
+ char Depth;
|
|
|
+ ImGuiDockNodeFlags Flags; // NB: We save individual flags one by one in ascii format (ImGuiDockNodeFlags_SavedFlagsMask_)
|
|
|
+ ImVec2ih Pos;
|
|
|
+ ImVec2ih Size;
|
|
|
+ ImVec2ih SizeRef;
|
|
|
+ ImGuiDockNodeSettings() { ID = ParentID = SelectedTabID = 0; SplitAxis = ImGuiAxis_None; Depth = 0; Flags = ImGuiDockNodeFlags_None; }
|
|
|
};
|
|
|
|
|
|
struct ImGuiDockContext
|
|
|
@@ -11083,13 +11155,13 @@ namespace ImGui
|
|
|
static void DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window);
|
|
|
static void DockNodeAddTabBar(ImGuiDockNode* node);
|
|
|
static void DockNodeRemoveTabBar(ImGuiDockNode* node);
|
|
|
- static ImGuiID DockNodeUpdateTabListMenu(ImGuiDockNode* node, ImGuiTabBar* tab_bar);
|
|
|
+ static ImGuiID DockNodeUpdateWindowMenu(ImGuiDockNode* node, ImGuiTabBar* tab_bar);
|
|
|
static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
|
|
|
static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window);
|
|
|
static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_window);
|
|
|
static void DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockPreviewData* preview_data, bool is_explicit_target, bool is_outer_docking);
|
|
|
static void DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, const ImGuiDockPreviewData* preview_data);
|
|
|
- static ImRect DockNodeCalcTabBarRect(const ImGuiDockNode* node);
|
|
|
+ static void DockNodeCalcTabBarLayout(const ImGuiDockNode* node, ImRect* out_title_rect, ImRect* out_tab_bar_rect, ImVec2* out_window_menu_button_pos);
|
|
|
static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired);
|
|
|
static bool DockNodeCalcDropRectsAndTestMousePos(const ImRect& parent, ImGuiDir dir, ImRect& out_draw, bool outer_docking, ImVec2* test_mouse_pos);
|
|
|
static const char* DockNodeGetHostWindowTitle(ImGuiDockNode* node, char* buf, int buf_size) { ImFormatString(buf, buf_size, "##DockNode_%02X", node->ID); return buf; }
|
|
|
@@ -11357,7 +11429,7 @@ static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
|
|
|
ImGuiDockContextPruneNodeData* data_root = (data->RootID == settings->ID) ? data : pool.GetByKey(data->RootID);
|
|
|
|
|
|
bool remove = false;
|
|
|
- remove |= (data->CountWindows == 1 && settings->ParentID == 0 && data->CountChildNodes == 0 && !settings->IsCentralNode); // Floating root node with only 1 window
|
|
|
+ remove |= (data->CountWindows == 1 && settings->ParentID == 0 && data->CountChildNodes == 0 && !(settings->Flags & ImGuiDockNodeFlags_CentralNode)); // Floating root node with only 1 window
|
|
|
remove |= (data->CountWindows == 0 && settings->ParentID == 0 && data->CountChildNodes == 0); // Leaf nodes with 0 window
|
|
|
remove |= (data_root->CountChildWindows == 0);
|
|
|
if (remove)
|
|
|
@@ -11388,12 +11460,7 @@ static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDoc
|
|
|
node->ParentNode->ChildNodes[1] = node;
|
|
|
node->SelectedTabID = settings->SelectedTabID;
|
|
|
node->SplitAxis = settings->SplitAxis;
|
|
|
- if (settings->IsDockSpace)
|
|
|
- node->LocalFlags |= ImGuiDockNodeFlags_DockSpace;
|
|
|
- if (settings->IsCentralNode)
|
|
|
- node->LocalFlags |= ImGuiDockNodeFlags_CentralNode;
|
|
|
- if (settings->IsHiddenTabBar)
|
|
|
- node->LocalFlags |= ImGuiDockNodeFlags_HiddenTabBar;
|
|
|
+ node->LocalFlags |= (settings->Flags & ImGuiDockNodeFlags_SavedFlagsMask_);
|
|
|
|
|
|
// Bind host window immediately if it already exist (in case of a rebuild)
|
|
|
// This is useful as the RootWindowForTitleBarHighlight links necessary to highlight the currently focused node requires node->HostWindow to be set.
|
|
|
@@ -11677,7 +11744,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
|
|
|
AuthorityForPos = AuthorityForSize = ImGuiDataAuthority_DockNode;
|
|
|
AuthorityForViewport = ImGuiDataAuthority_Auto;
|
|
|
IsVisible = true;
|
|
|
- IsFocused = HasCloseButton = HasCollapseButton = false;
|
|
|
+ IsFocused = HasCloseButton = HasWindowMenuButton = EnableCloseButton = false;
|
|
|
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false;
|
|
|
}
|
|
|
|
|
|
@@ -12076,7 +12143,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
DockNodeHideHostWindow(node);
|
|
|
node->WantCloseAll = false;
|
|
|
node->WantCloseTabID = 0;
|
|
|
- node->HasCloseButton = node->HasCollapseButton = false;
|
|
|
+ node->HasCloseButton = node->HasWindowMenuButton = node->EnableCloseButton = false;
|
|
|
node->LastFrameActive = g.FrameCount;
|
|
|
|
|
|
if (node->WantMouseMove && node->Windows.Size == 1)
|
|
|
@@ -12084,27 +12151,31 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
|
|
|
+
|
|
|
ImGuiWindow* host_window = NULL;
|
|
|
bool beginned_into_host_window = false;
|
|
|
if (node->IsDockSpace())
|
|
|
{
|
|
|
// [Explicit root dockspace node]
|
|
|
IM_ASSERT(node->HostWindow);
|
|
|
- node->HasCloseButton = false;
|
|
|
- node->HasCollapseButton = true;
|
|
|
+ node->EnableCloseButton = false;
|
|
|
+ node->HasCloseButton = (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
|
|
|
+ node->HasWindowMenuButton = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
|
|
|
host_window = node->HostWindow;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// [Automatic root or child nodes]
|
|
|
- node->HasCloseButton = false;
|
|
|
- node->HasCollapseButton = (node->Windows.Size > 0);
|
|
|
+ node->EnableCloseButton = false;
|
|
|
+ node->HasCloseButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
|
|
|
+ node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
|
|
|
for (int window_n = 0; window_n < node->Windows.Size; window_n++)
|
|
|
{
|
|
|
// FIXME-DOCK: Setting DockIsActive here means that for single active window in a leaf node, DockIsActive will be cleared until the next Begin() call.
|
|
|
ImGuiWindow* window = node->Windows[window_n];
|
|
|
window->DockIsActive = (node->Windows.Size > 1);
|
|
|
- node->HasCloseButton |= window->HasCloseButton;
|
|
|
+ node->EnableCloseButton |= window->HasCloseButton;
|
|
|
}
|
|
|
|
|
|
if (node->IsRootNode() && node->IsVisible)
|
|
|
@@ -12181,7 +12252,6 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
|
|
|
// We need to draw a background at the root level if requested by ImGuiDockNodeFlags_PassthruCentralNode, but we will only know the correct pos/size after
|
|
|
// processing the resizing splitters. So we are using the DrawList channel splitting facility to submit drawing primitives out of order!
|
|
|
- const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
|
|
|
const bool render_dockspace_bg = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0;
|
|
|
if (render_dockspace_bg)
|
|
|
{
|
|
|
@@ -12283,12 +12353,16 @@ static int IMGUI_CDECL TabItemComparerByDockOrder(const void* lhs, const void* r
|
|
|
return (a->BeginOrderWithinContext - b->BeginOrderWithinContext);
|
|
|
}
|
|
|
|
|
|
-static ImGuiID ImGui::DockNodeUpdateTabListMenu(ImGuiDockNode* node, ImGuiTabBar* tab_bar)
|
|
|
+static ImGuiID ImGui::DockNodeUpdateWindowMenu(ImGuiDockNode* node, ImGuiTabBar* tab_bar)
|
|
|
{
|
|
|
// Try to position the menu so it is more likely to stays within the same viewport
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
ImGuiID ret_tab_id = 0;
|
|
|
- SetNextWindowPos(ImVec2(node->Pos.x, node->Pos.y + GetFrameHeight()));
|
|
|
- if (BeginPopup("#TabListMenu"))
|
|
|
+ if (g.Style.WindowMenuButtonPosition == ImGuiDir_Left)
|
|
|
+ SetNextWindowPos(ImVec2(node->Pos.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(0.0f, 0.0f));
|
|
|
+ else
|
|
|
+ SetNextWindowPos(ImVec2(node->Pos.x + node->Size.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always, ImVec2(1.0f, 0.0f));
|
|
|
+ if (BeginPopup("#WindowMenu"))
|
|
|
{
|
|
|
node->IsFocused = true;
|
|
|
if (tab_bar->Tabs.Size == 1)
|
|
|
@@ -12374,27 +12448,38 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
|
|
|
ImGuiID focus_tab_id = 0;
|
|
|
node->IsFocused = is_focused;
|
|
|
|
|
|
- // Collapse button changes shape and display a list
|
|
|
- // FIXME-DOCK: Could we recycle popups id?
|
|
|
- if (IsPopupOpen("#TabListMenu"))
|
|
|
+ const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
|
|
|
+ const bool has_window_menu_button = (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
|
|
|
+ const bool has_close_button = (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0;
|
|
|
+
|
|
|
+ // In a dock node, the Collapse Button turns into the Window Menu button.
|
|
|
+ // FIXME-DOCK FIXME-OPT: Could we recycle popups id accross multiple dock nodes?
|
|
|
+ if (has_window_menu_button && IsPopupOpen("#WindowMenu"))
|
|
|
{
|
|
|
- if (ImGuiID tab_id = DockNodeUpdateTabListMenu(node, tab_bar))
|
|
|
+ if (ImGuiID tab_id = DockNodeUpdateWindowMenu(node, tab_bar))
|
|
|
focus_tab_id = tab_bar->NextSelectedTabId = tab_id;
|
|
|
is_focused |= node->IsFocused;
|
|
|
}
|
|
|
|
|
|
+ // Layout
|
|
|
+ ImRect title_bar_rect, tab_bar_rect;
|
|
|
+ ImVec2 window_menu_button_pos;
|
|
|
+ DockNodeCalcTabBarLayout(node, &title_bar_rect, &tab_bar_rect, &window_menu_button_pos);
|
|
|
+
|
|
|
// Title bar
|
|
|
if (is_focused)
|
|
|
node->LastFrameFocused = g.FrameCount;
|
|
|
- ImRect title_bar_rect = ImRect(node->Pos, node->Pos + ImVec2(node->Size.x, g.FontSize + style.FramePadding.y * 2.0f));
|
|
|
ImU32 title_bar_col = GetColorU32(host_window->Collapsed ? ImGuiCol_TitleBgCollapsed : is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
|
|
|
host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, host_window->WindowRounding, ImDrawCornerFlags_Top);
|
|
|
|
|
|
- // Collapse button
|
|
|
- if (CollapseButton(host_window->GetID("#COLLAPSE"), title_bar_rect.Min, node))
|
|
|
- OpenPopup("#TabListMenu");
|
|
|
- if (IsItemActive())
|
|
|
- focus_tab_id = tab_bar->SelectedTabId;
|
|
|
+ // Docking/Collapse button
|
|
|
+ if (has_window_menu_button)
|
|
|
+ {
|
|
|
+ if (CollapseButton(host_window->GetID("#COLLAPSE"), window_menu_button_pos, node))
|
|
|
+ OpenPopup("#WindowMenu");
|
|
|
+ if (IsItemActive())
|
|
|
+ focus_tab_id = tab_bar->SelectedTabId;
|
|
|
+ }
|
|
|
|
|
|
// Submit new tabs and apply NavWindow focus back to the tab bar. They will be added as Unsorted and sorted below based on relative DockOrder value.
|
|
|
const int tabs_count_old = tab_bar->Tabs.Size;
|
|
|
@@ -12425,7 +12510,6 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
|
|
|
tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = tab_bar->Tabs.back().Window->ID;
|
|
|
|
|
|
// Begin tab bar
|
|
|
- const ImRect tab_bar_rect = DockNodeCalcTabBarRect(node);
|
|
|
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs; // | ImGuiTabBarFlags_NoTabListScrollingButtons);
|
|
|
tab_bar_flags |= ImGuiTabBarFlags_SaveSettings | ImGuiTabBarFlags_DockNode;
|
|
|
if (!host_window->Collapsed && is_focused)
|
|
|
@@ -12472,15 +12556,15 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
|
|
|
|
|
|
// Close button (after VisibleWindow was updated)
|
|
|
// Note that VisibleWindow may have been overrided by CTRL+Tabbing, so VisibleWindow->ID may be != from tab_bar->SelectedTabId
|
|
|
- if (node->VisibleWindow)
|
|
|
+ if (has_close_button && node->VisibleWindow)
|
|
|
{
|
|
|
if (!node->VisibleWindow->HasCloseButton)
|
|
|
{
|
|
|
PushItemFlag(ImGuiItemFlags_Disabled, true);
|
|
|
PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.5f));
|
|
|
}
|
|
|
- const float rad = g.FontSize * 0.5f;
|
|
|
- if (CloseButton(host_window->GetID("#CLOSE"), title_bar_rect.GetTR() + ImVec2(-style.FramePadding.x - rad, style.FramePadding.y + rad), rad + 1))
|
|
|
+ const float button_sz = g.FontSize;
|
|
|
+ if (CloseButton(host_window->GetID("#CLOSE"), title_bar_rect.GetTR() + ImVec2(-style.FramePadding.x * 2.0f - button_sz, 0.0f)))
|
|
|
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_bar->VisibleTabId))
|
|
|
{
|
|
|
node->WantCloseTabID = tab->ID;
|
|
|
@@ -12585,15 +12669,32 @@ static bool ImGui::DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow*
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static ImRect ImGui::DockNodeCalcTabBarRect(const ImGuiDockNode* node)
|
|
|
+// window menu button == collapse button when not in a dock node.
|
|
|
+// FIXME: This is similar to RenderWindowTitleBarContents, may want to share code.
|
|
|
+static void ImGui::DockNodeCalcTabBarLayout(const ImGuiDockNode* node, ImRect* out_title_rect, ImRect* out_tab_bar_rect, ImVec2* out_window_menu_button_pos)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- ImRect r = ImRect(node->Pos.x, node->Pos.y, node->Pos.x + node->Size.x, node->Pos.y + (g.FontSize + g.Style.FramePadding.y * 2.0f));
|
|
|
- if (node->HasCollapseButton)
|
|
|
- r.Min.x += g.Style.FramePadding.x + g.FontSize; // + g.Style.ItemInnerSpacing.x; // <-- Adding ItemInnerSpacing makes the title text moves slightly when in a tab bar. Instead we adjusted RenderArrowDockMenu()
|
|
|
- // In DockNodeUpdateTabBar() we currently display a disabled close button even if there is none.
|
|
|
- r.Max.x -= g.Style.FramePadding.x + g.FontSize + 1.0f;
|
|
|
- return r;
|
|
|
+ ImRect r = ImRect(node->Pos.x, node->Pos.y, node->Pos.x + node->Size.x, node->Pos.y + g.FontSize + g.Style.FramePadding.y * 2.0f);
|
|
|
+ if (out_title_rect) { *out_title_rect = r; }
|
|
|
+
|
|
|
+ ImVec2 window_menu_button_pos = r.Min;
|
|
|
+ r.Min.x += g.Style.FramePadding.x;
|
|
|
+ r.Max.x -= g.Style.FramePadding.x;
|
|
|
+ if (node->HasCloseButton)
|
|
|
+ {
|
|
|
+ r.Max.x -= g.FontSize;// +1.0f; // In DockNodeUpdateTabBar() we currently display a disabled close button even if there is none.
|
|
|
+ }
|
|
|
+ if (node->HasWindowMenuButton && g.Style.WindowMenuButtonPosition == ImGuiDir_Left)
|
|
|
+ {
|
|
|
+ r.Min.x += g.FontSize; // + g.Style.ItemInnerSpacing.x; // <-- Adding ItemInnerSpacing makes the title text moves slightly when in a docking tab bar. Instead we adjusted RenderArrowDockMenu()
|
|
|
+ }
|
|
|
+ else if (node->HasWindowMenuButton && g.Style.WindowMenuButtonPosition == ImGuiDir_Right)
|
|
|
+ {
|
|
|
+ r.Max.x -= g.FontSize + g.Style.FramePadding.x;
|
|
|
+ window_menu_button_pos = ImVec2(r.Max.x, r.Min.y);
|
|
|
+ }
|
|
|
+ if (out_tab_bar_rect) { *out_tab_bar_rect = r; }
|
|
|
+ if (out_window_menu_button_pos) { *out_window_menu_button_pos = window_menu_button_pos; }
|
|
|
}
|
|
|
|
|
|
void ImGui::DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired)
|
|
|
@@ -12696,7 +12797,7 @@ static void ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNo
|
|
|
|
|
|
// Build a tentative future node (reuse same structure because it is practical)
|
|
|
data->FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (root_payload->HasCloseButton);
|
|
|
- data->FutureNode.HasCollapseButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0);
|
|
|
+ data->FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0);
|
|
|
data->FutureNode.Pos = host_node ? ref_node_for_rect->Pos : host_window->Pos;
|
|
|
data->FutureNode.Size = host_node ? ref_node_for_rect->Size : host_window->Size;
|
|
|
|
|
|
@@ -12796,7 +12897,8 @@ static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDock
|
|
|
if (data->IsDropAllowed && can_preview_tabs && data->SplitDir == ImGuiDir_None && data->IsCenterAvailable)
|
|
|
{
|
|
|
// Compute target tab bar geometry so we can locate our preview tabs
|
|
|
- ImRect tab_bar_rect = DockNodeCalcTabBarRect(&data->FutureNode);
|
|
|
+ ImRect tab_bar_rect;
|
|
|
+ DockNodeCalcTabBarLayout(&data->FutureNode, NULL, &tab_bar_rect, NULL);
|
|
|
ImVec2 tab_pos = tab_bar_rect.Min;
|
|
|
if (host_node && host_node->TabBar)
|
|
|
{
|
|
|
@@ -13427,7 +13529,7 @@ void ImGui::DockBuilderRemoveNode(ImGuiID node_id)
|
|
|
DockBuilderRemoveNodeDockedWindows(node_id, true);
|
|
|
DockBuilderRemoveNodeChildNodes(node_id);
|
|
|
if (node->IsCentralNode() && node->ParentNode)
|
|
|
- node->ParentNode->LocalFlags = ImGuiDockNodeFlags_CentralNode;
|
|
|
+ node->ParentNode->LocalFlags |= ImGuiDockNodeFlags_CentralNode;
|
|
|
DockContextRemoveNode(ctx, node, true);
|
|
|
}
|
|
|
|
|
|
@@ -14004,10 +14106,11 @@ static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettings
|
|
|
// Parsing, e.g.
|
|
|
// " DockNode ID=0x00000001 Pos=383,193 Size=201,322 Split=Y,0.506 "
|
|
|
// " DockNode ID=0x00000002 Parent=0x00000001 "
|
|
|
+ // Important: this code expect currently fields in a fixed order.
|
|
|
ImGuiDockNodeSettings node;
|
|
|
line = ImStrSkipBlank(line);
|
|
|
if (strncmp(line, "DockNode", 8) == 0) { line = ImStrSkipBlank(line + strlen("DockNode")); }
|
|
|
- else if (strncmp(line, "DockSpace", 9) == 0) { line = ImStrSkipBlank(line + strlen("DockSpace")); node.IsDockSpace = true; }
|
|
|
+ else if (strncmp(line, "DockSpace", 9) == 0) { line = ImStrSkipBlank(line + strlen("DockSpace")); node.Flags |= ImGuiDockNodeFlags_DockSpace; }
|
|
|
else return;
|
|
|
if (sscanf(line, "ID=0x%08X%n", &node.ID, &r) == 1) { line += r; } else return;
|
|
|
if (sscanf(line, " Parent=0x%08X%n", &node.ParentID, &r) == 1) { line += r; if (node.ParentID == 0) return; }
|
|
|
@@ -14021,8 +14124,12 @@ static void ImGui::DockSettingsHandler_ReadLine(ImGuiContext* ctx, ImGuiSettings
|
|
|
if (sscanf(line, " SizeRef=%i,%i%n", &x, &y, &r) == 2) { line += r; node.SizeRef = ImVec2ih((short)x, (short)y); }
|
|
|
}
|
|
|
if (sscanf(line, " Split=%c%n", &c, &r) == 1) { line += r; if (c == 'X') node.SplitAxis = ImGuiAxis_X; else if (c == 'Y') node.SplitAxis = ImGuiAxis_Y; }
|
|
|
- if (sscanf(line, " CentralNode=%d%n", &x, &r) == 1) { line += r; node.IsCentralNode = (x != 0); }
|
|
|
- if (sscanf(line, " HiddenTabBar=%d%n", &x, &r) == 1) { line += r; node.IsHiddenTabBar = (x != 0); }
|
|
|
+ if (sscanf(line, " NoResize=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoResize; }
|
|
|
+ if (sscanf(line, " CentralNode=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_CentralNode; }
|
|
|
+ if (sscanf(line, " NoTabBar=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoTabBar; }
|
|
|
+ if (sscanf(line, " HiddenTabBar=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_HiddenTabBar; }
|
|
|
+ if (sscanf(line, " NoWindowMenuButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoWindowMenuButton; }
|
|
|
+ if (sscanf(line, " NoCloseButton=%d%n", &x, &r) == 1) { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoCloseButton; }
|
|
|
if (sscanf(line, " SelectedTab=0x%08X%n", &node.SelectedTabID,&r) == 1) { line += r; }
|
|
|
ImGuiDockContext* dc = ctx->DockContext;
|
|
|
if (node.ParentID != 0)
|
|
|
@@ -14040,9 +14147,7 @@ static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDo
|
|
|
node_settings.SelectedTabID = node->SelectedTabID;
|
|
|
node_settings.SplitAxis = node->IsSplitNode() ? (char)node->SplitAxis : ImGuiAxis_None;
|
|
|
node_settings.Depth = (char)depth;
|
|
|
- node_settings.IsDockSpace = (char)node->IsDockSpace();
|
|
|
- node_settings.IsCentralNode = (char)node->IsCentralNode();
|
|
|
- node_settings.IsHiddenTabBar = (char)node->IsHiddenTabBar();
|
|
|
+ node_settings.Flags = (node->LocalFlags & ImGuiDockNodeFlags_SavedFlagsMask_);
|
|
|
node_settings.Pos = ImVec2ih((short)node->Pos.x, (short)node->Pos.y);
|
|
|
node_settings.Size = ImVec2ih((short)node->Size.x, (short)node->Size.y);
|
|
|
node_settings.SizeRef = ImVec2ih((short)node->SizeRef.x, (short)node->SizeRef.y);
|
|
|
@@ -14079,7 +14184,7 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
|
|
|
{
|
|
|
const int line_start_pos = buf->size(); (void)line_start_pos;
|
|
|
const ImGuiDockNodeSettings* node_settings = &dc->SettingsNodes[node_n];
|
|
|
- buf->appendf("%*s%s%*s", node_settings->Depth * 2, "", node_settings->IsDockSpace ? "DockSpace" : "DockNode ", (max_depth - node_settings->Depth) * 2, ""); // Text align nodes to facilitate looking at .ini file
|
|
|
+ buf->appendf("%*s%s%*s", node_settings->Depth * 2, "", (node_settings->Flags & ImGuiDockNodeFlags_DockSpace) ? "DockSpace" : "DockNode ", (max_depth - node_settings->Depth) * 2, ""); // Text align nodes to facilitate looking at .ini file
|
|
|
buf->appendf(" ID=0x%08X", node_settings->ID);
|
|
|
if (node_settings->ParentID)
|
|
|
buf->appendf(" Parent=0x%08X SizeRef=%d,%d", node_settings->ParentID, node_settings->SizeRef.x, node_settings->SizeRef.y);
|
|
|
@@ -14087,10 +14192,18 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
|
|
|
buf->appendf(" Pos=%d,%d Size=%d,%d", node_settings->Pos.x, node_settings->Pos.y, node_settings->Size.x, node_settings->Size.y);
|
|
|
if (node_settings->SplitAxis != ImGuiAxis_None)
|
|
|
buf->appendf(" Split=%c", (node_settings->SplitAxis == ImGuiAxis_X) ? 'X' : 'Y');
|
|
|
- if (node_settings->IsCentralNode)
|
|
|
+ if (node_settings->Flags & ImGuiDockNodeFlags_NoResize)
|
|
|
+ buf->appendf(" NoResize=1");
|
|
|
+ if (node_settings->Flags & ImGuiDockNodeFlags_CentralNode)
|
|
|
buf->appendf(" CentralNode=1");
|
|
|
- if (node_settings->IsHiddenTabBar)
|
|
|
+ if (node_settings->Flags & ImGuiDockNodeFlags_NoTabBar)
|
|
|
+ buf->appendf(" NoTabBar=1");
|
|
|
+ if (node_settings->Flags & ImGuiDockNodeFlags_HiddenTabBar)
|
|
|
buf->appendf(" HiddenTabBar=1");
|
|
|
+ if (node_settings->Flags & ImGuiDockNodeFlags_NoWindowMenuButton)
|
|
|
+ buf->appendf(" NoWindowMenuButton=1");
|
|
|
+ if (node_settings->Flags & ImGuiDockNodeFlags_NoCloseButton)
|
|
|
+ buf->appendf(" NoCloseButton=1");
|
|
|
if (node_settings->SelectedTabID)
|
|
|
buf->appendf(" SelectedTab=0x%08X", node_settings->SelectedTabID);
|
|
|
|
|
|
@@ -14322,16 +14435,16 @@ void ImGui::ShowViewportThumbnails()
|
|
|
|
|
|
void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
{
|
|
|
- if (!ImGui::Begin("ImGui Metrics", p_open))
|
|
|
+ if (!ImGui::Begin("Dear ImGui Metrics", p_open))
|
|
|
{
|
|
|
ImGui::End();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerMainRect, RT_InnerWorkRect, RT_InnerWorkRectClipped, RT_ContentsRegionRect, RT_ContentsFullRect };
|
|
|
+ enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerRect, RT_InnerClipRect, RT_WorkRect, RT_Contents, RT_ContentsRegionRect };
|
|
|
static bool show_windows_begin_order = false;
|
|
|
static bool show_windows_rects = false;
|
|
|
- static int show_windows_rect_type = RT_InnerWorkRect;
|
|
|
+ static int show_windows_rect_type = RT_WorkRect;
|
|
|
static bool show_drawcmd_clip_rects = true;
|
|
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
@@ -14344,6 +14457,19 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
|
|
|
struct Funcs
|
|
|
{
|
|
|
+ static ImRect GetRect(ImGuiWindow* window, int rect_type)
|
|
|
+ {
|
|
|
+ if (rect_type == RT_OuterRect) { return window->Rect(); }
|
|
|
+ else if (rect_type == RT_OuterRectClipped) { return window->OuterRectClipped; }
|
|
|
+ else if (rect_type == RT_InnerRect) { return window->InnerRect; }
|
|
|
+ else if (rect_type == RT_InnerClipRect) { return window->InnerClipRect; }
|
|
|
+ else if (rect_type == RT_WorkRect) { return window->WorkRect; }
|
|
|
+ else if (rect_type == RT_Contents) { return ImRect(window->Pos, window->Pos + window->SizeContents); }
|
|
|
+ else if (rect_type == RT_ContentsRegionRect) { return window->ContentsRegionRect; }
|
|
|
+ IM_ASSERT(0);
|
|
|
+ return ImRect();
|
|
|
+ }
|
|
|
+
|
|
|
static void NodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, ImDrawList* draw_list, const char* label)
|
|
|
{
|
|
|
bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size);
|
|
|
@@ -14372,9 +14498,10 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
continue;
|
|
|
}
|
|
|
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
|
|
|
- bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()),
|
|
|
- "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
|
|
|
- pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
|
|
|
+ char buf[300];
|
|
|
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "Draw %4d triangles, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
|
|
|
+ pcmd->ElemCount/3, (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
|
|
|
+ bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf);
|
|
|
if (show_drawcmd_clip_rects && fg_draw_list && ImGui::IsItemHovered())
|
|
|
{
|
|
|
ImRect clip_rect = pcmd->ClipRect;
|
|
|
@@ -14388,11 +14515,11 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
continue;
|
|
|
|
|
|
// Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
|
|
|
+ ImGui::Text("ElemCount: %d, ElemCount/3: %d, VtxOffset: +%d, IdxOffset: +%d", pcmd->ElemCount, pcmd->ElemCount/3, pcmd->VtxOffset, pcmd->IdxOffset);
|
|
|
ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
|
|
|
while (clipper.Step())
|
|
|
for (int prim = clipper.DisplayStart, idx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++)
|
|
|
{
|
|
|
- char buf[300];
|
|
|
char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
|
|
|
ImVec2 triangles_pos[3];
|
|
|
for (int n = 0; n < 3; n++, idx_i++)
|
|
|
@@ -14401,7 +14528,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
ImDrawVert& v = draw_list->VtxBuffer[vtx_i];
|
|
|
triangles_pos[n] = v.pos;
|
|
|
buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
|
|
|
- (n == 0) ? "idx" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
|
|
|
+ (n == 0) ? "elem" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
|
|
|
}
|
|
|
ImGui::Selectable(buf, false);
|
|
|
if (fg_draw_list && ImGui::IsItemHovered())
|
|
|
@@ -14563,7 +14690,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
ImGui::Checkbox("Show windows rectangles", &show_windows_rects);
|
|
|
ImGui::SameLine();
|
|
|
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12);
|
|
|
- show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, "OuterRect\0" "OuterRectClipped\0" "InnerMainRect\0" "InnerWorkRect\0" "InnerWorkRectClipped\0" "ContentsRegionRect\0");
|
|
|
+ show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, "OuterRect\0" "OuterRectClipped\0" "InnerRect\0" "InnerClipRect\0" "WorkRect\0" "Contents\0" "ContentsRegionRect\0");
|
|
|
+ if (show_windows_rects && g.NavWindow)
|
|
|
+ {
|
|
|
+ ImRect r = Funcs::GetRect(g.NavWindow, show_windows_rect_type);
|
|
|
+ ImGui::BulletText("'%s': (%.1f,%.1f) (%.1f,%.1f) Size (%.1f,%.1f)", g.NavWindow->Name, r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight());
|
|
|
+ }
|
|
|
ImGui::Checkbox("Show clipping rectangle when hovering ImDrawCmd node", &show_drawcmd_clip_rects);
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
@@ -14578,13 +14710,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
ImDrawList* draw_list = GetForegroundDrawList(window);
|
|
|
if (show_windows_rects)
|
|
|
{
|
|
|
- ImRect r;
|
|
|
- if (show_windows_rect_type == RT_OuterRect) { r = window->Rect(); }
|
|
|
- else if (show_windows_rect_type == RT_OuterRectClipped) { r = window->OuterRectClipped; }
|
|
|
- else if (show_windows_rect_type == RT_InnerMainRect) { r = window->InnerMainRect; }
|
|
|
- else if (show_windows_rect_type == RT_InnerWorkRect) { r = window->InnerWorkRect; }
|
|
|
- else if (show_windows_rect_type == RT_InnerWorkRectClipped) { r = window->InnerWorkRectClipped; }
|
|
|
- else if (show_windows_rect_type == RT_ContentsRegionRect) { r = window->ContentsRegionRect; }
|
|
|
+ ImRect r = Funcs::GetRect(window, show_windows_rect_type);
|
|
|
draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
|
|
|
}
|
|
|
if (show_windows_begin_order && !(window->Flags & ImGuiWindowFlags_ChildWindow))
|
|
|
@@ -14628,10 +14754,12 @@ void ImGui::ShowDockingDebug()
|
|
|
ImGui::BulletText("Misc:%s%s%s%s", node->IsDockSpace() ? " IsDockSpace" : "", node->IsCentralNode() ? " IsCentralNode" : "", (g.FrameCount - node->LastFrameAlive < 2) ? " IsAlive" : "", (g.FrameCount - node->LastFrameActive < 2) ? " IsActive" : "");
|
|
|
if (ImGui::TreeNode("flags", "LocalFlags: 0x%04X SharedFlags: 0x%04X", node->LocalFlags, node->SharedFlags))
|
|
|
{
|
|
|
- ImGui::CheckboxFlags("LocalFlags: NoSplit", (unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_NoSplit);
|
|
|
- ImGui::CheckboxFlags("LocalFlags: NoResize", (unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_NoResize);
|
|
|
- ImGui::CheckboxFlags("LocalFlags: NoTabBar", (unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_NoTabBar);
|
|
|
- ImGui::CheckboxFlags("LocalFlags: HiddenTabBar",(unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_HiddenTabBar);
|
|
|
+ ImGui::CheckboxFlags("LocalFlags: NoSplit", (ImU32*)&node->LocalFlags, ImGuiDockNodeFlags_NoSplit);
|
|
|
+ ImGui::CheckboxFlags("LocalFlags: NoResize", (ImU32*)&node->LocalFlags, ImGuiDockNodeFlags_NoResize);
|
|
|
+ ImGui::CheckboxFlags("LocalFlags: NoTabBar", (ImU32*)&node->LocalFlags, ImGuiDockNodeFlags_NoTabBar);
|
|
|
+ ImGui::CheckboxFlags("LocalFlags: HiddenTabBar", (ImU32*)&node->LocalFlags, ImGuiDockNodeFlags_HiddenTabBar);
|
|
|
+ ImGui::CheckboxFlags("LocalFlags: NoWindowMenuButton", (ImU32*)&node->LocalFlags, ImGuiDockNodeFlags_NoWindowMenuButton);
|
|
|
+ ImGui::CheckboxFlags("LocalFlags: NoCloseButton", (ImU32*)&node->LocalFlags, ImGuiDockNodeFlags_NoCloseButton);
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
if (node->ChildNodes[0])
|