mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +00:00 
			
		
		
		
	Merge branch 'master' into docking
# Conflicts: # docs/CHANGELOG.txt # imgui.cpp
This commit is contained in:
		
							
								
								
									
										273
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										273
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -855,6 +855,8 @@ CODE | ||||
|     main font. Then you can refer to icons within your strings. | ||||
|     You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment. | ||||
|     (Read the 'misc/fonts/README.txt' file for more details about icons font loading.) | ||||
|     With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas, | ||||
|     and copying your own graphics data into it. See misc/fonts/README.txt about using the AddCustomRectFontGlyph API. | ||||
|  | ||||
|  Q: How can I load multiple fonts? | ||||
|  A: Use the font atlas to pack them into a single texture: | ||||
| @@ -2282,20 +2284,64 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // [SECTION] ImGuiListClipper | ||||
| // This is currently not as flexible/powerful as it should be, needs some rework (see TODO) | ||||
| // This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed | ||||
| // the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO) | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| // Helper to calculate coarse clipping of large list of evenly sized items. | ||||
| // NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. | ||||
| // NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX | ||||
| void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|     if (g.LogEnabled) | ||||
|     { | ||||
|         // If logging is active, do not perform any clipping | ||||
|         *out_items_display_start = 0; | ||||
|         *out_items_display_end = items_count; | ||||
|         return; | ||||
|     } | ||||
|     if (window->SkipItems) | ||||
|     { | ||||
|         *out_items_display_start = *out_items_display_end = 0; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect | ||||
|     ImRect unclipped_rect = window->ClipRect; | ||||
|     if (g.NavMoveRequest) | ||||
|         unclipped_rect.Add(g.NavScoringRectScreen); | ||||
|  | ||||
|     const ImVec2 pos = window->DC.CursorPos; | ||||
|     int start = (int)((unclipped_rect.Min.y - pos.y) / items_height); | ||||
|     int end = (int)((unclipped_rect.Max.y - pos.y) / items_height); | ||||
|  | ||||
|     // When performing a navigation request, ensure we have one item extra in the direction we are moving to | ||||
|     if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up) | ||||
|         start--; | ||||
|     if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down) | ||||
|         end++; | ||||
|  | ||||
|     start = ImClamp(start, 0, items_count); | ||||
|     end = ImClamp(end + 1, start, items_count); | ||||
|     *out_items_display_start = start; | ||||
|     *out_items_display_end = end; | ||||
| } | ||||
|  | ||||
| static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) | ||||
| { | ||||
|     // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor. | ||||
|     // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. | ||||
|     // The clipper should probably have a 4th step to display the last item in a regular manner. | ||||
|     ImGui::SetCursorPosY(pos_y); | ||||
|     ImGuiWindow* window = ImGui::GetCurrentWindow(); | ||||
|     window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;      // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. | ||||
|     window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y);    // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|     window->DC.CursorPos.y = pos_y; | ||||
|     window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y); | ||||
|     window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;  // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. | ||||
|     window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y);      // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. | ||||
|     if (ImGuiColumns* columns = window->DC.CurrentColumns) | ||||
|         columns->LineMinY = window->DC.CursorPos.y;                             // Setting this so that cell Y position are set properly | ||||
|         columns->LineMinY = window->DC.CursorPos.y;                         // Setting this so that cell Y position are set properly | ||||
| } | ||||
|  | ||||
| // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 | ||||
| @@ -2303,7 +2349,10 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) | ||||
| // FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style. | ||||
| void ImGuiListClipper::Begin(int count, float items_height) | ||||
| { | ||||
|     StartPosY = ImGui::GetCursorPosY(); | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|  | ||||
|     StartPosY = window->DC.CursorPos.y; | ||||
|     ItemsHeight = items_height; | ||||
|     ItemsCount = count; | ||||
|     StepNo = 0; | ||||
| @@ -2330,7 +2379,10 @@ void ImGuiListClipper::End() | ||||
|  | ||||
| bool ImGuiListClipper::Step() | ||||
| { | ||||
|     if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems) | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|  | ||||
|     if (ItemsCount == 0 || window->SkipItems) | ||||
|     { | ||||
|         ItemsCount = -1; | ||||
|         return false; | ||||
| @@ -2339,16 +2391,16 @@ bool ImGuiListClipper::Step() | ||||
|     { | ||||
|         DisplayStart = 0; | ||||
|         DisplayEnd = 1; | ||||
|         StartPosY = ImGui::GetCursorPosY(); | ||||
|         StartPosY = window->DC.CursorPos.y; | ||||
|         StepNo = 1; | ||||
|         return true; | ||||
|     } | ||||
|     if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element. | ||||
|     { | ||||
|         if (ItemsCount == 1) { ItemsCount = -1; return false; } | ||||
|         float items_height = ImGui::GetCursorPosY() - StartPosY; | ||||
|         float items_height = window->DC.CursorPos.y - StartPosY; | ||||
|         IM_ASSERT(items_height > 0.0f);   // If this triggers, it means Item 0 hasn't moved the cursor vertically | ||||
|         Begin(ItemsCount-1, items_height); | ||||
|         Begin(ItemsCount - 1, items_height); | ||||
|         DisplayStart++; | ||||
|         DisplayEnd++; | ||||
|         StepNo = 3; | ||||
| @@ -3414,7 +3466,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame() | ||||
|                 if (!g.HoveredRootWindow->TitleBarRect().Contains(g.IO.MouseClickedPos[0])) | ||||
|                     g.MovingWindow = NULL; | ||||
|         } | ||||
|         else if (g.NavWindow != NULL && GetFrontMostPopupModal() == NULL) | ||||
|         else if (g.NavWindow != NULL && GetTopMostPopupModal() == NULL) | ||||
|         { | ||||
|             // Clicking on void disable focus | ||||
|             FocusWindow(NULL); | ||||
| @@ -3426,9 +3478,9 @@ void ImGui::UpdateMouseMovingWindowEndFrame() | ||||
|     // (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger) | ||||
|     if (g.IO.MouseClicked[1]) | ||||
|     { | ||||
|         // Find the top-most window between HoveredWindow and the front most Modal Window. | ||||
|         // Find the top-most window between HoveredWindow and the top-most Modal Window. | ||||
|         // This is where we can trim the popup stack. | ||||
|         ImGuiWindow* modal = GetFrontMostPopupModal(); | ||||
|         ImGuiWindow* modal = GetTopMostPopupModal(); | ||||
|         bool hovered_window_above_modal = false; | ||||
|         if (modal == NULL) | ||||
|             hovered_window_above_modal = true; | ||||
| @@ -3535,12 +3587,12 @@ void ImGui::UpdateMouseWheel() | ||||
|         return; | ||||
|     if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f) | ||||
|         return; | ||||
|     ImGuiWindow* window = g.HoveredWindow; | ||||
|  | ||||
|     // Zoom / Scale window | ||||
|     // FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned. | ||||
|     if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling && !window->Collapsed) | ||||
|     if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling && !g.HoveredWindow->Collapsed) | ||||
|     { | ||||
|         ImGuiWindow* window = g.HoveredWindow; | ||||
|         const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); | ||||
|         const float scale = new_font_scale / window->FontWindowScale; | ||||
|         window->FontWindowScale = new_font_scale; | ||||
| @@ -3555,31 +3607,36 @@ void ImGui::UpdateMouseWheel() | ||||
|     } | ||||
|  | ||||
|     // Mouse wheel scrolling | ||||
|     // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). | ||||
|     while ((window->Flags & ImGuiWindowFlags_ChildWindow) && (window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs) && window->ParentWindow) | ||||
|         window = window->ParentWindow; | ||||
|     const bool scroll_allowed = !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs); | ||||
|     if (scroll_allowed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f) && !g.IO.KeyCtrl) | ||||
|     // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent | ||||
|     // FIXME: Lock scrolling window while not moving (see #2604) | ||||
|  | ||||
|     // Vertical Mouse Wheel scrolling | ||||
|     const float wheel_y = (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; | ||||
|     if (wheel_y != 0.0f && !g.IO.KeyCtrl) | ||||
|     { | ||||
|         ImVec2 max_step = window->InnerRect.GetSize() * 0.67f; | ||||
|  | ||||
|         // Vertical Mouse Wheel Scrolling (hold Shift to scroll horizontally) | ||||
|         if (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) | ||||
|         ImGuiWindow* window = g.HoveredWindow; | ||||
|         while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) | ||||
|             window = window->ParentWindow; | ||||
|         if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) | ||||
|         { | ||||
|             float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step.y)); | ||||
|             SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * scroll_step); | ||||
|         } | ||||
|         else if (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) | ||||
|         { | ||||
|             float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step.x)); | ||||
|             SetWindowScrollX(window, window->Scroll.x - g.IO.MouseWheel * scroll_step); | ||||
|             float max_step = window->InnerRect.GetHeight() * 0.67f; | ||||
|             float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step)); | ||||
|             SetWindowScrollY(window, window->Scroll.y - wheel_y * scroll_step); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         // Horizontal Mouse Wheel Scrolling (for hardware that supports it) | ||||
|         if (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) | ||||
|     // Horizontal Mouse Wheel scrolling, or Vertical Mouse Wheel w/ Shift held | ||||
|     const float wheel_x = (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheelH : (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; | ||||
|     if (wheel_x != 0.0f && !g.IO.KeyCtrl) | ||||
|     { | ||||
|         ImGuiWindow* window = g.HoveredWindow; | ||||
|         while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) | ||||
|             window = window->ParentWindow; | ||||
|         if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) | ||||
|         { | ||||
|             float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step.x)); | ||||
|             SetWindowScrollX(window, window->Scroll.x - g.IO.MouseWheelH * scroll_step); | ||||
|             float max_step = window->InnerRect.GetWidth() * 0.67f; | ||||
|             float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step)); | ||||
|             SetWindowScrollX(window, window->Scroll.x - wheel_x * scroll_step); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -3597,7 +3654,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() | ||||
|     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(); | ||||
|     ImGuiWindow* modal_window = GetTopMostPopupModal(); | ||||
|     if (modal_window) | ||||
|         if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) | ||||
|             g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
| @@ -3838,7 +3895,7 @@ void ImGui::NewFrame() | ||||
|     UpdateMouseMovingWindowNewFrame(); | ||||
|  | ||||
|     // Background darkening/whitening | ||||
|     if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) | ||||
|     if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) | ||||
|         g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); | ||||
|     else | ||||
|         g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); | ||||
| @@ -4179,7 +4236,7 @@ static void ImGui::EndFrameDrawDimmedBackgrounds() | ||||
|     ImGuiContext& g = *GImGui; | ||||
|  | ||||
|     // Draw modal whitening background on _other_ viewports than the one the modal is one | ||||
|     ImGuiWindow* modal_window = GetFrontMostPopupModal(); | ||||
|     ImGuiWindow* modal_window = GetTopMostPopupModal(); | ||||
|     const bool dim_bg_for_modal = (modal_window != NULL); | ||||
|     const bool dim_bg_for_window_list = (g.NavWindowingTargetAnim != NULL); | ||||
|     if (dim_bg_for_modal || dim_bg_for_window_list) | ||||
| @@ -4345,18 +4402,18 @@ void ImGui::Render() | ||||
|             AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport)); | ||||
|     } | ||||
|  | ||||
|     ImGuiWindow* windows_to_render_front_most[2]; | ||||
|     windows_to_render_front_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; | ||||
|     windows_to_render_front_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL; | ||||
|     ImGuiWindow* windows_to_render_top_most[2]; | ||||
|     windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; | ||||
|     windows_to_render_top_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL; | ||||
|     for (int n = 0; n != g.Windows.Size; n++) | ||||
|     { | ||||
|         ImGuiWindow* window = g.Windows[n]; | ||||
|         if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_front_most[0] && window != windows_to_render_front_most[1]) | ||||
|         if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1]) | ||||
|             AddRootWindowToDrawData(window); | ||||
|     } | ||||
|     for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_front_most); n++) | ||||
|         if (windows_to_render_front_most[n] && IsWindowActiveAndVisible(windows_to_render_front_most[n])) // NavWindowingTarget is always temporarily displayed as the front-most window | ||||
|             AddRootWindowToDrawData(windows_to_render_front_most[n]); | ||||
|     for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++) | ||||
|         if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the tp-most window | ||||
|             AddRootWindowToDrawData(windows_to_render_top_most[n]); | ||||
|  | ||||
|     // Draw software mouse cursor if requested | ||||
|     if (g.IO.MouseDrawCursor) | ||||
| @@ -4406,47 +4463,6 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex | ||||
|     return text_size; | ||||
| } | ||||
|  | ||||
| // Helper to calculate coarse clipping of large list of evenly sized items. | ||||
| // NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern. | ||||
| // NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX | ||||
| void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|     if (g.LogEnabled) | ||||
|     { | ||||
|         // If logging is active, do not perform any clipping | ||||
|         *out_items_display_start = 0; | ||||
|         *out_items_display_end = items_count; | ||||
|         return; | ||||
|     } | ||||
|     if (window->SkipItems) | ||||
|     { | ||||
|         *out_items_display_start = *out_items_display_end = 0; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect | ||||
|     ImRect unclipped_rect = window->ClipRect; | ||||
|     if (g.NavMoveRequest) | ||||
|         unclipped_rect.Add(g.NavScoringRectScreen); | ||||
|  | ||||
|     const ImVec2 pos = window->DC.CursorPos; | ||||
|     int start = (int)((unclipped_rect.Min.y - pos.y) / items_height); | ||||
|     int end = (int)((unclipped_rect.Max.y - pos.y) / items_height); | ||||
|  | ||||
|     // When performing a navigation request, ensure we have one item extra in the direction we are moving to | ||||
|     if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up) | ||||
|         start--; | ||||
|     if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down) | ||||
|         end++; | ||||
|  | ||||
|     start = ImClamp(start, 0, items_count); | ||||
|     end = ImClamp(end + 1, start, items_count); | ||||
|     *out_items_display_start = start; | ||||
|     *out_items_display_end = end; | ||||
| } | ||||
|  | ||||
| // Find window given position, search front-to-back | ||||
| // FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programatically | ||||
| // with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is | ||||
| @@ -5172,7 +5188,12 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s | ||||
|     if (window->ScrollTarget.x < FLT_MAX) | ||||
|     { | ||||
|         float cr_x = window->ScrollTargetCenterRatio.x; | ||||
|         scroll.x = window->ScrollTarget.x - cr_x * window->InnerRect.GetWidth(); | ||||
|         float target_x = window->ScrollTarget.x; | ||||
|         if (snap_on_edges && cr_x <= 0.0f && target_x <= window->WindowPadding.x) | ||||
|             target_x = 0.0f; | ||||
|         else if (snap_on_edges && cr_x >= 1.0f && target_x >= window->ContentSize.x + window->WindowPadding.x + GImGui->Style.ItemSpacing.x) | ||||
|             target_x = window->ContentSize.x + window->WindowPadding.x * 2.0f; | ||||
|         scroll.x = target_x - cr_x * window->InnerRect.GetWidth(); | ||||
|     } | ||||
|     if (window->ScrollTarget.y < FLT_MAX) | ||||
|     { | ||||
| @@ -6167,7 +6188,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|         PushClipRect(host_rect.Min, host_rect.Max, false); | ||||
|  | ||||
|         // Draw modal or window list full viewport dimming background (for other viewports we'll render them in EndFrame) | ||||
|         const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0; | ||||
|         const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0; | ||||
|         const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && ((window == g.NavWindowingTargetAnim->RootWindow) || (g.NavWindowingList && (window == g.NavWindowingList) && g.NavWindowingList->Viewport != g.NavWindowingTargetAnim->Viewport)); | ||||
|         if (dim_bg_for_modal || dim_bg_for_window_list) | ||||
|         { | ||||
| @@ -6400,9 +6421,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) | ||||
|             if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y) | ||||
|                 window->HiddenFramesCanSkipItems = 1; | ||||
|  | ||||
|         // Completely hide along with parent or if parent is collapsed | ||||
|         if (parent_window && (parent_window->Collapsed || parent_window->Hidden)) | ||||
|         // Hide along with parent or if parent is collapsed | ||||
|         if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0)) | ||||
|             window->HiddenFramesCanSkipItems = 1; | ||||
|         if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0)) | ||||
|             window->HiddenFramesCannotSkipItems = 1; | ||||
|     } | ||||
|  | ||||
|     // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point) | ||||
| @@ -6480,7 +6503,7 @@ void ImGui::BringWindowToFocusFront(ImGuiWindow* window) | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     if (g.WindowsFocusOrder.back() == window) | ||||
|         return; | ||||
|     for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the front most window | ||||
|     for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the top-most window | ||||
|         if (g.WindowsFocusOrder[i] == window) | ||||
|         { | ||||
|             memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*)); | ||||
| @@ -6495,7 +6518,7 @@ void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) | ||||
|     ImGuiWindow* current_front_window = g.Windows.back(); | ||||
|     if (current_front_window == window || current_front_window->RootWindow == window) | ||||
|         return; | ||||
|     for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window | ||||
|     for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window | ||||
|         if (g.Windows[i] == window) | ||||
|         { | ||||
|             memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*)); | ||||
| @@ -7502,6 +7525,15 @@ void ImGui::SetScrollY(float scroll_y) | ||||
|     window->ScrollTargetCenterRatio.y = 0.0f; | ||||
| } | ||||
|  | ||||
| void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) | ||||
| { | ||||
|     // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); | ||||
|     window->ScrollTarget.x = (float)(int)(local_x + window->Scroll.x); | ||||
|     window->ScrollTargetCenterRatio.x = center_x_ratio; | ||||
| } | ||||
|  | ||||
| void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) | ||||
| { | ||||
|     // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size | ||||
| @@ -7511,6 +7543,16 @@ void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) | ||||
|     window->ScrollTargetCenterRatio.y = center_y_ratio; | ||||
| } | ||||
|  | ||||
| // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. | ||||
| void ImGui::SetScrollHereX(float center_x_ratio) | ||||
| { | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|     float target_x = window->DC.LastItemRect.Min.x - window->Pos.x; // Left of last item, in window space | ||||
|     float last_item_width = window->DC.LastItemRect.GetWidth(); | ||||
|     target_x += (last_item_width * center_x_ratio) + (GImGui->Style.ItemSpacing.x * (center_x_ratio - 0.5f) * 2.0f); // Precisely aim before, in the middle or after the last item. | ||||
|     SetScrollFromPosX(target_x, center_x_ratio); | ||||
| } | ||||
|  | ||||
| // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. | ||||
| void ImGui::SetScrollHereY(float center_y_ratio) | ||||
| { | ||||
| @@ -7841,7 +7883,7 @@ bool ImGui::IsPopupOpen(const char* str_id) | ||||
|     return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id); | ||||
| } | ||||
|  | ||||
| ImGuiWindow* ImGui::GetFrontMostPopupModal() | ||||
| ImGuiWindow* ImGui::GetTopMostPopupModal() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) | ||||
| @@ -9118,7 +9160,7 @@ static void ImGui::NavUpdateWindowing() | ||||
|     ImGuiWindow* apply_focus_window = NULL; | ||||
|     bool apply_toggle_layer = false; | ||||
|  | ||||
|     ImGuiWindow* modal_window = GetFrontMostPopupModal(); | ||||
|     ImGuiWindow* modal_window = GetTopMostPopupModal(); | ||||
|     if (modal_window != NULL) | ||||
|     { | ||||
|         g.NavWindowingTarget = NULL; | ||||
| @@ -9160,7 +9202,7 @@ static void ImGui::NavUpdateWindowing() | ||||
|             g.NavWindowingHighlightAlpha = 1.0f; | ||||
|         } | ||||
|  | ||||
|         // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most) | ||||
|         // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered top-most) | ||||
|         if (!IsNavInputDown(ImGuiNavInput_Menu)) | ||||
|         { | ||||
|             g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore. | ||||
| @@ -14592,6 +14634,7 @@ void ImGui::ShowViewportThumbnails() | ||||
|     ImGui::Dummy(bb_full.GetSize() * SCALE); | ||||
| } | ||||
|  | ||||
| #ifndef IMGUI_DISABLE_METRICS_WINDOW | ||||
| void ImGui::ShowMetricsWindow(bool* p_open) | ||||
| { | ||||
|     if (!ImGui::Begin("Dear ImGui Metrics", p_open)) | ||||
| @@ -14600,10 +14643,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerRect, RT_InnerClipRect, RT_WorkRect, RT_Contents, RT_ContentsRegionRect, RT_Count }; | ||||
|     enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Contents, WRT_ContentsRegionRect, WRT_Count }; // Windows Rect Type | ||||
|     const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" }; | ||||
|  | ||||
|     static bool show_windows_begin_order = false; | ||||
|     static bool show_windows_rects = false; | ||||
|     static int  show_windows_rect_type = RT_WorkRect; | ||||
|     static int  show_windows_rect_type = WRT_WorkRect; | ||||
|     static bool show_drawcmd_clip_rects = true; | ||||
|  | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
| @@ -14616,15 +14661,15 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|  | ||||
|     struct Funcs | ||||
|     { | ||||
|         static ImRect GetRect(ImGuiWindow* window, int rect_type) | ||||
|         static ImRect GetWindowRect(ImGuiWindow* window, int rect_type) | ||||
|         { | ||||
|             if (rect_type == RT_OuterRect)                  { return window->Rect(); } | ||||
|             else if (rect_type == RT_OuterRectClipped)      { return window->OuterRectClipped; } | ||||
|             else if (rect_type == RT_InnerRect)             { return window->InnerRect; } | ||||
|             else if (rect_type == RT_InnerClipRect)         { return window->InnerClipRect; } | ||||
|             else if (rect_type == RT_WorkRect)              { return window->WorkRect; } | ||||
|             else if (rect_type == RT_Contents)              { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } | ||||
|             else if (rect_type == RT_ContentsRegionRect)    { return window->ContentsRegionRect; } | ||||
|             if (rect_type == WRT_OuterRect)                 { return window->Rect(); } | ||||
|             else if (rect_type == WRT_OuterRectClipped)     { return window->OuterRectClipped; } | ||||
|             else if (rect_type == WRT_InnerRect)            { return window->InnerRect; } | ||||
|             else if (rect_type == WRT_InnerClipRect)        { return window->InnerClipRect; } | ||||
|             else if (rect_type == WRT_WorkRect)             { return window->WorkRect; } | ||||
|             else if (rect_type == WRT_Contents)             { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } | ||||
|             else if (rect_type == WRT_ContentsRegionRect)   { return window->ContentsRegionRect; } | ||||
|             IM_ASSERT(0); | ||||
|             return ImRect(); | ||||
|         } | ||||
| @@ -14849,16 +14894,15 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|         ImGui::Checkbox("Show windows rectangles", &show_windows_rects); | ||||
|         ImGui::SameLine(); | ||||
|         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12); | ||||
|         const char* rects_names[RT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" }; | ||||
|         show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, rects_names, RT_Count); | ||||
|         show_windows_rects |= ImGui::Combo("##show_windows_rect_type", &show_windows_rect_type, wrt_rects_names, WRT_Count); | ||||
|         if (show_windows_rects && g.NavWindow) | ||||
|         { | ||||
|             ImGui::BulletText("'%s':", g.NavWindow->Name); | ||||
|             ImGui::Indent(); | ||||
|             for (int n = 0; n < RT_Count; n++) | ||||
|             for (int rect_n = 0; rect_n < WRT_Count; rect_n++) | ||||
|             { | ||||
|                 ImRect r = Funcs::GetRect(g.NavWindow, n); | ||||
|                 ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), rects_names[n]); | ||||
|                 ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n); | ||||
|                 ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); | ||||
|             } | ||||
|             ImGui::Unindent(); | ||||
|         } | ||||
| @@ -14876,7 +14920,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|             ImDrawList* draw_list = GetForegroundDrawList(window); | ||||
|             if (show_windows_rects) | ||||
|             { | ||||
|                 ImRect r = Funcs::GetRect(window, show_windows_rect_type); | ||||
|                 ImRect r = Funcs::GetWindowRect(window, show_windows_rect_type); | ||||
|                 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255)); | ||||
|             } | ||||
|             if (show_windows_begin_order && !(window->Flags & ImGuiWindowFlags_ChildWindow)) | ||||
| @@ -14891,6 +14935,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|     } | ||||
|     ImGui::End(); | ||||
| } | ||||
| #else | ||||
| void ImGui::ShowMetricsWindow(bool*) | ||||
| { | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void ImGui::ShowDockingDebug() | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 omar
					omar