mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Refactor: Internals: Moved Viewport functions in imgui.cpp in their own section. (part 3) (#2036, #1542)
This commit is contained in:
		
							
								
								
									
										320
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -56,6 +56,7 @@ CODE | ||||
| - Main Code (most of the code! lots of stuff, needs tidying up) | ||||
| - Tooltips | ||||
| - Popups | ||||
| - Viewports, Platform Windows | ||||
| - Navigation | ||||
| - Columns | ||||
| - Drag and Drop | ||||
| @@ -911,7 +912,6 @@ static void             SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, | ||||
| // Platform Dependents default implementation for IO functions | ||||
| static const char*      GetClipboardTextFn_DefaultImpl(void* user_data); | ||||
| static void             SetClipboardTextFn_DefaultImpl(void* user_data, const char* text); | ||||
| static void             ImeSetInputScreenPosFn_DefaultImpl(int x, int y); | ||||
|  | ||||
| namespace ImGui | ||||
| { | ||||
| @@ -3582,53 +3582,6 @@ void ImGui::Render() | ||||
| #endif | ||||
| } | ||||
|  | ||||
| ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& pos, const ImVec2& size, ImGuiViewportFlags flags) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     IM_ASSERT(id != 0); | ||||
|  | ||||
|     ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id); | ||||
|     if (viewport) | ||||
|     { | ||||
|         viewport->Pos = pos; | ||||
|         viewport->Size = size; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // New viewport | ||||
|         viewport = IM_NEW(ImGuiViewportP)(); | ||||
|         viewport->ID = id; | ||||
|         viewport->Idx = g.Viewports.Size; | ||||
|         viewport->Pos = viewport->LastPos = pos; | ||||
|         viewport->Size = size; | ||||
|         viewport->PlatformMonitor = FindPlatformMonitorForRect(viewport->GetRect()); | ||||
|         g.Viewports.push_back(viewport); | ||||
|  | ||||
|         if (window && (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)) | ||||
|             flags |= ImGuiViewportFlags_NoFocusOnAppearing; | ||||
|  | ||||
|         // We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport. | ||||
|         // We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame | ||||
|         g.DrawListSharedData.ClipRectFullscreen.z = ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x); | ||||
|         g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y); | ||||
|  | ||||
|         // Request an initial DpiScale before the OS platform window creation | ||||
|         // This is so we can select an appropriate font size on the first frame of our window lifetime | ||||
|         if (g.PlatformIO.Platform_GetWindowDpiScale) | ||||
|             viewport->DpiScale = g.PlatformIO.Platform_GetWindowDpiScale(viewport); | ||||
|     } | ||||
|  | ||||
|     viewport->Window = window; | ||||
|     viewport->Flags = flags; | ||||
|     viewport->LastFrameActive = g.FrameCount; | ||||
|     IM_ASSERT(window == NULL || viewport->ID == window->ID); | ||||
|  | ||||
|     if (window != NULL) | ||||
|         window->ViewportOwned = true; | ||||
|  | ||||
|     return viewport; | ||||
| } | ||||
|  | ||||
| const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) | ||||
| { | ||||
|     const char* text_display_end = text; | ||||
| @@ -4636,118 +4589,6 @@ static int ImGui::FindPlatformMonitorForRect(const ImRect& rect) | ||||
|     return best_monitor_n; | ||||
| } | ||||
|  | ||||
| // FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten. | ||||
| static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindowFlags flags = window->Flags; | ||||
|     window->ViewportAllowPlatformMonitorExtend = -1; | ||||
|  | ||||
|     // Restore main viewport if multi-viewport is not supported by the back-end | ||||
|     ImGuiViewportP* main_viewport = g.Viewports[0]; | ||||
|     if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) | ||||
|     { | ||||
|         window->Viewport = main_viewport; | ||||
|         window->ViewportId = main_viewport->ID; | ||||
|         window->ViewportOwned = false; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // Merge into host viewports (after moving, resizing) | ||||
|     if (window->ViewportOwned && window->ViewportTryMerge && g.ActiveId == 0) | ||||
|     { | ||||
|         UpdateTryMergeWindowIntoHostViewport(window, g.Viewports[0]); | ||||
|         window->ViewportTryMerge = false; | ||||
|     } | ||||
|     window->ViewportOwned = false; | ||||
|  | ||||
|     // Appearing popups reset their viewport so they can inherit again | ||||
|     if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing) | ||||
|     { | ||||
|         window->Viewport = NULL; | ||||
|         window->ViewportId = 0; | ||||
|     } | ||||
|  | ||||
|     if (!g.NextWindowData.ViewportCond) | ||||
|     { | ||||
|         // By default inherit from parent window | ||||
|         if (window->Viewport == NULL && window->ParentWindow) | ||||
|             window->Viewport = window->ParentWindow->Viewport; | ||||
|  | ||||
|         // Attempt to restore saved viewport id (= window that hasn't been activated yet), try to restore the viewport based on saved 'window->ViewportPos' restored from .ini file | ||||
|         if (window->Viewport == NULL && window->ViewportId != 0) | ||||
|         { | ||||
|             window->Viewport = FindViewportByID(window->ViewportId); | ||||
|             if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX) | ||||
|                 window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_NoDecoration); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (g.NextWindowData.ViewportCond) | ||||
|     { | ||||
|         // Code explicitly request a viewport | ||||
|         window->Viewport = FindViewportByID(g.NextWindowData.ViewportId); | ||||
|         window->ViewportId = g.NextWindowData.ViewportId; // Store ID even if Viewport isn't resolved yet. | ||||
|     } | ||||
|     else if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu)) | ||||
|     { | ||||
|         // Always inherit viewport from parent window | ||||
|         window->Viewport = window->ParentWindow->Viewport; | ||||
|     } | ||||
|     else if (flags & ImGuiWindowFlags_Tooltip) | ||||
|     { | ||||
|         window->Viewport = g.MouseViewport; | ||||
|     } | ||||
|     else if (g.MovingWindow && g.MovingWindow->RootWindow == window && IsMousePosValid()) | ||||
|     { | ||||
|         // Transition to our own viewport when leaving our host boundaries + set the NoInputs flag (which will be cleared in UpdateMovingWindow when releasing the mouse) | ||||
|         // If we are already in our own viewport, if need to set the NoInputs flag. | ||||
|         // If we have no viewport (which happens when detaching a docked node) immediately create one. | ||||
|         // We test for 'window->Viewport->Window == window' instead of 'window->ViewportOwned' because ViewportOwned is not valid during this function. | ||||
|         bool has_viewport = (window->Viewport != NULL); | ||||
|         bool own_viewport = has_viewport && (window->Viewport->Window == window); | ||||
|         bool leave_host_viewport = has_viewport && !own_viewport && !window->Viewport->GetRect().Contains(window->Rect()); | ||||
|         bool move_from_own_viewport = has_viewport && own_viewport && !(window->Viewport->Flags & ImGuiViewportFlags_NoInputs); | ||||
|         if (!has_viewport || leave_host_viewport || move_from_own_viewport) | ||||
|             window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs); | ||||
|     } | ||||
|     else if (GetWindowAlwaysWantOwnViewport(window)) | ||||
|     { | ||||
|         window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration); | ||||
|     } | ||||
|  | ||||
|     // Mark window as allowed to protrude outside of its viewport and into the current monitor | ||||
|     // We need to take account of the possibility that mouse may become invalid. | ||||
|     const bool use_mouse_ref = (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow); | ||||
|     if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) | ||||
|     { | ||||
|         ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.CurrentPopupStack.back().OpenMousePos; | ||||
|         bool mouse_valid = IsMousePosValid(&mouse_ref); | ||||
|         if ((window->Appearing || (flags & ImGuiWindowFlags_Tooltip)) && (!use_mouse_ref || mouse_valid)) | ||||
|             window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos()); | ||||
|         else | ||||
|             window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor; | ||||
|     } | ||||
|     if (window->ViewportTrySplit && window->ViewportAllowPlatformMonitorExtend < 0) | ||||
|         window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor; | ||||
|     window->ViewportTrySplit = false; | ||||
|  | ||||
|     // Fallback to default viewport | ||||
|     if (window->Viewport == NULL) | ||||
|         window->Viewport = main_viewport; | ||||
|  | ||||
|     // Update flags | ||||
|     window->ViewportOwned = (window == window->Viewport->Window); | ||||
|     if (window->ViewportOwned) | ||||
|         window->Viewport->Flags |= ImGuiViewportFlags_NoDecoration; | ||||
|  | ||||
|     // If the OS window has a title bar, hide our imgui title bar | ||||
|     if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration)) | ||||
|         window->Flags |= ImGuiWindowFlags_NoTitleBar; | ||||
|  | ||||
|     window->ViewportId = window->Viewport->ID; | ||||
| } | ||||
|  | ||||
| struct ImGuiResizeGripDef | ||||
| { | ||||
|     ImVec2  CornerPos; | ||||
| @@ -7619,6 +7460,165 @@ static void ImGui::UpdateViewports() | ||||
|     IM_ASSERT(g.MouseViewport != NULL); | ||||
| } | ||||
|  | ||||
| ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& pos, const ImVec2& size, ImGuiViewportFlags flags) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     IM_ASSERT(id != 0); | ||||
|  | ||||
|     ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id); | ||||
|     if (viewport) | ||||
|     { | ||||
|         viewport->Pos = pos; | ||||
|         viewport->Size = size; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // New viewport | ||||
|         viewport = IM_NEW(ImGuiViewportP)(); | ||||
|         viewport->ID = id; | ||||
|         viewport->Idx = g.Viewports.Size; | ||||
|         viewport->Pos = viewport->LastPos = pos; | ||||
|         viewport->Size = size; | ||||
|         viewport->PlatformMonitor = FindPlatformMonitorForRect(viewport->GetRect()); | ||||
|         g.Viewports.push_back(viewport); | ||||
|  | ||||
|         if (window && (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)) | ||||
|             flags |= ImGuiViewportFlags_NoFocusOnAppearing; | ||||
|  | ||||
|         // We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport. | ||||
|         // We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame | ||||
|         g.DrawListSharedData.ClipRectFullscreen.z = ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x); | ||||
|         g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y); | ||||
|  | ||||
|         // Request an initial DpiScale before the OS platform window creation | ||||
|         // This is so we can select an appropriate font size on the first frame of our window lifetime | ||||
|         if (g.PlatformIO.Platform_GetWindowDpiScale) | ||||
|             viewport->DpiScale = g.PlatformIO.Platform_GetWindowDpiScale(viewport); | ||||
|     } | ||||
|  | ||||
|     viewport->Window = window; | ||||
|     viewport->Flags = flags; | ||||
|     viewport->LastFrameActive = g.FrameCount; | ||||
|     IM_ASSERT(window == NULL || viewport->ID == window->ID); | ||||
|  | ||||
|     if (window != NULL) | ||||
|         window->ViewportOwned = true; | ||||
|  | ||||
|     return viewport; | ||||
| } | ||||
|  | ||||
| // FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten. | ||||
| static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindowFlags flags = window->Flags; | ||||
|     window->ViewportAllowPlatformMonitorExtend = -1; | ||||
|  | ||||
|     // Restore main viewport if multi-viewport is not supported by the back-end | ||||
|     ImGuiViewportP* main_viewport = g.Viewports[0]; | ||||
|     if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) | ||||
|     { | ||||
|         window->Viewport = main_viewport; | ||||
|         window->ViewportId = main_viewport->ID; | ||||
|         window->ViewportOwned = false; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // Merge into host viewports (after moving, resizing) | ||||
|     if (window->ViewportOwned && window->ViewportTryMerge && g.ActiveId == 0) | ||||
|     { | ||||
|         UpdateTryMergeWindowIntoHostViewport(window, g.Viewports[0]); | ||||
|         window->ViewportTryMerge = false; | ||||
|     } | ||||
|     window->ViewportOwned = false; | ||||
|  | ||||
|     // Appearing popups reset their viewport so they can inherit again | ||||
|     if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing) | ||||
|     { | ||||
|         window->Viewport = NULL; | ||||
|         window->ViewportId = 0; | ||||
|     } | ||||
|  | ||||
|     if (!g.NextWindowData.ViewportCond) | ||||
|     { | ||||
|         // By default inherit from parent window | ||||
|         if (window->Viewport == NULL && window->ParentWindow) | ||||
|             window->Viewport = window->ParentWindow->Viewport; | ||||
|  | ||||
|         // Attempt to restore saved viewport id (= window that hasn't been activated yet), try to restore the viewport based on saved 'window->ViewportPos' restored from .ini file | ||||
|         if (window->Viewport == NULL && window->ViewportId != 0) | ||||
|         { | ||||
|             window->Viewport = FindViewportByID(window->ViewportId); | ||||
|             if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX) | ||||
|                 window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_NoDecoration); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (g.NextWindowData.ViewportCond) | ||||
|     { | ||||
|         // Code explicitly request a viewport | ||||
|         window->Viewport = FindViewportByID(g.NextWindowData.ViewportId); | ||||
|         window->ViewportId = g.NextWindowData.ViewportId; // Store ID even if Viewport isn't resolved yet. | ||||
|     } | ||||
|     else if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu)) | ||||
|     { | ||||
|         // Always inherit viewport from parent window | ||||
|         window->Viewport = window->ParentWindow->Viewport; | ||||
|     } | ||||
|     else if (flags & ImGuiWindowFlags_Tooltip) | ||||
|     { | ||||
|         window->Viewport = g.MouseViewport; | ||||
|     } | ||||
|     else if (g.MovingWindow && g.MovingWindow->RootWindow == window && IsMousePosValid()) | ||||
|     { | ||||
|         // Transition to our own viewport when leaving our host boundaries + set the NoInputs flag (which will be cleared in UpdateMovingWindow when releasing the mouse) | ||||
|         // If we are already in our own viewport, if need to set the NoInputs flag. | ||||
|         // If we have no viewport (which happens when detaching a docked node) immediately create one. | ||||
|         // We test for 'window->Viewport->Window == window' instead of 'window->ViewportOwned' because ViewportOwned is not valid during this function. | ||||
|         bool has_viewport = (window->Viewport != NULL); | ||||
|         bool own_viewport = has_viewport && (window->Viewport->Window == window); | ||||
|         bool leave_host_viewport = has_viewport && !own_viewport && !window->Viewport->GetRect().Contains(window->Rect()); | ||||
|         bool move_from_own_viewport = has_viewport && own_viewport && !(window->Viewport->Flags & ImGuiViewportFlags_NoInputs); | ||||
|         if (!has_viewport || leave_host_viewport || move_from_own_viewport) | ||||
|             window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs); | ||||
|     } | ||||
|     else if (GetWindowAlwaysWantOwnViewport(window)) | ||||
|     { | ||||
|         window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration); | ||||
|     } | ||||
|  | ||||
|     // Mark window as allowed to protrude outside of its viewport and into the current monitor | ||||
|     // We need to take account of the possibility that mouse may become invalid. | ||||
|     const bool use_mouse_ref = (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow); | ||||
|     if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) | ||||
|     { | ||||
|         ImVec2 mouse_ref = (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.CurrentPopupStack.back().OpenMousePos; | ||||
|         bool mouse_valid = IsMousePosValid(&mouse_ref); | ||||
|         if ((window->Appearing || (flags & ImGuiWindowFlags_Tooltip)) && (!use_mouse_ref || mouse_valid)) | ||||
|             window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos()); | ||||
|         else | ||||
|             window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor; | ||||
|     } | ||||
|     if (window->ViewportTrySplit && window->ViewportAllowPlatformMonitorExtend < 0) | ||||
|         window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor; | ||||
|     window->ViewportTrySplit = false; | ||||
|  | ||||
|     // Fallback to default viewport | ||||
|     if (window->Viewport == NULL) | ||||
|         window->Viewport = main_viewport; | ||||
|  | ||||
|     // Update flags | ||||
|     window->ViewportOwned = (window == window->Viewport->Window); | ||||
|     if (window->ViewportOwned) | ||||
|         window->Viewport->Flags |= ImGuiViewportFlags_NoDecoration; | ||||
|  | ||||
|     // If the OS window has a title bar, hide our imgui title bar | ||||
|     if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration)) | ||||
|         window->Flags |= ImGuiWindowFlags_NoTitleBar; | ||||
|  | ||||
|     window->ViewportId = window->Viewport->ID; | ||||
| } | ||||
|  | ||||
| void ImGui::UpdatePlatformWindows() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user