|
|
|
@ -10896,11 +10896,11 @@ namespace ImGui |
|
|
|
|
static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node); |
|
|
|
|
static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window); |
|
|
|
|
static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_window); |
|
|
|
|
static bool DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockPreviewData* preview_data, bool is_explicit_target, bool is_outer_docking); |
|
|
|
|
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 DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired); |
|
|
|
|
static bool DockNodeCalcDropRects(const ImRect& parent, ImGuiDir dir, ImRect& out_draw, bool outer_docking); |
|
|
|
|
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; } |
|
|
|
|
static int DockNodeGetDepth(const ImGuiDockNode* node) { int depth = 0; while (node->ParentNode) { node = node->ParentNode; depth++; } return depth; } |
|
|
|
|
static int DockNodeGetTabOrder(ImGuiWindow* window); |
|
|
|
@ -11439,6 +11439,25 @@ void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node) |
|
|
|
|
MarkIniSettingsDirty(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This is mostly used for automation.
|
|
|
|
|
bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos) |
|
|
|
|
{ |
|
|
|
|
if (split_outer) |
|
|
|
|
{ |
|
|
|
|
IM_ASSERT(0); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
ImGuiDockPreviewData split_data; |
|
|
|
|
DockNodePreviewDockCalc(target, target_node, payload, &split_data, false, split_outer); |
|
|
|
|
if (split_data.DropRectsDraw[split_dir+1].IsInverted()) |
|
|
|
|
return false; |
|
|
|
|
*out_pos = split_data.DropRectsDraw[split_dir+1].GetCenter(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Docking: ImGuiDockNode
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
@ -12408,7 +12427,7 @@ void ImGui::DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& po |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Retrieve the drop rectangles for a given direction or for the center + perform hit testing.
|
|
|
|
|
bool ImGui::DockNodeCalcDropRects(const ImRect& parent, ImGuiDir dir, ImRect& out_r, bool outer_docking) |
|
|
|
|
bool ImGui::DockNodeCalcDropRectsAndTestMousePos(const ImRect& parent, ImGuiDir dir, ImRect& out_r, bool outer_docking, ImVec2* test_mouse_pos) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
|
|
|
|
@ -12440,12 +12459,15 @@ bool ImGui::DockNodeCalcDropRects(const ImRect& parent, ImGuiDir dir, ImRect& ou |
|
|
|
|
else if (dir == ImGuiDir_Left) { out_r = ImRect(c.x - off.x - hs_h, c.y - hs_w, c.x - off.x + hs_h, c.y + hs_w); } |
|
|
|
|
else if (dir == ImGuiDir_Right) { out_r = ImRect(c.x + off.x - hs_h, c.y - hs_w, c.x + off.x + hs_h, c.y + hs_w); } |
|
|
|
|
|
|
|
|
|
if (test_mouse_pos == NULL) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
ImRect hit_r = out_r; |
|
|
|
|
if (!outer_docking) |
|
|
|
|
{ |
|
|
|
|
// Custom hit testing for the 5-way selection, designed to reduce flickering when moving diagonally between sides
|
|
|
|
|
hit_r.Expand(ImFloor(hs_w * 0.30f)); |
|
|
|
|
ImVec2 mouse_delta = (g.IO.MousePos - c); |
|
|
|
|
ImVec2 mouse_delta = (*test_mouse_pos - c); |
|
|
|
|
float mouse_delta_len2 = ImLengthSqr(mouse_delta); |
|
|
|
|
float r_threshold_center = hs_w * 1.4f; |
|
|
|
|
float r_threshold_sides = hs_w * (1.4f + 1.2f); |
|
|
|
@ -12454,14 +12476,13 @@ bool ImGui::DockNodeCalcDropRects(const ImRect& parent, ImGuiDir dir, ImRect& ou |
|
|
|
|
if (mouse_delta_len2 < r_threshold_sides * r_threshold_sides) |
|
|
|
|
return (dir == ImGetDirQuadrantFromDelta(mouse_delta.x, mouse_delta.y)); |
|
|
|
|
} |
|
|
|
|
return hit_r.Contains(g.IO.MousePos); |
|
|
|
|
return hit_r.Contains(*test_mouse_pos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// host_node may be NULL if the window doesn't have a DockNode already.
|
|
|
|
|
static bool ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload, ImGuiDockPreviewData* data, bool is_explicit_target, bool is_outer_docking) |
|
|
|
|
static void ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload, ImGuiDockPreviewData* data, bool is_explicit_target, bool is_outer_docking) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
IM_ASSERT(g.CurrentWindow == host_window); // Because we rely on font size to calculate tab sizes
|
|
|
|
|
|
|
|
|
|
// There is an edge case when docking into a dockspace which only has inactive nodes.
|
|
|
|
|
// In this case DockNodeTreeFindNodeByPos() will have selected a leaf node which is inactive.
|
|
|
|
@ -12503,7 +12524,7 @@ static bool ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNo |
|
|
|
|
continue; |
|
|
|
|
if (dir != ImGuiDir_None && !data->IsSidesAvailable) |
|
|
|
|
continue; |
|
|
|
|
if (DockNodeCalcDropRects(data->FutureNode.Rect(), (ImGuiDir)dir, data->DropRectsDraw[dir+1], is_outer_docking)) |
|
|
|
|
if (DockNodeCalcDropRectsAndTestMousePos(data->FutureNode.Rect(), (ImGuiDir)dir, data->DropRectsDraw[dir+1], is_outer_docking, &g.IO.MousePos)) |
|
|
|
|
{ |
|
|
|
|
data->SplitDir = (ImGuiDir)dir; |
|
|
|
|
data->IsSplitDirExplicit = true; |
|
|
|
@ -12531,13 +12552,12 @@ static bool ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNo |
|
|
|
|
data->FutureNode.Size = size_new; |
|
|
|
|
data->SplitRatio = (split_dir == ImGuiDir_Right || split_dir == ImGuiDir_Down) ? (1.0f - split_ratio) : (split_ratio); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return data->IsSplitDirExplicit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload, const ImGuiDockPreviewData* data) |
|
|
|
|
{ |
|
|
|
|
ImGuiContext& g = *GImGui; |
|
|
|
|
IM_ASSERT(g.CurrentWindow == host_window); // Because we rely on font size to calculate tab sizes
|
|
|
|
|
|
|
|
|
|
// With this option, we only display the preview on the target viewport, and the payload viewport is made transparent.
|
|
|
|
|
// To compensate for the single layer obstructed by the payload, we'll increase the alpha of the preview nodes.
|
|
|
|
@ -13684,8 +13704,11 @@ void ImGui::BeginAsDockableDragDropTarget(ImGuiWindow* window) |
|
|
|
|
ImGuiDockPreviewData* split_data = &split_inner; |
|
|
|
|
if (node && (node->ParentNode || node->IsCentralNode())) |
|
|
|
|
if (ImGuiDockNode* root_node = DockNodeGetRootNode(node)) |
|
|
|
|
if (DockNodePreviewDockCalc(window, root_node, payload_window, &split_outer, is_explicit_target, true)) |
|
|
|
|
{ |
|
|
|
|
DockNodePreviewDockCalc(window, root_node, payload_window, &split_outer, is_explicit_target, true); |
|
|
|
|
if (split_outer.IsSplitDirExplicit) |
|
|
|
|
split_data = &split_outer; |
|
|
|
|
} |
|
|
|
|
DockNodePreviewDockCalc(window, node, payload_window, &split_inner, is_explicit_target, false); |
|
|
|
|
if (split_data == &split_outer) |
|
|
|
|
split_inner.IsDropAllowed = false; |
|
|
|
|