Docking: Added DockBuilderForkNode() primitive for usage for user code to fork/copy entire layouts. This will probably need to be added to as I find ways to migrate patterns from user code to the library. Added IMGUI_DEBUG_DOCKING_INI helper to facilitate debugging. (+1 squashed commits)

This commit is contained in:
omar 2018-09-26 13:09:41 +02:00
parent dc92431328
commit 45731cca19
3 changed files with 57 additions and 12 deletions

View File

@ -867,8 +867,9 @@ CODE
#include <stdint.h> // intptr_t #include <stdint.h> // intptr_t
#endif #endif
#define IMGUI_DEBUG_NAV_SCORING 0 #define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL
#define IMGUI_DEBUG_NAV_RECTS 0 #define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window
#define IMGUI_DEBUG_DOCKING_INI 0 // Save additional comments in .ini file (makes saving slower)
// Visual Studio warnings // Visual Studio warnings
#ifdef _MSC_VER #ifdef _MSC_VER
@ -9631,7 +9632,7 @@ namespace ImGui
static void DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req); static void DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req);
static void DockContextProcessUndockWindow(ImGuiContext* ctx, ImGuiWindow* window); static void DockContextProcessUndockWindow(ImGuiContext* ctx, ImGuiWindow* window);
static void DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node); static void DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node);
static void DockContextGcUnusedSettingsNodes(ImGuiContext* ctx); static void DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx);
static ImGuiDockNode* DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id); static ImGuiDockNode* DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id);
static void DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id, bool clear_persistent_docking_references); // Set root_id==0 to clear all static void DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id, bool clear_persistent_docking_references); // Set root_id==0 to clear all
static void DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDockNodeSettings* node_settings_array, int node_settings_count); static void DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDockNodeSettings* node_settings_array, int node_settings_count);
@ -9715,7 +9716,7 @@ void ImGui::DockContextShutdown(ImGuiContext* ctx)
void ImGui::DockContextOnLoadSettings(ImGuiContext* ctx) void ImGui::DockContextOnLoadSettings(ImGuiContext* ctx)
{ {
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = ctx->DockContext;
DockContextGcUnusedSettingsNodes(ctx); DockContextPruneUnusedSettingsNodes(ctx);
DockContextBuildNodesFromSettings(ctx, dc->SettingsNodes.Data, dc->SettingsNodes.Size); DockContextBuildNodesFromSettings(ctx, dc->SettingsNodes.Data, dc->SettingsNodes.Size);
} }
@ -9725,7 +9726,7 @@ void ImGui::DockContextClearNodes(ImGuiContext* ctx, ImGuiID root_id, bool clear
DockBuilderRemoveNodeChildNodes(ctx, root_id); DockBuilderRemoveNodeChildNodes(ctx, root_id);
} }
// This function also acts as a de-facto test to make sure we can rebuild from scratch without a glitch // This function also acts as a defacto test to make sure we can rebuild from scratch without a glitch
void ImGui::DockContextRebuild(ImGuiContext* ctx) void ImGui::DockContextRebuild(ImGuiContext* ctx)
{ {
//IMGUI_DEBUG_LOG("[docking] full rebuild\n"); //IMGUI_DEBUG_LOG("[docking] full rebuild\n");
@ -9858,7 +9859,8 @@ static int IMGUI_CDECL DockNodeComparerDepthMostFirst(const void* lhs, const voi
return ImGui::DockNodeGetDepth(b) - ImGui::DockNodeGetDepth(a); return ImGui::DockNodeGetDepth(b) - ImGui::DockNodeGetDepth(a);
} }
static void ImGui::DockContextGcUnusedSettingsNodes(ImGuiContext* ctx) // Garbage collect unused nodes (run once at init time)
static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = ctx->DockContext;
@ -11678,6 +11680,47 @@ ImGuiID ImGui::DockBuilderSplitNode(ImGuiContext* ctx, ImGuiID id, ImGuiDir spli
return id_at_dir; return id_at_dir;
} }
static ImGuiDockNode* DockBuilderCloneNodeForFork(ImGuiContext* ctx, ImGuiDockNode* src_node, ImGuiID dst_node_id_if_known, ImVector<ImGuiID>* out_node_remap_pairs)
{
ImGuiDockNode* dst_node = ImGui::DockContextAddNode(ctx, dst_node_id_if_known);
dst_node->Flags = src_node->Flags;
dst_node->Pos = src_node->Pos;
dst_node->Size = src_node->Size;
dst_node->SizeRef = src_node->SizeRef;
dst_node->SplitAxis = src_node->SplitAxis;
dst_node->IsDockSpace = src_node->IsDockSpace;
dst_node->IsDocumentRoot = src_node->IsDocumentRoot;
out_node_remap_pairs->push_back(src_node->ID);
out_node_remap_pairs->push_back(dst_node->ID);
for (int child_n = 0; child_n < IM_ARRAYSIZE(src_node->ChildNodes); child_n++)
if (src_node->ChildNodes[child_n])
{
dst_node->ChildNodes[child_n] = DockBuilderCloneNodeForFork(ctx, src_node->ChildNodes[child_n], 0, out_node_remap_pairs);
dst_node->ChildNodes[child_n]->ParentNode = dst_node;
}
//IMGUI_DEBUG_LOG("Fork node %08X -> %08X (%d childs)\n", src_node->ID, dst_node->ID, dst_node->IsSplitNode() ? 2 : 0);
return dst_node;
}
void ImGui::DockBuilderForkNode(ImGuiContext* ctx, ImGuiID src_node_id, ImGuiID dst_node_id, ImVector<ImGuiID>* out_node_remap_pairs)
{
IM_ASSERT(src_node_id != 0);
IM_ASSERT(dst_node_id != 0);
IM_ASSERT(out_node_remap_pairs != NULL);
ImGuiDockNode* src_node = DockContextFindNodeByID(ctx, src_node_id);
IM_ASSERT(src_node != NULL);
out_node_remap_pairs->clear();
DockBuilderRemoveNode(ctx, dst_node_id);
DockBuilderCloneNodeForFork(ctx, src_node, dst_node_id, out_node_remap_pairs);
IM_ASSERT((out_node_remap_pairs->Size % 2) == 0);
}
void ImGui::DockBuilderFinish(ImGuiContext* ctx, ImGuiID root_id) void ImGui::DockBuilderFinish(ImGuiContext* ctx, ImGuiID root_id)
{ {
DockContextBuildAddWindowsToNodes(ctx, root_id); DockContextBuildAddWindowsToNodes(ctx, root_id);
@ -11993,7 +12036,9 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
buf->appendf("[%s][Data]\n", handler->TypeName); buf->appendf("[%s][Data]\n", handler->TypeName);
for (int node_n = 0; node_n < dc->SettingsNodes.Size; node_n++) for (int node_n = 0; node_n < dc->SettingsNodes.Size; node_n++)
{ {
//const int line_start_pos = buf->size(); #if IMGUI_DEBUG_DOCKING_INI
const int line_start_pos = buf->size();
#endif
const ImGuiDockNodeSettings* node_settings = &dc->SettingsNodes[node_n]; 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->IsDockSpace ? "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); buf->appendf(" ID=0x%08X", node_settings->ID);
@ -12008,14 +12053,13 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
if (node_settings->SelectedTabID) if (node_settings->SelectedTabID)
buf->appendf(" SelectedTab=0x%08X", node_settings->SelectedTabID); buf->appendf(" SelectedTab=0x%08X", node_settings->SelectedTabID);
#if 0 #if IMGUI_DEBUG_DOCKING_INI
// [DEBUG] Include comments in the .ini file to ease debugging // [DEBUG] Include comments in the .ini file to ease debugging
if (ImGuiDockNode* node = DockContextFindNodeByID(ctx, node_settings->ID)) if (ImGuiDockNode* node = DockContextFindNodeByID(ctx, node_settings->ID))
{ {
buf->appendf("%*s", ImMax(2, (line_start_pos + 90) - buf->size()), ""); // Align everything buf->appendf("%*s", ImMax(2, (line_start_pos + 90) - buf->size()), ""); // Align everything
if (node->IsDockSpace && node->HostWindow && node->HostWindow->ParentWindow) if (node->IsDockSpace && node->HostWindow && node->HostWindow->ParentWindow)
buf->appendf(" ; in '%s'", node->HostWindow->ParentWindow->Name); buf->appendf(" ; in '%s'", node->HostWindow->ParentWindow->Name);
int contains_window = 0; int contains_window = 0;
for (int window_n = 0; window_n < ctx->SettingsWindows.Size; window_n++) for (int window_n = 0; window_n < ctx->SettingsWindows.Size; window_n++)
if (ctx->SettingsWindows[window_n].DockId == node_settings->ID) if (ctx->SettingsWindows[window_n].DockId == node_settings->ID)

View File

@ -1565,13 +1565,14 @@ struct ImGuiSizeCallbackData
ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing.
}; };
// For SetNextWindowDockFamily() and DockSpace() function // [BETA] For SetNextWindowDockFamily() and DockSpace() function
struct ImGuiDockFamily struct ImGuiDockFamily
{ {
ImGuiID ID; // 0 = unaffiliated ImGuiID ID; // 0 = unaffiliated
bool CompatibleWithFamilyZero; // true = can be docked/merged with an unaffiliated window bool CompatibleWithFamilyZero; // true = can be docked/merged with an unaffiliated window
ImGuiDockFamily() { ID = 0; CompatibleWithFamilyZero = true; } ImGuiDockFamily() { ID = 0; CompatibleWithFamilyZero = true; }
ImGuiDockFamily(ImGuiID id, bool compatible_with_family_zero = true) { ID = id; CompatibleWithFamilyZero = compatible_with_family_zero; }
}; };
// Data payload for Drag and Drop operations // Data payload for Drag and Drop operations

View File

@ -1488,7 +1488,7 @@ namespace ImGui
IMGUI_API void DockBuilderRemoveNodeDockedWindows(ImGuiContext* ctx, ImGuiID node_id, bool clear_persistent_docking_references = true); IMGUI_API void DockBuilderRemoveNodeDockedWindows(ImGuiContext* ctx, ImGuiID node_id, bool clear_persistent_docking_references = true);
IMGUI_API void DockBuilderRemoveNodeChildNodes(ImGuiContext* ctx, ImGuiID node_id); // Remove all split/hierarchy. All remaining docked windows will be re-docked to the root. IMGUI_API void DockBuilderRemoveNodeChildNodes(ImGuiContext* ctx, ImGuiID node_id); // Remove all split/hierarchy. All remaining docked windows will be re-docked to the root.
IMGUI_API ImGuiID DockBuilderSplitNode(ImGuiContext* ctx, ImGuiID node_id, ImGuiDir split_dir, float size_ratio_for_node_at_dir, ImGuiID* out_id_dir, ImGuiID* out_id_other); IMGUI_API ImGuiID DockBuilderSplitNode(ImGuiContext* ctx, ImGuiID node_id, ImGuiDir split_dir, float size_ratio_for_node_at_dir, ImGuiID* out_id_dir, ImGuiID* out_id_other);
//IMGUI_API void DockBuilderForkNode(ImGuiContext* ctx, ImGuiID src_node_id, ImGuiID new_node_id); IMGUI_API void DockBuilderForkNode(ImGuiContext* ctx, ImGuiID src_node_id, ImGuiID dst_node_id, ImVector<ImGuiID>* out_node_remap_pairs);
IMGUI_API void DockBuilderFinish(ImGuiContext* ctx, ImGuiID node_id); IMGUI_API void DockBuilderFinish(ImGuiContext* ctx, ImGuiID node_id);
// Drag and Drop // Drag and Drop