From 9ebab255d250daf27ed05f49d015c9a2cbf946b5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 21 May 2024 19:00:25 +0200 Subject: [PATCH] Docking: *BREAKING* changed signature of DockSpaceOverViewport() to allow passing an explicit dockspace id if desired. (#7611) --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 41 ++++++++++++++++++++++++----------------- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a44369047..6890d361d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -73,6 +73,11 @@ Other changes: Docking+Viewports Branch: +- Docking: *BREAKING* changed signature of DockSpaceOverViewport() to allow passing + an explicit dockspace id if desired. (#7611) + Before: DockSpaceOverViewport(const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, ...); + After: DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, ...); + Simply add a leading 0 to your existing calls to DockSpaceOverViewport() if you have any. - Tables: resizing border hit-rect scales according to current monitor dpi scale. diff --git a/imgui.cpp b/imgui.cpp index 3abba4587..66cc9dc19 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -438,6 +438,9 @@ CODE - likewise io.MousePos and GetMousePos() will use OS coordinates. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos. + - 2024/05/21 (1.90.7) - docking: changed signature of DockSpaceOverViewport() to add explicit dockspace id if desired. pass 0 to use old behavior. (#7611) + - old: DockSpaceOverViewport(const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, ...); + - new: DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, ...); - 2024/05/16 (1.90.7) - inputs: on macOS X, Cmd and Ctrl keys are now automatically swapped by io.AddKeyEvent() as this naturally align with how macOS X uses those keys. - it shouldn't really affect you unless you had custom shortcut swapping in place for macOS X apps. - removed ImGuiMod_Shortcut which was previously dynamically remapping to Ctrl or Cmd/Super. It is now unnecessary to specific cross-platform idiomatic shortcuts. (#2343, #4084, #5923, #456) @@ -18488,7 +18491,7 @@ void ImGui::SetWindowDock(ImGuiWindow* window, ImGuiID dock_id, ImGuiCond cond) // The Central Node is always displayed even when empty and shrink/extend according to the requested size of its neighbors. // DockSpace() needs to be submitted _before_ any window they can host. If you use a dockspace, submit it early in your app. // When ImGuiDockNodeFlags_KeepAliveOnly is set, nothing is submitted in the current window (function may be called from any location). -ImGuiID ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags flags, const ImGuiWindowClass* window_class) +ImGuiID ImGui::DockSpace(ImGuiID dockspace_id, const ImVec2& size_arg, ImGuiDockNodeFlags flags, const ImGuiWindowClass* window_class) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); @@ -18504,16 +18507,16 @@ ImGuiID ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags window = GetCurrentWindow(); // call to set window->WriteAccessed = true; IM_ASSERT((flags & ImGuiDockNodeFlags_DockSpace) == 0); - IM_ASSERT(id != 0); - ImGuiDockNode* node = DockContextFindNodeByID(&g, id); - if (!node) + IM_ASSERT(dockspace_id != 0); + ImGuiDockNode* node = DockContextFindNodeByID(&g, dockspace_id); + if (node == NULL) { - IMGUI_DEBUG_LOG_DOCKING("[docking] DockSpace: dockspace node 0x%08X created\n", id); - node = DockContextAddNode(&g, id); + IMGUI_DEBUG_LOG_DOCKING("[docking] DockSpace: dockspace node 0x%08X created\n", dockspace_id); + node = DockContextAddNode(&g, dockspace_id); node->SetLocalFlags(ImGuiDockNodeFlags_CentralNode); } if (window_class && window_class->ClassId != node->WindowClass.ClassId) - IMGUI_DEBUG_LOG_DOCKING("[docking] DockSpace: dockspace node 0x%08X: setup WindowClass 0x%08X -> 0x%08X\n", id, node->WindowClass.ClassId, window_class->ClassId); + IMGUI_DEBUG_LOG_DOCKING("[docking] DockSpace: dockspace node 0x%08X: setup WindowClass 0x%08X -> 0x%08X\n", dockspace_id, node->WindowClass.ClassId, window_class->ClassId); node->SharedFlags = flags; node->WindowClass = window_class ? *window_class : ImGuiWindowClass(); @@ -18523,7 +18526,7 @@ ImGuiID ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags { IM_ASSERT(node->IsDockSpace() == false && "Cannot call DockSpace() twice a frame with the same ID"); node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace); - return id; + return dockspace_id; } node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace); @@ -18531,7 +18534,7 @@ ImGuiID ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags if (flags & ImGuiDockNodeFlags_KeepAliveOnly) { node->LastFrameAlive = g.FrameCount; - return id; + return dockspace_id; } const ImVec2 content_avail = GetContentRegionAvail(); @@ -18556,7 +18559,7 @@ ImGuiID ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags window_flags |= ImGuiWindowFlags_NoBackground; char title[256]; - ImFormatString(title, IM_ARRAYSIZE(title), "%s/DockSpace_%08X", window->Name, id); + ImFormatString(title, IM_ARRAYSIZE(title), "%s/DockSpace_%08X", window->Name, dockspace_id); PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f); Begin(title, NULL, window_flags); @@ -18585,22 +18588,23 @@ ImGuiID ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags ImRect bb(node->Pos, node->Pos + size); ItemSize(size); - ItemAdd(bb, id, NULL, ImGuiItemFlags_NoNav); // Not a nav point (could be, would need to draw the nav rect and replicate/refactor activation from BeginChild(), but seems like CTRL+Tab works better here?) + ItemAdd(bb, dockspace_id, NULL, ImGuiItemFlags_NoNav); // Not a nav point (could be, would need to draw the nav rect and replicate/refactor activation from BeginChild(), but seems like CTRL+Tab works better here?) if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && IsWindowChildOf(g.HoveredWindow, host_window, false, true)) // To fullfill IsItemHovered(), similar to EndChild() g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; - return id; + return dockspace_id; } // Tips: Use with ImGuiDockNodeFlags_PassthruCentralNode! -// The limitation with this call is that your window won't have a menu bar. +// The limitation with this call is that your window won't have a local menu bar, but you can also use BeginMainMenuBar(). // Even though we could pass window flags, it would also require the user to be able to call BeginMenuBar() somehow meaning we can't Begin/End in a single function. -// But you can also use BeginMainMenuBar(). If you really want a menu bar inside the same window as the one hosting the dockspace, you will need to copy this code somewhere and tweak it. -ImGuiID ImGui::DockSpaceOverViewport(const ImGuiViewport* viewport, ImGuiDockNodeFlags dockspace_flags, const ImGuiWindowClass* window_class) +// If you really want a menu bar inside the same window as the one hosting the dockspace, you will need to copy this code somewhere and tweak it. +ImGuiID ImGui::DockSpaceOverViewport(ImGuiID dockspace_id, const ImGuiViewport* viewport, ImGuiDockNodeFlags dockspace_flags, const ImGuiWindowClass* window_class) { if (viewport == NULL) viewport = GetMainViewport(); + // Submit a window filling the entire viewport SetNextWindowPos(viewport->WorkPos); SetNextWindowSize(viewport->WorkSize); SetNextWindowViewport(viewport->ID); @@ -18612,7 +18616,7 @@ ImGuiID ImGui::DockSpaceOverViewport(const ImGuiViewport* viewport, ImGuiDockNod host_window_flags |= ImGuiWindowFlags_NoBackground; char label[32]; - ImFormatString(label, IM_ARRAYSIZE(label), "DockSpaceViewport_%08X", viewport->ID); + ImFormatString(label, IM_ARRAYSIZE(label), "WindowOverViewport_%08X", viewport->ID); PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); @@ -18620,8 +18624,11 @@ ImGuiID ImGui::DockSpaceOverViewport(const ImGuiViewport* viewport, ImGuiDockNod Begin(label, NULL, host_window_flags); PopStyleVar(3); - ImGuiID dockspace_id = GetID("DockSpace"); + // Submit the dockspace + if (dockspace_id == 0) + dockspace_id = GetID("DockSpace"); DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags, window_class); + End(); return dockspace_id; diff --git a/imgui.h b/imgui.h index 4c1080991..75b35e6ab 100644 --- a/imgui.h +++ b/imgui.h @@ -848,14 +848,14 @@ namespace ImGui // - Drag from window menu button (upper-left button) to undock an entire node (all windows). // - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking. // About dockspaces: - // - Use DockSpaceOverViewport() to create an explicit dock node covering the screen or a specific viewport. + // - Use DockSpaceOverViewport() to create a window covering the screen or a specific viewport + a dockspace inside it. // This is often used with ImGuiDockNodeFlags_PassthruCentralNode to make it transparent. // - Use DockSpace() to create an explicit dock node _within_ an existing window. See Docking demo for details. // - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame! // - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked. // e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly. - IMGUI_API ImGuiID DockSpace(ImGuiID id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); - IMGUI_API ImGuiID DockSpaceOverViewport(const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); + IMGUI_API ImGuiID DockSpace(ImGuiID dockspace_id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); + IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (control docking compatibility + provide hints to platform backend via custom viewport flags and platform parent/child relationship) IMGUI_API ImGuiID GetWindowDockID(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d7508f520..bb41ad18f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8450,7 +8450,7 @@ void ShowExampleAppDockSpace(bool* p_open) // If we remove all options we are showcasing, this demo would become: // void ShowExampleAppDockSpace() // { - // ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); + // ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport()); // } // In most cases you should be able to just call DockSpaceOverViewport() and ignore all the code below! // In this specific demo, we are not using DockSpaceOverViewport() because: