mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Docking: Added Docking system. (Part 2) (#351)
This commit is contained in:
		
							
								
								
									
										465
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										465
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -1067,6 +1067,7 @@ ImGuiIO::ImGuiIO() | ||||
|     DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f); | ||||
|  | ||||
|     // Miscellaneous configuration options | ||||
|     ConfigDockingWithKeyMod = true; | ||||
| #ifdef __APPLE__ | ||||
|     ConfigMacOSXBehaviors = true;  // Set Mac OS X style defaults based on __APPLE__ compile time flag | ||||
| #else | ||||
| @@ -2345,7 +2346,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) | ||||
|     AutoFitChildAxises = 0x00; | ||||
|     AutoPosLastDirection = ImGuiDir_None; | ||||
|     HiddenFramesRegular = HiddenFramesForResize = 0; | ||||
|     SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; | ||||
|     SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; | ||||
|     SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); | ||||
|  | ||||
|     LastFrameActive = -1; | ||||
| @@ -2367,6 +2368,12 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) | ||||
|     FocusIdxAllCounter = FocusIdxTabCounter = -1; | ||||
|     FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; | ||||
|     FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX; | ||||
|  | ||||
|     DockNode = DockNodeAsHost = NULL; | ||||
|     DockId = 0; | ||||
|     DockTabItemStatusFlags = 0; | ||||
|     DockOrder = -1; | ||||
|     DockIsActive = DockTabIsVisible = DockTabWantClose = false; | ||||
| } | ||||
|  | ||||
| ImGuiWindow::~ImGuiWindow() | ||||
| @@ -2656,8 +2663,9 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) | ||||
|     if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) | ||||
|         return false; | ||||
|  | ||||
|     // Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect tht case. | ||||
|     if (window->DC.LastItemId == window->MoveId && window->WriteAccessed) | ||||
|     // Special handling for the dummy item after Begin() which represent the title bar or tab.  | ||||
|     // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. | ||||
|     if ((window->DC.LastItemId == window->ID || window->DC.LastItemId == window->MoveId) && window->WriteAccessed) | ||||
|         return false; | ||||
|     return true; | ||||
| } | ||||
| @@ -3042,16 +3050,17 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() | ||||
|     // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame. | ||||
|     // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. | ||||
|     FindHoveredWindow(); | ||||
|     //IM_ASSERT(g.HoveredWindow == NULL || g.HoveredWindow == g.MovingWindow || g.HoveredWindow->Viewport == g.MouseViewport); | ||||
|  | ||||
|     // Modal windows prevents cursor from hovering behind them. | ||||
|     ImGuiWindow* modal_window = GetFrontMostPopupModal(); | ||||
|     if (modal_window) | ||||
|         if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) | ||||
|             g.HoveredRootWindow = g.HoveredWindow = NULL; | ||||
|             g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|  | ||||
|     // Disabled mouse? | ||||
|     if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) | ||||
|         g.HoveredWindow = g.HoveredRootWindow = NULL; | ||||
|         g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|  | ||||
|     // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward. | ||||
|     int mouse_earliest_button_down = -1; | ||||
| @@ -3071,7 +3080,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() | ||||
|     // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) | ||||
|     const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; | ||||
|     if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) | ||||
|         g.HoveredWindow = g.HoveredRootWindow = NULL; | ||||
|         g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|  | ||||
|     // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to imgui + app) | ||||
|     if (g.WantCaptureMouseNextFrame != -1) | ||||
| @@ -3210,9 +3219,16 @@ void ImGui::NewFrame() | ||||
|     g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); | ||||
|     g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; | ||||
|  | ||||
|     // Undocking | ||||
|     // (needs to be before UpdateMovingWindow so the window is already offset and following the mouse on the detaching frame) | ||||
|     DockContextUpdateUndocking(g.DockContext); | ||||
|  | ||||
|     // Find hovered window | ||||
|     // (needs to be before UpdateMovingWindow so we fill HoveredWindowUnderMovingWindow on the mouse release frame) | ||||
|     UpdateHoveredWindowAndCaptureFlags(); | ||||
|  | ||||
|     // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) | ||||
|     UpdateMouseMovingWindow(); | ||||
|     UpdateHoveredWindowAndCaptureFlags(); | ||||
|  | ||||
|     // Background darkening/whitening | ||||
|     if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) | ||||
| @@ -3257,6 +3273,9 @@ void ImGui::NewFrame() | ||||
|     g.CurrentPopupStack.resize(0); | ||||
|     ClosePopupsOverWindow(g.NavWindow); | ||||
|  | ||||
|     // Docking | ||||
|     DockContextUpdateDocking(g.DockContext); | ||||
|  | ||||
|     // Create implicit window - we will only render it if the user has added something to it. | ||||
|     // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. | ||||
|     SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); | ||||
| @@ -3277,6 +3296,10 @@ void ImGui::Initialize(ImGuiContext* context) | ||||
|     ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll; | ||||
|     g.SettingsHandlers.push_back(ini_handler); | ||||
|  | ||||
|     // Docking Extension | ||||
|     IM_ASSERT(g.DockContext == NULL); | ||||
|     DockContextInitialize(&g); | ||||
|  | ||||
|     g.Initialized = true; | ||||
| } | ||||
|  | ||||
| @@ -3297,6 +3320,10 @@ void ImGui::Shutdown(ImGuiContext* context) | ||||
|     if (g.SettingsLoaded && g.IO.IniFilename != NULL) | ||||
|         SaveIniSettingsToDisk(g.IO.IniFilename); | ||||
|  | ||||
|     // Shutdown Docking extensions | ||||
|     IM_ASSERT(g.DockContext != NULL); | ||||
|     DockContextShutdown(&g); | ||||
|  | ||||
|     // Clear everything else | ||||
|     for (int i = 0; i < g.Windows.Size; i++) | ||||
|         IM_DELETE(g.Windows[i]); | ||||
| @@ -3306,8 +3333,7 @@ void ImGui::Shutdown(ImGuiContext* context) | ||||
|     g.CurrentWindowStack.clear(); | ||||
|     g.WindowsById.Clear(); | ||||
|     g.NavWindow = NULL; | ||||
|     g.HoveredWindow = NULL; | ||||
|     g.HoveredRootWindow = NULL; | ||||
|     g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|     g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; | ||||
|     g.MovingWindow = NULL; | ||||
|     g.ColorModifiers.clear(); | ||||
| @@ -3470,6 +3496,14 @@ void ImGui::PopClipRect() | ||||
|     window->ClipRect = window->DrawList->_ClipRectStack.back(); | ||||
| } | ||||
|  | ||||
| static ImGuiWindow* FindFromMostVisibleChildWindow(ImGuiWindow* window) | ||||
| { | ||||
|     for (int n = window->DC.ChildWindows.Size - 1; n >= 0; n--) | ||||
|         if (IsWindowActiveAndVisible(window->DC.ChildWindows[n])) | ||||
|             return FindFromMostVisibleChildWindow(window->DC.ChildWindows[n]); | ||||
|     return window; | ||||
| } | ||||
|  | ||||
| // This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. | ||||
| void ImGui::EndFrame() | ||||
| { | ||||
| @@ -3492,6 +3526,33 @@ void ImGui::EndFrame() | ||||
|         g.CurrentWindow->Active = false; | ||||
|     End(); | ||||
|  | ||||
|     // CTRL-TAB | ||||
|     const bool dim_bg_for_window_list = (g.NavWindowingTargetAnim != NULL); | ||||
|     if (dim_bg_for_window_list) | ||||
|     { | ||||
|         // Choose a draw list that will be front-most across all our children | ||||
|         ImGuiWindow* window = g.NavWindowingTargetAnim; | ||||
|         ImDrawList* draw_list = FindFromMostVisibleChildWindow(window->RootWindow)->DrawList; | ||||
|         draw_list->PushClipRectFullScreen(); | ||||
|  | ||||
|         // Docking: draw modal whitening background on other nodes of a same dock tree | ||||
|         if (window->RootWindowDockStop->DockIsActive) | ||||
|             if (window->RootWindow != window->RootWindowDockStop) | ||||
|                 RenderRectFilledWithHole(draw_list, window->RootWindow->Rect(), window->RootWindowDockStop->Rect(), GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio), g.Style.WindowRounding); | ||||
|  | ||||
|         // Draw navigation selection/windowing rectangle border | ||||
|         float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding); | ||||
|         ImRect bb = window->Rect(); | ||||
|         bb.Expand(g.FontSize); | ||||
|         if (bb.Contains(GetViewportRect())) // If a window fits the entire viewport, adjust its highlight inward | ||||
|         { | ||||
|             bb.Expand(-g.FontSize - 1.0f); | ||||
|             rounding = window->WindowRounding; | ||||
|         } | ||||
|         draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f); | ||||
|         draw_list->PopClipRect(); | ||||
|     } | ||||
|  | ||||
|     // Show CTRL+TAB list | ||||
|     if (g.NavWindowingTarget) | ||||
|         NavUpdateWindowingList(); | ||||
| @@ -3701,10 +3762,11 @@ static void FindHoveredWindow() | ||||
|     ImGuiContext& g = *GImGui; | ||||
|  | ||||
|     ImGuiWindow* hovered_window = NULL; | ||||
|     ImGuiWindow* hovered_window_ignoring_moving_window = NULL; | ||||
|     if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) | ||||
|         hovered_window = g.MovingWindow; | ||||
|  | ||||
|     for (int i = g.Windows.Size - 1; i >= 0 && hovered_window == NULL; i--) | ||||
|     for (int i = g.Windows.Size - 1; i >= 0; i--) | ||||
|     { | ||||
|         ImGuiWindow* window = g.Windows[i]; | ||||
|         if (!window->Active || window->Hidden) | ||||
| @@ -3718,14 +3780,16 @@ static void FindHoveredWindow() | ||||
|         { | ||||
|             if (hovered_window == NULL) | ||||
|                 hovered_window = window; | ||||
|             if (hovered_window) | ||||
|             if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow)) | ||||
|                 hovered_window_ignoring_moving_window = window; | ||||
|             if (hovered_window && hovered_window_ignoring_moving_window) | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     g.HoveredWindow = hovered_window; | ||||
|     g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; | ||||
|  | ||||
|     g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window; | ||||
| } | ||||
|  | ||||
| // Test if mouse cursor is hovering given rectangle | ||||
| @@ -3951,7 +4015,17 @@ bool ImGui::IsItemDeactivatedAfterEdit() | ||||
| bool ImGui::IsItemFocused() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     return g.NavId && !g.NavDisableHighlight && g.NavId == g.CurrentWindow->DC.LastItemId; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|  | ||||
|     if (g.NavId == 0 || g.NavDisableHighlight || g.NavId != window->DC.LastItemId) | ||||
|         return false; | ||||
|  | ||||
|     // Special handling for the dummy item after Begin() which represent the title bar or tab.  | ||||
|     // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. | ||||
|     if (window->DC.LastItemId == window->ID && window->WriteAccessed) | ||||
|         return false; | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool ImGui::IsItemClicked(int mouse_button) | ||||
| @@ -4030,7 +4104,7 @@ static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* parent_window = g.CurrentWindow; | ||||
|  | ||||
|     flags |= ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; | ||||
|     flags |= ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_NoDocking; | ||||
|     flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove);  // Inherit the NoMove flag | ||||
|  | ||||
|     // Size | ||||
| @@ -4163,6 +4237,13 @@ static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, b | ||||
|     window->SetWindowPosAllowFlags       = enabled ? (window->SetWindowPosAllowFlags       | flags) : (window->SetWindowPosAllowFlags       & ~flags); | ||||
|     window->SetWindowSizeAllowFlags      = enabled ? (window->SetWindowSizeAllowFlags      | flags) : (window->SetWindowSizeAllowFlags      & ~flags); | ||||
|     window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags); | ||||
|     window->SetWindowDockAllowFlags      = enabled ? (window->SetWindowDockAllowFlags      | flags) : (window->SetWindowDockAllowFlags      & ~flags); | ||||
| } | ||||
|  | ||||
| ImGuiWindow* ImGui::FindWindowByID(ImGuiID id) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id); | ||||
| } | ||||
|  | ||||
| ImGuiWindow* ImGui::FindWindowByName(const char* name) | ||||
| @@ -4195,6 +4276,8 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl | ||||
|             window->Collapsed = settings->Collapsed; | ||||
|             if (ImLengthSqr(settings->Size) > 0.00001f) | ||||
|                 size = ImFloor(settings->Size); | ||||
|             window->DockId = settings->DockId; | ||||
|             window->DockOrder = settings->DockOrder; | ||||
|         } | ||||
|     window->Size = window->SizeFull = window->SizeFullAtLastBegin = size; | ||||
|     window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values | ||||
| @@ -4220,6 +4303,11 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl | ||||
|     return window; | ||||
| } | ||||
|  | ||||
| static ImGuiWindow* GetWindowForTitleAndMenuHeight(ImGuiWindow* window) | ||||
| { | ||||
|     return (window->DockNodeAsHost && window->DockNodeAsHost->VisibleWindow) ? window->DockNodeAsHost->VisibleWindow : window; | ||||
| } | ||||
|  | ||||
| static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
| @@ -4244,8 +4332,9 @@ static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) | ||||
|     // Minimum size | ||||
|     if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) | ||||
|     { | ||||
|         ImGuiWindow* window_for_height = GetWindowForTitleAndMenuHeight(window); | ||||
|         new_size = ImMax(new_size, g.Style.WindowMinSize); | ||||
|         new_size.y = ImMax(new_size.y, window->TitleBarHeight() + window->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows | ||||
|         new_size.y = ImMax(new_size.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows | ||||
|     } | ||||
|     return new_size; | ||||
| } | ||||
| @@ -4476,7 +4565,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au | ||||
|     } | ||||
|  | ||||
|     // Apply back modified position/size to window | ||||
|     if (size_target.x != FLT_MAX) | ||||
|     if (size_target.x != FLT_MAX && (size_target.x != window->SizeFull.x || size_target.y != window->SizeFull.y)) | ||||
|     { | ||||
|         window->SizeFull = size_target; | ||||
|         MarkIniSettingsDirty(window); | ||||
| @@ -4493,9 +4582,11 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au | ||||
| void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) | ||||
| { | ||||
|     window->ParentWindow = parent_window; | ||||
|     window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window; | ||||
|     window->RootWindow = window->RootWindowDockStop = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window; | ||||
|     if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) | ||||
|         window->RootWindow = parent_window->RootWindow; | ||||
|     if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip) && !window->DockIsActive) | ||||
|         window->RootWindowDockStop = parent_window->RootWindowDockStop; | ||||
|     if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) | ||||
|         window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight; | ||||
|     while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened) | ||||
| @@ -4526,6 +4617,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         window = CreateNewWindow(name, size_on_first_use, flags); | ||||
|     } | ||||
|  | ||||
|     // Update stored window name when it changes (which can only happen with the "###" operator). | ||||
|     // Only if it is meant to be displayed to the end user in a different place than the title bar (which already always display the 'name' parameter) | ||||
|     bool window_title_visible_elsewhere = (window->DockIsActive); | ||||
|     if (!window_just_created && window_title_visible_elsewhere && strcmp(name, window->Name) != 0) | ||||
|     { | ||||
|         IM_DELETE(window->Name); | ||||
|         window->Name = ImStrdup(name); | ||||
|     } | ||||
|  | ||||
|     // Automatically disable manual moving/resizing when NoInputs is set | ||||
|     if (flags & ImGuiWindowFlags_NoInputs) | ||||
|         flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; | ||||
| @@ -4546,12 +4646,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         flags = window->Flags; | ||||
|     } | ||||
|  | ||||
|     // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack | ||||
|     ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); | ||||
|     ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; | ||||
|     IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); | ||||
|     window->HasCloseButton = (p_open != NULL); | ||||
|  | ||||
|     // Update the Appearing flag | ||||
|     bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1);   // Not using !WasActive because the implicit "Debug" window would always toggle off->on | ||||
|     const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0); | ||||
| @@ -4565,6 +4659,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|     if (window->Appearing) | ||||
|         SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); | ||||
|  | ||||
|     // Docking | ||||
|     // (NB: during the frame dock nodes are created, it is possible that (window->DockIsActive == false) even though (window->DockNode->Windows.Size > 1) | ||||
|     IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL); // Cannot be both | ||||
|     if (g.NextWindowData.DockCond) | ||||
|         SetWindowDock(window, g.NextWindowData.DockId, g.NextWindowData.DockCond); | ||||
|     if (first_begin_of_the_frame && (window->DockId != 0 || window->DockNode != NULL)) | ||||
|     { | ||||
|         BeginDocked(window, p_open); | ||||
|         flags = window->Flags; | ||||
|     } | ||||
|  | ||||
|     // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack | ||||
|     ImGuiWindow* parent_window_in_stack = window->DockIsActive ? window->DockNode->HostWindow : g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); | ||||
|     ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; | ||||
|     IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); | ||||
|  | ||||
|     // Add to stack | ||||
|     g.CurrentWindowStack.push_back(window); | ||||
|     SetCurrentWindow(window); | ||||
| @@ -4631,6 +4741,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         UpdateWindowParentAndRootLinks(window, flags, parent_window); | ||||
|  | ||||
|         window->Active = true; | ||||
|         window->HasCloseButton = (p_open != NULL); | ||||
|         window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); | ||||
|         window->LastFrameActive = current_frame; | ||||
|         window->IDStack.resize(1); | ||||
| @@ -4666,16 +4777,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         SetCurrentWindow(window); | ||||
|  | ||||
|         // Lock border size and padding for the frame (so that altering them doesn't cause inconsistencies) | ||||
|         window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; | ||||
|         window->WindowPadding = style.WindowPadding; | ||||
|         if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) | ||||
|         if (window->DockIsActive) | ||||
|             window->WindowBorderSize = 0.0f; | ||||
|         else if (flags & ImGuiWindowFlags_ChildWindow) | ||||
|             window->WindowBorderSize = style.ChildBorderSize; | ||||
|         else | ||||
|             window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; | ||||
|         if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) | ||||
|             window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); | ||||
|         else | ||||
|             window->WindowPadding = style.WindowPadding; | ||||
|         window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); | ||||
|         window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; | ||||
|  | ||||
|         // Collapse window by double-clicking on title bar | ||||
|         // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing | ||||
|         if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) | ||||
|         if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive) | ||||
|         { | ||||
|             // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar. | ||||
|             ImRect title_bar_rect = window->TitleBarRect(); | ||||
| @@ -4719,6 +4836,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|                 MarkIniSettingsDirty(window); | ||||
|         } | ||||
|  | ||||
|         //if (window->DockNode && window->DockIsActive) | ||||
|         //    size_full_modified = window->SizeFull; | ||||
|  | ||||
|         // Apply minimum/maximum window size constraints and final size | ||||
|         window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull); | ||||
|         window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull; | ||||
| @@ -4768,14 +4888,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|             window->Pos = FindBestWindowPosForPopup(window); | ||||
|  | ||||
|         // Clamp position so it stays visible | ||||
|         if (!(flags & ImGuiWindowFlags_ChildWindow)) | ||||
|         // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. | ||||
|         if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) | ||||
|         { | ||||
|             if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. | ||||
|             { | ||||
|                 ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); | ||||
|                 window->Pos = ImMax(window->Pos + window->Size, padding) - window->Size; | ||||
|                 window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding); | ||||
|             } | ||||
|             ImVec2 clamp_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); | ||||
|             window->Pos = ImMax(window->Pos + window->Size, clamp_padding) - window->Size; | ||||
|             window->Pos = ImMin(window->Pos, g.IO.DisplaySize - clamp_padding); | ||||
|         } | ||||
|         window->Pos = ImFloor(window->Pos); | ||||
|  | ||||
| @@ -4795,8 +4913,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         // Apply window focus (new and reactivated windows are moved to front) | ||||
|         bool want_focus = false; | ||||
|         if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) | ||||
|             if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) | ||||
|         { | ||||
|             if (flags & ImGuiWindowFlags_Popup) | ||||
|                 want_focus = true; | ||||
|             else if ((window->DockIsActive || !(flags & ImGuiWindowFlags_ChildWindow)) && !(flags & ImGuiWindowFlags_Tooltip)) | ||||
|                 want_focus = true; | ||||
|         } | ||||
|  | ||||
|         // Handle manual resize: Resize Grips, Borders, Gamepad | ||||
|         int border_held = -1; | ||||
| @@ -4846,7 +4968,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         const float window_rounding = window->WindowRounding; | ||||
|         const float window_border_size = window->WindowBorderSize; | ||||
|         const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; | ||||
|         const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight); | ||||
|         const bool title_bar_is_highlight = want_focus || (window_to_highlight && (window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight || (window->DockNode && window->DockNode == window_to_highlight->DockNode))); | ||||
|         const ImRect title_bar_rect = window->TitleBarRect(); | ||||
|         if (window->Collapsed) | ||||
|         { | ||||
| @@ -4862,16 +4984,17 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|             // Window background | ||||
|             ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); | ||||
|             if (g.NextWindowData.BgAlphaCond != 0) | ||||
|             { | ||||
|                 bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(g.NextWindowData.BgAlphaVal) << IM_COL32_A_SHIFT); | ||||
|                 g.NextWindowData.BgAlphaCond = 0; | ||||
|             } | ||||
|             window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); | ||||
|  | ||||
|             // Title bar | ||||
|             ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); | ||||
|             if (!(flags & ImGuiWindowFlags_NoTitleBar)) | ||||
|             // (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,  | ||||
|             // in order for their pos/size to be matching their undocking state.) | ||||
|             if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive) | ||||
|             { | ||||
|                 ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); | ||||
|                 window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top); | ||||
|             } | ||||
|  | ||||
|             // Menu bar | ||||
|             if (flags & ImGuiWindowFlags_MenuBar) | ||||
| @@ -4911,7 +5034,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|                 ImRect border = GetResizeBorderRect(window, border_held, grip_draw_size, 0.0f); | ||||
|                 window->DrawList->AddLine(border.Min, border.Max, GetColorU32(ImGuiCol_SeparatorActive), ImMax(1.0f, window_border_size)); | ||||
|             } | ||||
|             if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar)) | ||||
|             if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive) | ||||
|                 window->DrawList->AddLine(title_bar_rect.GetBL() + ImVec2(style.WindowBorderSize, -1), title_bar_rect.GetBR() + ImVec2(-style.WindowBorderSize, -1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); | ||||
|         } | ||||
|  | ||||
| @@ -4991,7 +5114,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         } | ||||
|  | ||||
|         // Title bar | ||||
|         if (!(flags & ImGuiWindowFlags_NoTitleBar)) | ||||
|         if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive) | ||||
|         { | ||||
|             // Close & collapse button are on layer 1 (same as menus) and don't default focus | ||||
|             const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; | ||||
| @@ -5007,9 +5130,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|             // Close button | ||||
|             if (p_open != NULL) | ||||
|             { | ||||
|                 const float pad = style.FramePadding.y; | ||||
|                 const float rad = g.FontSize * 0.5f; | ||||
|                 if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1)) | ||||
|                 if (CloseButton(window->GetID("#CLOSE"), ImVec2(window->Pos.x + window->Size.x - style.FramePadding.x - rad, window->Pos.y + style.FramePadding.y + rad), rad + 1)) | ||||
|                     *p_open = false; | ||||
|             } | ||||
|  | ||||
| @@ -5042,6 +5164,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|  | ||||
|         // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() | ||||
|         window->OuterRectClipped = window->Rect(); | ||||
|         if (window->DockIsActive) | ||||
|             window->OuterRectClipped.Min.y += window->TitleBarHeight(); | ||||
|         window->OuterRectClipped.ClipWith(window->ClipRect); | ||||
|  | ||||
|         // Pressing CTRL+C while holding on a window copy its content to the clipboard | ||||
| @@ -5069,13 +5193,39 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize))); | ||||
|         window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y); | ||||
|  | ||||
|         // After Begin() we fill the last item / hovered data based on title bar data. It is a standard behavior (to allow creation of context menus on title bar only, etc.). | ||||
|         window->DC.LastItemId = window->MoveId; | ||||
|         window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0; | ||||
|         window->DC.LastItemRect = title_bar_rect; | ||||
|         if (g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable) | ||||
|         { | ||||
|             // Docking: Dragging a dockable window (or any of its child) turns it into a drag and drop source. | ||||
|             // We need to do this _before_ we overwrite window->DC.LastItemId below because BeginAsDockableDragDropSource() also overwrites it. | ||||
|             if ((g.ActiveId == window->MoveId) && ((g.IO.ConfigDockingWithKeyMod && g.IO.KeyShift) || (!g.IO.ConfigDockingWithKeyMod))) | ||||
|                 if ((window->RootWindow->Flags & (ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking)) == 0) | ||||
|                     BeginAsDockableDragDropSource(window); | ||||
|  | ||||
|             // Docking: Any dockable window can act as a target. For dock node hosts we call BeginAsDockableDragDropTarget() in DockNodeUpdate() instead. | ||||
|             if (g.DragDropActive && !(flags & ImGuiWindowFlags_NoDocking)) | ||||
|                 if (g.MovingWindow == NULL || g.MovingWindow->RootWindow != window) | ||||
|                     if ((window == window->RootWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost)) | ||||
|                         BeginAsDockableDragDropTarget(window); | ||||
|         } | ||||
|  | ||||
|         // We fill last item data based on Title Bar or Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). | ||||
|         // This is useful to allow creating context menus on title bar only, etc. | ||||
|         if (window->DockIsActive) | ||||
|         { | ||||
|             window->DC.LastItemId = window->ID; | ||||
|             window->DC.LastItemStatusFlags = window->DockTabItemStatusFlags; | ||||
|             window->DC.LastItemRect = window->DockTabItemRect; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             window->DC.LastItemId = window->MoveId; | ||||
|             window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0; | ||||
|             window->DC.LastItemRect = title_bar_rect; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); | ||||
|     if (!(flags & ImGuiWindowFlags_DockNodeHost)) | ||||
|         PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); | ||||
|  | ||||
|     // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) | ||||
|     if (first_begin_of_the_frame) | ||||
| @@ -5084,12 +5234,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|     window->BeginCount++; | ||||
|     g.NextWindowData.Clear(); | ||||
|  | ||||
|     if (window->DockIsActive && !window->DockTabIsVisible) | ||||
|         window->HiddenFramesRegular = 1; | ||||
|  | ||||
|     if (flags & ImGuiWindowFlags_ChildWindow) | ||||
|     { | ||||
|         // Child window can be out of sight and have "negative" clip windows. | ||||
|         // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar). | ||||
|         IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0); | ||||
|  | ||||
|         IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0 || (window->DockIsActive)); | ||||
|         if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) | ||||
|             if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y) | ||||
|                 window->HiddenFramesRegular = 1; | ||||
| @@ -5104,7 +5256,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         window->HiddenFramesRegular = 1; | ||||
|  | ||||
|     // Update the Hidden flag | ||||
|     window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize); | ||||
|     window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize > 0); | ||||
|  | ||||
|     // Return false if we don't intend to display anything to allow user to perform an early out optimization | ||||
|     window->SkipItems = (window->Collapsed || !window->Active || window->Hidden) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesForResize <= 0; | ||||
| @@ -5135,12 +5287,18 @@ void ImGui::End() | ||||
|  | ||||
|     if (window->DC.ColumnsSet != NULL) | ||||
|         EndColumns(); | ||||
|     PopClipRect();   // Inner window clip rectangle | ||||
|     if (!(window->Flags & ImGuiWindowFlags_DockNodeHost))   // Pop inner window clip rectangle | ||||
|         PopClipRect(); | ||||
|  | ||||
|     // Stop logging | ||||
|     if (!(window->Flags & ImGuiWindowFlags_ChildWindow))    // FIXME: add more options for scope of logging | ||||
|         LogFinish(); | ||||
|  | ||||
|     // Docking: report contents sizes to parent to allow for auto-resize | ||||
|     if (window->DockNode && window->DockTabIsVisible) | ||||
|         if (ImGuiWindow* host_window = window->DockNode->HostWindow)         // FIXME-DOCKSPACE | ||||
|             host_window->DC.CursorMaxPos = window->DC.CursorMaxPos + window->WindowPadding - host_window->WindowPadding; | ||||
|  | ||||
|     // Pop from window stack | ||||
|     g.CurrentWindowStack.pop_back(); | ||||
|     if (window->Flags & ImGuiWindowFlags_Popup) | ||||
| @@ -5192,7 +5350,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) | ||||
|         g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId | ||||
|         g.NavIdIsAlive = false; | ||||
|         g.NavLayer = 0; | ||||
|         //printf("[%05d] FocusWindow(\"%s\")\n", g.FrameCount, window ? window->Name : NULL); | ||||
|         //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL); | ||||
|     } | ||||
|  | ||||
|     // Passing NULL allow to disable keyboard focus | ||||
| @@ -5511,6 +5669,8 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) | ||||
|     case ImGuiCol_TabActive: return "TabActive"; | ||||
|     case ImGuiCol_TabUnfocused: return "TabUnfocused"; | ||||
|     case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive"; | ||||
|     case ImGuiCol_DockingPreview: return "DockingPreview"; | ||||
|     case ImGuiCol_DockingBg: return "DockingBg"; | ||||
|     case ImGuiCol_PlotLines: return "PlotLines"; | ||||
|     case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; | ||||
|     case ImGuiCol_PlotHistogram: return "PlotHistogram"; | ||||
| @@ -5554,11 +5714,11 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) | ||||
|         switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) | ||||
|         { | ||||
|         case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: | ||||
|             if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) | ||||
|             if (g.HoveredWindow == NULL || g.HoveredWindow->RootWindowDockStop != g.CurrentWindow->RootWindowDockStop) | ||||
|                 return false; | ||||
|             break; | ||||
|         case ImGuiHoveredFlags_RootWindow: | ||||
|             if (g.HoveredWindow != g.CurrentWindow->RootWindow) | ||||
|             if (g.HoveredWindow != g.CurrentWindow->RootWindowDockStop) | ||||
|                 return false; | ||||
|             break; | ||||
|         case ImGuiHoveredFlags_ChildWindows: | ||||
| @@ -5591,9 +5751,9 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) | ||||
|     switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) | ||||
|     { | ||||
|     case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: | ||||
|         return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; | ||||
|         return g.NavWindow && g.NavWindow->RootWindowDockStop == g.CurrentWindow->RootWindowDockStop; | ||||
|     case ImGuiFocusedFlags_RootWindow: | ||||
|         return g.NavWindow == g.CurrentWindow->RootWindow; | ||||
|         return g.NavWindow == g.CurrentWindow->RootWindowDockStop; | ||||
|     case ImGuiFocusedFlags_ChildWindows: | ||||
|         return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); | ||||
|     default: | ||||
| @@ -5601,10 +5761,16 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool ImGui::IsWindowDocked() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     return (g.CurrentWindow->DockIsActive); | ||||
| } | ||||
|  | ||||
| // Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) | ||||
| bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) | ||||
| { | ||||
|     return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); | ||||
|     return window->Active && window == window->RootWindowDockStop && !(window->Flags & ImGuiWindowFlags_NoNavFocus); | ||||
| } | ||||
|  | ||||
| float ImGui::GetWindowWidth() | ||||
| @@ -5777,6 +5943,7 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi | ||||
|     g.NextWindowData.PosVal = pos; | ||||
|     g.NextWindowData.PosPivotVal = pivot; | ||||
|     g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; | ||||
|     g.NextWindowData.PosUndock = true; | ||||
| } | ||||
|  | ||||
| void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) | ||||
| @@ -5824,6 +5991,13 @@ void ImGui::SetNextWindowBgAlpha(float alpha) | ||||
|     g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op) | ||||
| } | ||||
|  | ||||
| void ImGui::SetNextWindowDock(ImGuiID id, ImGuiCond cond) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     g.NextWindowData.DockCond = cond ? cond : ImGuiCond_Always; | ||||
|     g.NextWindowData.DockId = id; | ||||
| } | ||||
|  | ||||
| // In window space (not screen space!) | ||||
| ImVec2 ImGui::GetContentRegionMax() | ||||
| { | ||||
| @@ -6280,7 +6454,7 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_ | ||||
|                 window->HiddenFramesRegular = 1; | ||||
|                 ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); | ||||
|             } | ||||
|     ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoNav; | ||||
|     ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoNav|ImGuiWindowFlags_NoDocking; | ||||
|     Begin(window_name, NULL, flags | extra_flags); | ||||
| } | ||||
|  | ||||
| @@ -6494,7 +6668,7 @@ bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) | ||||
|         g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values | ||||
|         return false; | ||||
|     } | ||||
|     return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); | ||||
|     return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoDocking); | ||||
| } | ||||
|  | ||||
| bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
| @@ -6992,8 +7166,8 @@ static void NavRestoreLayer(int layer) | ||||
|     g.NavLayer = layer; | ||||
|     if (layer == 0) | ||||
|         g.NavWindow = ImGui::NavRestoreLastChildNavWindow(g.NavWindow); | ||||
|     if (layer == 0 && g.NavWindow->NavLastIds[0] != 0) | ||||
|         ImGui::SetNavIDWithRectRel(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]); | ||||
|     if (g.NavWindow->NavLastIds[layer] != 0) | ||||
|         ImGui::SetNavIDWithRectRel(g.NavWindow->NavLastIds[layer], layer, g.NavWindow->NavRectRel[layer]); | ||||
|     else | ||||
|         ImGui::NavInitWindow(g.NavWindow, true); | ||||
| } | ||||
| @@ -7034,7 +7208,10 @@ static ImVec2 ImGui::NavCalcPreferredRefPos() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow) | ||||
|     { | ||||
|         IM_ASSERT(ImGui::IsMousePosValid()); // This will probably trigger at some point, please share your repro! | ||||
|         return ImFloor(g.IO.MousePos); | ||||
|     } | ||||
|  | ||||
|     // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item | ||||
|     const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; | ||||
| @@ -7215,7 +7392,7 @@ static void ImGui::NavUpdate() | ||||
|         { | ||||
|             ClearActiveID(); | ||||
|         } | ||||
|         else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) | ||||
|         else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow && g.NavWindow != g.NavWindow->RootWindowDockStop) | ||||
|         { | ||||
|             // Exit child window | ||||
|             ImGuiWindow* child_window = g.NavWindow; | ||||
| @@ -7596,7 +7773,7 @@ static void ImGui::NavUpdateWindowing() | ||||
|     } | ||||
|  | ||||
|     // Apply final focus | ||||
|     if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow)) | ||||
|     if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindowDockStop)) | ||||
|     { | ||||
|         g.NavDisableHighlight = false; | ||||
|         g.NavDisableMouseHover = true; | ||||
| @@ -7618,7 +7795,10 @@ static void ImGui::NavUpdateWindowing() | ||||
|     { | ||||
|         // Move to parent menu if necessary | ||||
|         ImGuiWindow* new_nav_window = g.NavWindow; | ||||
|         while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) | ||||
|         while (new_nav_window->ParentWindow | ||||
|             && (new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0  | ||||
|             && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0  | ||||
|             && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) | ||||
|             new_nav_window = new_nav_window->ParentWindow; | ||||
|         if (new_nav_window != g.NavWindow) | ||||
|         { | ||||
| @@ -7628,7 +7808,13 @@ static void ImGui::NavUpdateWindowing() | ||||
|         } | ||||
|         g.NavDisableHighlight = false; | ||||
|         g.NavDisableMouseHover = true; | ||||
|         NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0); | ||||
|  | ||||
|         // When entering a regular menu bar with the Alt key, we always reinitialize the navigation ID. It however persist on docking tab tabs. | ||||
|         const int new_nav_layer = (g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0; | ||||
|         const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL); | ||||
|         if (new_nav_layer == 1 && !preserve_layer_1_nav_id) | ||||
|             g.NavWindow->NavLastIds[1] = 0; | ||||
|         NavRestoreLayer(new_nav_layer); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -7639,6 +7825,8 @@ static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window) | ||||
|         return "(Popup)"; | ||||
|     if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0) | ||||
|         return "(Main menu bar)"; | ||||
|     if (window->DockNodeAsHost) | ||||
|         return "(Dock node)"; | ||||
|     return "(Untitled)"; | ||||
| } | ||||
|  | ||||
| @@ -8178,7 +8366,7 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) | ||||
|         return false; | ||||
|  | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|     if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) | ||||
|     if (g.HoveredWindowUnderMovingWindow == NULL || window->RootWindow != g.HoveredWindowUnderMovingWindow->RootWindow) | ||||
|         return false; | ||||
|     IM_ASSERT(id != 0); | ||||
|     if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId)) | ||||
| @@ -8206,7 +8394,7 @@ bool ImGui::BeginDragDropTarget() | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|     if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) | ||||
|         return false; | ||||
|     if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) | ||||
|     if (g.HoveredWindowUnderMovingWindow == NULL || window->RootWindow != g.HoveredWindowUnderMovingWindow->RootWindow) | ||||
|         return false; | ||||
|  | ||||
|     const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect; | ||||
| @@ -8663,6 +8851,7 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) | ||||
|     } | ||||
|     ImGui::MemFree(buf); | ||||
|     g.SettingsLoaded = true; | ||||
|     DockContextOnLoadSettings(); | ||||
| } | ||||
|  | ||||
| void ImGui::SaveIniSettingsToDisk(const char* ini_filename) | ||||
| @@ -8711,9 +8900,12 @@ static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, | ||||
|     ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; | ||||
|     float x, y; | ||||
|     int i; | ||||
|     if (sscanf(line, "Pos=%f,%f", &x, &y) == 2)         settings->Pos = ImVec2(x, y); | ||||
|     else if (sscanf(line, "Size=%f,%f", &x, &y) == 2)   settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize); | ||||
|     else if (sscanf(line, "Collapsed=%d", &i) == 1)     settings->Collapsed = (i != 0); | ||||
|     ImU32 u1; | ||||
|     if (sscanf(line, "Pos=%f,%f", &x, &y) == 2)                 { settings->Pos = ImVec2(x, y); } | ||||
|     else if (sscanf(line, "Size=%f,%f", &x, &y) == 2)           { settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize); } | ||||
|     else if (sscanf(line, "Collapsed=%d", &i) == 1)             { settings->Collapsed = (i != 0); } | ||||
|     else if (sscanf(line, "DockId=0x%X,%d", &u1, &i) == 2)      { settings->DockId = u1; settings->DockOrder = (short)i; } | ||||
|     else if (sscanf(line, "DockId=0x%X", &u1) == 1)             { settings->DockId = u1; settings->DockOrder = -1; } | ||||
| } | ||||
|  | ||||
| static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) | ||||
| @@ -8721,6 +8913,8 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting | ||||
|     // Gather data from windows that were active during this session | ||||
|     // (if a window wasn't opened in this session we preserve its settings) | ||||
|     ImGuiContext& g = *imgui_ctx; | ||||
|     if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)) | ||||
|         return; | ||||
|     for (int i = 0; i != g.Windows.Size; i++) | ||||
|     { | ||||
|         ImGuiWindow* window = g.Windows[i]; | ||||
| @@ -8736,6 +8930,9 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting | ||||
|         IM_ASSERT(settings->ID == window->ID); | ||||
|         settings->Pos = window->Pos; | ||||
|         settings->Size = window->SizeFull; | ||||
|         IM_ASSERT(window->DockNode == NULL || window->DockNode->ID == window->DockId); | ||||
|         settings->DockId = window->DockId; | ||||
|         settings->DockOrder = window->DockOrder; | ||||
|         settings->Collapsed = window->Collapsed; | ||||
|     } | ||||
|  | ||||
| @@ -8744,8 +8941,6 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting | ||||
|     for (int i = 0; i != g.SettingsWindows.Size; i++) | ||||
|     { | ||||
|         const ImGuiWindowSettings* settings = &g.SettingsWindows[i]; | ||||
|         if (settings->Pos.x == FLT_MAX) | ||||
|             continue; | ||||
|         const char* name = settings->Name; | ||||
|         if (const char* p = strstr(name, "###"))  // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() | ||||
|             name = p; | ||||
| @@ -8753,6 +8948,14 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting | ||||
|         buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y); | ||||
|         buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y); | ||||
|         buf->appendf("Collapsed=%d\n", settings->Collapsed); | ||||
|         if (settings->DockId != 0) | ||||
|         { | ||||
|             // Write DockId as 4 digits if possible. Automatic DockId are small numbers, but full explicit DockSpace() are full ImGuiID range. | ||||
|             if (settings->DockOrder == -1) | ||||
|                 buf->appendf("DockId=0x%08X\n", settings->DockId); | ||||
|             else | ||||
|                 buf->appendf("DockId=0x%08X,%d\n", settings->DockId, settings->DockOrder); | ||||
|         } | ||||
|         buf->appendf("\n"); | ||||
|     } | ||||
| } | ||||
| @@ -8899,6 +9102,32 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|  | ||||
|     struct Funcs | ||||
|     { | ||||
|         static void NodeDockNode(ImGuiDockNode* node, const char* label) | ||||
|         { | ||||
|             ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once); | ||||
|             bool open;  | ||||
|             if (node->Windows.Size > 0) | ||||
|                 open = ImGui::TreeNode((void*)(intptr_t)node->ID, "%s 0x%04X%s: %d windows (vis: '%s')", label, node->ID, node->IsVisible ? "" : " (hidden)", node->Windows.Size, node->VisibleWindow ? node->VisibleWindow->Name : "NULL"); | ||||
|             else | ||||
|                 open = ImGui::TreeNode((void*)(intptr_t)node->ID, "%s 0x%04X%s: split %s (act: '%s')", label, node->ID, node->IsVisible ? "" : " (hidden)", (node->SplitAxis == ImGuiAxis_X) ? "horizontal" : (node->SplitAxis == ImGuiAxis_Y) ? "vertical" : "n/a", node->VisibleWindow ? node->VisibleWindow->Name : "NULL"); | ||||
|             if (open) | ||||
|             { | ||||
|                 IM_ASSERT(node->ChildNodes[0] == NULL || node->ChildNodes[0]->ParentNode == node); | ||||
|                 IM_ASSERT(node->ChildNodes[1] == NULL || node->ChildNodes[1]->ParentNode == node); | ||||
|                 ImGui::BulletText("Pos (%.0f,%.0f), Size (%.0f, %.0f), LastExplicit (%.0f, %.0f)%s%s",  | ||||
|                     node->Pos.x, node->Pos.y, node->Size.x, node->Size.y,  | ||||
|                     node->LastExplicitSize.x, node->LastExplicitSize.y, | ||||
|                     node->IsExplicitRoot ? ", IsExplicitRoot " : "", node->IsDocumentRoot ? ", IsDocumentRoot " : ""); | ||||
|                 if (node->ChildNodes[0]) | ||||
|                     NodeDockNode(node->ChildNodes[0], "Child[0]"); | ||||
|                 if (node->ChildNodes[1]) | ||||
|                     NodeDockNode(node->ChildNodes[1], "Child[1]"); | ||||
|                 if (node->TabBar) | ||||
|                     NodeTabBar(node->TabBar); | ||||
|                 ImGui::TreePop(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         static void NodeTabBar(ImGuiTabBar* tab_bar) | ||||
|         { | ||||
|             // Previous window list | ||||
| @@ -9027,7 +9256,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|                 ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); | ||||
|             else | ||||
|                 ImGui::BulletText("NavRectRel[0]: <None>"); | ||||
|             ImGui::BulletText("DockId: 0x%04X, DockOrder: %d, %s: 0x%p", window->DockId, window->DockOrder, window->DockNodeAsHost ? "DockNodeAsHost" : "DockNode", window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode); | ||||
|             if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); | ||||
|             if (window->RootWindowDockStop != window->RootWindow) NodeWindow(window->RootWindowDockStop, "RootWindowDockStop"); | ||||
|             if (window->ParentWindow != NULL) NodeWindow(window->ParentWindow, "ParentWindow"); | ||||
|             if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); | ||||
|             if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) | ||||
| @@ -9059,6 +9290,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|             Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList"); | ||||
|         ImGui::TreePop(); | ||||
|     } | ||||
|  | ||||
|     if (ImGui::TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) | ||||
|     { | ||||
|         for (int i = 0; i < g.OpenPopupStack.Size; i++) | ||||
| @@ -9068,17 +9300,93 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|         } | ||||
|         ImGui::TreePop(); | ||||
|     } | ||||
|     if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.Data.Size)) | ||||
|  | ||||
|     if (ImGui::TreeNode("Docking")) | ||||
|     { | ||||
|         for (int n = 0; n < g.TabBars.Data.Size; n++) | ||||
|             Funcs::NodeTabBar(g.TabBars.GetByIndex(n)); | ||||
|         ImGuiDockContext* ctx = g.DockContext; | ||||
|         static bool show_window_dock_info = false; | ||||
|         ImGui::Checkbox("Ctrl shows window dock info", &show_window_dock_info); | ||||
|  | ||||
|         if (ImGui::TreeNode("Dock nodes")) | ||||
|         { | ||||
|             if (ImGui::SmallButton("Clear settings"))   { DockContextClearNodes(ctx, true); } | ||||
|             ImGui::SameLine(); | ||||
|             if (ImGui::SmallButton("Rebuild all"))      { ctx->WantFullRebuild = true; } | ||||
|             for (int n = 0; n < ctx->Nodes.Data.Size; n++) | ||||
|                 if (ImGuiDockNode* node = (ImGuiDockNode*)ctx->Nodes.Data[n].val_p) | ||||
|                     if (node->IsRootNode()) | ||||
|                         Funcs::NodeDockNode(node, "Node"); | ||||
|             ImGui::TreePop(); | ||||
|         } | ||||
|  | ||||
|         if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.Data.Size)) | ||||
|         { | ||||
|             for (int n = 0; n < g.TabBars.Data.Size; n++) | ||||
|                 Funcs::NodeTabBar(g.TabBars.GetByIndex(n)); | ||||
|             ImGui::TreePop(); | ||||
|         } | ||||
|  | ||||
|         if (ImGui::TreeNode("Settings")) | ||||
|         { | ||||
|             if (ImGui::SmallButton("Refresh")) | ||||
|                 SaveIniSettingsToMemory(); | ||||
|             ImGui::SameLine(); | ||||
|             if (ImGui::SmallButton("Save to disk")) | ||||
|                 SaveIniSettingsToDisk(g.IO.IniFilename); | ||||
|             ImGui::Separator(); | ||||
|             ImGui::Text("Docked Windows:"); | ||||
|             for (int n = 0; n < g.SettingsWindows.Size; n++) | ||||
|                 if (g.SettingsWindows[n].DockId != 0) | ||||
|                     ImGui::BulletText("Window '%s' -> DockId %08X", g.SettingsWindows[n].Name, g.SettingsWindows[n].DockId); | ||||
|             ImGui::Separator(); | ||||
|             ImGui::Text("Dock Nodes:"); | ||||
|             for (int n = 0; n < ctx->SettingsNodes.Size; n++) | ||||
|             { | ||||
|                 ImGuiDockNodeSettings* settings = &ctx->SettingsNodes[n]; | ||||
|                 const char* selected_tab_name = NULL; | ||||
|                 if (settings->SelectedTabID) | ||||
|                 { | ||||
|                     if (ImGuiWindow* window = FindWindowByID(settings->SelectedTabID)) | ||||
|                         selected_tab_name = window->Name; | ||||
|                     else if (ImGuiWindowSettings* window_settings = FindWindowSettings(settings->SelectedTabID)) | ||||
|                         selected_tab_name = window_settings->Name; | ||||
|                 } | ||||
|                 ImGui::BulletText("Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->ID, settings->ParentID, settings->SelectedTabID, selected_tab_name ? selected_tab_name : settings->SelectedTabID ? "N/A" : ""); | ||||
|             } | ||||
|             ImGui::TreePop(); | ||||
|         } | ||||
|  | ||||
|         if (g.IO.KeyCtrl && show_window_dock_info) | ||||
|         { | ||||
|             for (int n = 0; n < ctx->Nodes.Data.Size; n++) | ||||
|                 if (ImGuiDockNode* node = (ImGuiDockNode*)ctx->Nodes.Data[n].val_p) | ||||
|                 { | ||||
|                     ImGuiDockNode* root_node = DockNodeGetRootNode(node); | ||||
|                     if (ImGuiDockNode* hovered_node = DockNodeTreeFindNodeByPos(root_node, g.IO.MousePos)) | ||||
|                         if (hovered_node != node) | ||||
|                             continue; | ||||
|                     char buf[64] = ""; | ||||
|                     char* p = buf; | ||||
|                     ImDrawList* overlay_draw_list = GetOverlayDrawList(); | ||||
|                     p += ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p, "DockId: %X%s\n", node->ID, node->IsDocumentRoot ? " *DocRoot*" : ""); | ||||
|                     p += ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p, "Size: (%.0f, %.0f)\n", node->Size.x, node->Size.y); | ||||
|                     p += ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p, "Explicit: (%.0f, %.0f)\n", node->LastExplicitSize.x, node->LastExplicitSize.y); | ||||
|                     int depth = DockNodeGetDepth(node); | ||||
|                     overlay_draw_list->AddRect(node->Pos + ImVec2(3,3) * (float)depth, node->Pos + node->Size - ImVec2(3,3) * (float)depth, IM_COL32(200, 100, 100, 255)); | ||||
|                     ImVec2 pos = node->Pos + ImVec2(3,3) * (float)depth; | ||||
|                     overlay_draw_list->AddRectFilled(pos - ImVec2(1, 1), pos + CalcTextSize(buf) + ImVec2(1, 1), IM_COL32(200, 100, 100, 255)); | ||||
|                     overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf); | ||||
|                 } | ||||
|         } | ||||
|         ImGui::TreePop(); | ||||
|     } | ||||
|  | ||||
|     if (ImGui::TreeNode("Internal state")) | ||||
|     { | ||||
|         const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); | ||||
|         ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); | ||||
|         ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); | ||||
|         ImGui::Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); | ||||
|         ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not | ||||
|         ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); | ||||
|         ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); | ||||
| @@ -9094,7 +9402,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|         ImGui::TreePop(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     if (g.IO.KeyCtrl && show_window_begin_order) | ||||
|     { | ||||
|         for (int n = 0; n < g.Windows.Size; n++) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user