Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImGuiWindowFlags_UserDrawnOverlappingDecorators #8347

Open
wants to merge 5 commits into
base: docking
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 61 additions & 5 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7179,8 +7179,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)
Expand All @@ -7199,12 +7206,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)
Expand Down Expand Up @@ -8305,6 +8331,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);
}
}

void ImGui::End()
{
ImGuiContext& g = *GImGui;
Expand Down
3 changes: 3 additions & 0 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
36 changes: 36 additions & 0 deletions imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2683,6 +2683,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
{
Expand Down Expand Up @@ -2757,6 +2792,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().
Expand Down