Docking: Internal: Added helper for automation to process docking at the mouse level.
This commit is contained in:
parent
433a7556c7
commit
f70eacee8e
45
imgui.cpp
45
imgui.cpp
@ -10896,11 +10896,11 @@ namespace ImGui
|
|||||||
static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
|
static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
|
||||||
static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window);
|
static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window);
|
||||||
static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_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 void DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, const ImGuiDockPreviewData* preview_data);
|
||||||
static ImRect DockNodeCalcTabBarRect(const ImGuiDockNode* node);
|
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 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 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 DockNodeGetDepth(const ImGuiDockNode* node) { int depth = 0; while (node->ParentNode) { node = node->ParentNode; depth++; } return depth; }
|
||||||
static int DockNodeGetTabOrder(ImGuiWindow* window);
|
static int DockNodeGetTabOrder(ImGuiWindow* window);
|
||||||
@ -11439,6 +11439,25 @@ void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
|
|||||||
MarkIniSettingsDirty();
|
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
|
// 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.
|
// 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;
|
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_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); }
|
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;
|
ImRect hit_r = out_r;
|
||||||
if (!outer_docking)
|
if (!outer_docking)
|
||||||
{
|
{
|
||||||
// Custom hit testing for the 5-way selection, designed to reduce flickering when moving diagonally between sides
|
// 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));
|
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 mouse_delta_len2 = ImLengthSqr(mouse_delta);
|
||||||
float r_threshold_center = hs_w * 1.4f;
|
float r_threshold_center = hs_w * 1.4f;
|
||||||
float r_threshold_sides = hs_w * (1.4f + 1.2f);
|
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)
|
if (mouse_delta_len2 < r_threshold_sides * r_threshold_sides)
|
||||||
return (dir == ImGetDirQuadrantFromDelta(mouse_delta.x, mouse_delta.y));
|
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.
|
// 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;
|
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.
|
// 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.
|
// 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;
|
continue;
|
||||||
if (dir != ImGuiDir_None && !data->IsSidesAvailable)
|
if (dir != ImGuiDir_None && !data->IsSidesAvailable)
|
||||||
continue;
|
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->SplitDir = (ImGuiDir)dir;
|
||||||
data->IsSplitDirExplicit = true;
|
data->IsSplitDirExplicit = true;
|
||||||
@ -12531,13 +12552,12 @@ static bool ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNo
|
|||||||
data->FutureNode.Size = size_new;
|
data->FutureNode.Size = size_new;
|
||||||
data->SplitRatio = (split_dir == ImGuiDir_Right || split_dir == ImGuiDir_Down) ? (1.0f - split_ratio) : (split_ratio);
|
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)
|
static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload, const ImGuiDockPreviewData* data)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
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.
|
// 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.
|
// 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;
|
ImGuiDockPreviewData* split_data = &split_inner;
|
||||||
if (node && (node->ParentNode || node->IsCentralNode()))
|
if (node && (node->ParentNode || node->IsCentralNode()))
|
||||||
if (ImGuiDockNode* root_node = DockNodeGetRootNode(node))
|
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;
|
split_data = &split_outer;
|
||||||
|
}
|
||||||
DockNodePreviewDockCalc(window, node, payload_window, &split_inner, is_explicit_target, false);
|
DockNodePreviewDockCalc(window, node, payload_window, &split_inner, is_explicit_target, false);
|
||||||
if (split_data == &split_outer)
|
if (split_data == &split_outer)
|
||||||
split_inner.IsDropAllowed = false;
|
split_inner.IsDropAllowed = false;
|
||||||
|
@ -1678,6 +1678,7 @@ namespace ImGui
|
|||||||
IMGUI_API void DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, float split_ratio, bool split_outer);
|
IMGUI_API void DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, float split_ratio, bool split_outer);
|
||||||
IMGUI_API void DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window);
|
IMGUI_API void DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window);
|
||||||
IMGUI_API void DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node);
|
IMGUI_API void DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node);
|
||||||
|
IMGUI_API bool DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos);
|
||||||
inline ImGuiDockNode* DockNodeGetRootNode(ImGuiDockNode* node) { while (node->ParentNode) node = node->ParentNode; return node; }
|
inline ImGuiDockNode* DockNodeGetRootNode(ImGuiDockNode* node) { while (node->ParentNode) node = node->ParentNode; return node; }
|
||||||
IMGUI_API void BeginDocked(ImGuiWindow* window, bool* p_open);
|
IMGUI_API void BeginDocked(ImGuiWindow* window, bool* p_open);
|
||||||
IMGUI_API void BeginAsDockableDragDropSource(ImGuiWindow* window);
|
IMGUI_API void BeginAsDockableDragDropSource(ImGuiWindow* window);
|
||||||
|
Loading…
Reference in New Issue
Block a user