1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-13 00:24:20 +00:00

add ImGuiWindowFlags_UserDrawnOverlappingDecorators

This commit is contained in:
Mihaly Sisak 2025-01-25 15:38:50 +01:00
parent 81dab646ee
commit cd15f7e6f9
No known key found for this signature in database
GPG key ID: 8167510F7EF98143
3 changed files with 100 additions and 5 deletions

View file

@ -7153,8 +7153,15 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
// FIXME-DOCK: Ideally we'd use ImGuiCol_TitleBgActive/ImGuiCol_TitleBg here, but neither is guaranteed to be visible enough at this sort of size..
ImU32 col = GetColorU32(((held && hovered) || (node->IsFocused && !hovered)) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
window->DrawList->AddTriangleFilled(p, p + ImVec2(unhide_sz_draw, 0.0f), p + ImVec2(0.0f, unhide_sz_draw), col);
ImVec2 p2 = p + ImVec2(unhide_sz_draw, 0.0f);
ImVec2 p3 = p + ImVec2(0.0f, unhide_sz_draw);
if (flags & ImGuiWindowFlags_UserDrawnOverlappingDecorators)
window->Decorator.DockingTabBar.Fill(p, p2, p3, col);
else
window->DrawList->AddTriangleFilled(p, p2, p3, col);
}
else if (flags & ImGuiWindowFlags_UserDrawnOverlappingDecorators)
window->Decorator.DockingTabBar.Reset();
// Scrollbars
if (window->ScrollbarX)
@ -7173,12 +7180,31 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
const float border_inner = IM_ROUND(window_border_size * 0.5f);
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(border_inner, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, border_inner)));
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, border_inner) : ImVec2(border_inner, resize_grip_draw_size)));
window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + border_inner), corner.y + grip.InnerDir.y * (window_rounding + border_inner)), window_rounding, grip.AngleMin12, grip.AngleMax12);
window->DrawList->PathFillConvex(col);
ImVec2 p1 = corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(border_inner, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, border_inner));
ImVec2 p2 = corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, border_inner) : ImVec2(border_inner, resize_grip_draw_size));
ImVec2 pc = ImVec2(corner.x + grip.InnerDir.x * (window_rounding + border_inner), corner.y + grip.InnerDir.y * (window_rounding + border_inner));
float r = window_rounding;
int a1 = grip.AngleMin12;
int a2 = grip.AngleMax12;
if (flags & ImGuiWindowFlags_UserDrawnOverlappingDecorators)
{
window->Decorator.ResizeGrip[resize_grip_n].Fill(p1, p2, pc, r, a1, a2, col);
}
else
{
window->DrawList->PathLineTo(p1);
window->DrawList->PathLineTo(p2);
window->DrawList->PathArcToFast(pc, r, a1, a2);
window->DrawList->PathFillConvex(col);
}
}
if (flags & ImGuiWindowFlags_UserDrawnOverlappingDecorators)
for (int resize_grip_n = resize_grip_count; resize_grip_n < 4; resize_grip_n++)
window->Decorator.ResizeGrip[resize_grip_n].Reset();
}
else if (flags & ImGuiWindowFlags_UserDrawnOverlappingDecorators)
for (int resize_grip_n = 0; resize_grip_n < 4; resize_grip_n++)
window->Decorator.ResizeGrip[resize_grip_n].Reset();
// Borders (for dock node host they will be rendered over after the tab bar)
if (handle_borders_and_resize_grips && !window->DockNodeAsHost)
@ -8277,6 +8303,36 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
return !window->SkipItems;
}
// In case of ImGuiWindowFlags_UserDrawnOverlappingDecorators
// the Begin() call does not draw the docking unhide tab bar (small triangle in the corner) and resize grips
// but saves them to the window->Decorator structure
void ImGui::DrawOverlappingDecorators()
{
ImGuiWindow* window = GetCurrentWindow();
IM_ASSERT_USER_ERROR(window != NULL, "Call this function beween Begin() and End()");
int flags = window->Flags;
IM_ASSERT_USER_ERROR(flags & ImGuiWindowFlags_UserDrawnOverlappingDecorators, "Only call this function for windows with ImGuiWindowFlags_UserDrawnOverlappingDecorators set");
if (window->Decorator.DockingTabBar.IsDrawing)
{
ImGuiDecoratorDockingTabBar& dt = window->Decorator.DockingTabBar;
window->DrawList->AddTriangleFilled(dt.P1, dt.P2, dt.P3, dt.Col);
}
for (int resize_grip_n = 0; resize_grip_n < 4; resize_grip_n++)
if (window->Decorator.ResizeGrip[resize_grip_n].IsDrawing)
{
ImGuiDecoratorResizeGrip& rg = window->Decorator.ResizeGrip[resize_grip_n];
window->DrawList->PathLineTo(rg.P1);
window->DrawList->PathLineTo(rg.P2);
window->DrawList->PathArcToFast(rg.Pc, rg.R, rg.A1, rg.A2);
window->DrawList->PathFillConvex(rg.Col);
}
}
static void ImGui::SetLastItemDataForWindow(ImGuiWindow* window, const ImRect& rect)
{
ImGuiContext& g = *GImGui;

View file

@ -374,7 +374,9 @@ namespace ImGui
// such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding
// BeginXXX function returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.]
// - Note that the bottom of window stack always contains a window called "Debug".
// - DrawOverlappingDecorators() is only needed if the window was created with the ImGuiWindowFlags_UserDrawnOverlappingDecorators flag
IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0);
IMGUI_API void DrawOverlappingDecorators();
IMGUI_API void End();
// Child Windows
@ -1127,6 +1129,7 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with keyboard/gamepad navigation (e.g. skipped by CTRL+TAB)
ImGuiWindowFlags_UnsavedDocument = 1 << 18, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
ImGuiWindowFlags_NoDocking = 1 << 19, // Disable docking of this window
ImGuiWindowFlags_UserDrawnOverlappingDecorators=1<<20, // Draw docking unhide tab bar (small triangle in the corner) and resize grips when user calls DrawOverlappingDecorators()
ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse,
ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,

View file

@ -2677,6 +2677,41 @@ struct IMGUI_API ImGuiWindowTempData
ImVector<float> TextWrapPosStack; // Store text wrap pos to restore (attention: .back() is not == TextWrapPos)
};
// Overlapping decorators for ImGuiWindowFlags_UserDrawnOverlappingDecorators, docking unhide tab bar (small triangle in the corner)
struct IMGUI_API ImGuiDecoratorDockingTabBar
{
bool IsDrawing; // Is this gui element being drawn in this frame
ImVec2 P1; // window->DrawList->AddTriangleFilled p1
ImVec2 P2; // window->DrawList->AddTriangleFilled p2
ImVec2 P3; // window->DrawList->AddTriangleFilled p3
ImU32 Col; // window->DrawList->AddTriangleFilled col
void Fill(ImVec2 p1, ImVec2 p2, ImVec2 p3, ImU32 col) { IsDrawing = true; P1 = p1; P2 = p2; P3 = p3; Col = col; }
void Reset() { IsDrawing = false; }
};
// Overlapping decorators for ImGuiWindowFlags_UserDrawnOverlappingDecorators, resize grips
struct IMGUI_API ImGuiDecoratorResizeGrip
{
bool IsDrawing; // Is this gui element being drawn in this frame
ImVec2 P1; // window->DrawList->PathLineTo 1st call pos
ImVec2 P2; // window->DrawList->PathLineTo 2nd call pos
ImVec2 Pc; // window->DrawList->PathArcToFast center
float R; // window->DrawList->PathArcToFast radius
int A1; // window->DrawList->PathArcToFast a_min_of_12
int A2; // window->DrawList->PathArcToFast a_max_of_12
ImU32 Col; // window->DrawList->PathFillConvex col
void Fill(ImVec2 p1, ImVec2 p2, ImVec2 pc, float r, int a1, int a2, ImU32 col) { IsDrawing = true; P1 = p1; P2 = p2; Pc = pc; R = r; A1 = a1; A2 = a2; Col = col; }
void Reset() { IsDrawing = false; }
};
struct IMGUI_API ImGuiDecorator
{
ImGuiDecoratorDockingTabBar DockingTabBar;
ImGuiDecoratorResizeGrip ResizeGrip[4];
};
// Storage for one window
struct IMGUI_API ImGuiWindow
{
@ -2751,6 +2786,7 @@ struct IMGUI_API ImGuiWindow
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack. (In theory this should be in the TempData structure)
ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name.
ImGuiDecorator Decorator; // Temporary overlapping decorator data for ImGuiWindowFlags_UserDrawnOverlappingDecorators
// The best way to understand what those rectangles are is to use the 'Metrics->Tools->Show Windows Rectangles' viewer.
// The main 'OuterRect', omitted as a field, is window->Rect().