mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 05:01:05 +01:00 
			
		
		
		
	Nav, TreeNode: Pressing Left with ImGuiTreeNodeFlags_NavLeftJumpsBackHere now goes through proper navigation logic: honor scrolling and selection. (#1079, #1131)
Added a stack for this purpose which other features might build on (e.g. #2920). However this is currently gated by many tests and not a performance concern, but making stack happen all the time may be undesirable.
This commit is contained in:
		| @@ -44,6 +44,8 @@ Breaking changes: | ||||
|  | ||||
| Other changes: | ||||
|  | ||||
| - Nav, TreeNode: Pressing Left with ImGuiTreeNodeFlags_NavLeftJumpsBackHere now goes | ||||
|   through proper navigation logic: honor scrolling and selection. (#1079, #1131) | ||||
| - Sliders: Fixed an integer overflow and div-by-zero in SliderInt() when | ||||
|   v_max=INT_MAX (#6675, #6679) [@jbarthelmes] | ||||
| - ImDrawList: Fixed OOB access in _CalcCircleAutoSegmentCount when passing excessively | ||||
|   | ||||
							
								
								
									
										14
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -3653,6 +3653,7 @@ void ImGui::Shutdown() | ||||
|     g.FontStack.clear(); | ||||
|     g.OpenPopupStack.clear(); | ||||
|     g.BeginPopupStack.clear(); | ||||
|     g.NavTreeNodeStack.clear(); | ||||
|  | ||||
|     g.Viewports.clear_delete(); | ||||
|  | ||||
| @@ -11191,6 +11192,19 @@ void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result) | ||||
|     NavUpdateAnyRequestFlag(); | ||||
| } | ||||
|  | ||||
| // Called by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere | ||||
| void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     g.NavMoveScoringItems = false; | ||||
|     g.LastItemData.ID = tree_node_data->ID; | ||||
|     g.LastItemData.InFlags = tree_node_data->InFlags; | ||||
|     g.LastItemData.NavRect = tree_node_data->NavRect; | ||||
|     NavApplyItemToResult(result); // Result this instead of implementing a NavApplyPastTreeNodeToResult() | ||||
|     NavClearPreferredPosForAxis(ImGuiAxis_Y); | ||||
|     NavUpdateAnyRequestFlag(); | ||||
| } | ||||
|  | ||||
| void ImGui::NavMoveRequestCancel() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|   | ||||
							
								
								
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							| @@ -26,7 +26,7 @@ | ||||
| // Library Version | ||||
| // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') | ||||
| #define IMGUI_VERSION       "1.89.9 WIP" | ||||
| #define IMGUI_VERSION_NUM   18981 | ||||
| #define IMGUI_VERSION_NUM   18982 | ||||
| #define IMGUI_HAS_TABLE | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -135,6 +135,7 @@ struct ImGuiLastItemData;           // Status storage for last submitted items | ||||
| struct ImGuiLocEntry;               // A localization entry. | ||||
| struct ImGuiMenuColumns;            // Simple column measurement, currently used for MenuItem() only | ||||
| struct ImGuiNavItemData;            // Result of a gamepad/keyboard directional navigation move query result | ||||
| struct ImGuiNavTreeNodeData;        // Temporary storage for last TreeNode() being a Left arrow landing candidate. | ||||
| struct ImGuiMetricsConfig;          // Storage for ShowMetricsWindow() and DebugNodeXXX() functions | ||||
| struct ImGuiNextWindowData;         // Storage for SetNextWindow** functions | ||||
| struct ImGuiNextItemData;           // Storage for SetNextItem** functions | ||||
| @@ -1201,6 +1202,16 @@ struct ImGuiLastItemData | ||||
|     ImGuiLastItemData()     { memset(this, 0, sizeof(*this)); } | ||||
| }; | ||||
|  | ||||
| // Store data emitted by TreeNode() for usage by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere. | ||||
| // This is the minimum amount of data that we need to perform the equivalent of NavApplyItemToResult() and which we can't infer in TreePop() | ||||
| // Only stored when the node is a potential candidate for landing on a Left arrow jump. | ||||
| struct ImGuiNavTreeNodeData | ||||
| { | ||||
|     ImGuiID                 ID; | ||||
|     ImGuiItemFlags          InFlags; | ||||
|     ImRect                  NavRect; | ||||
| }; | ||||
|  | ||||
| struct IMGUI_API ImGuiStackSizes | ||||
| { | ||||
|     short   SizeOfIDStack; | ||||
| @@ -1865,6 +1876,8 @@ struct ImGuiContext | ||||
|     ImVector<ImGuiGroupData>GroupStack;                         // Stack for BeginGroup()/EndGroup() - not inherited by Begin() | ||||
|     ImVector<ImGuiPopupData>OpenPopupStack;                     // Which popups are open (persistent) | ||||
|     ImVector<ImGuiPopupData>BeginPopupStack;                    // Which level of BeginPopup() we are in (reset every frame) | ||||
|     ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack;            // Stack for TreeNode() when a NavLeft requested is emitted. | ||||
|  | ||||
|     int                     BeginMenuCount; | ||||
|  | ||||
|     // Viewports | ||||
| @@ -2930,6 +2943,7 @@ namespace ImGui | ||||
|     IMGUI_API void          NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); | ||||
|     IMGUI_API void          NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); | ||||
|     IMGUI_API void          NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result); | ||||
|     IMGUI_API void          NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data); | ||||
|     IMGUI_API void          NavMoveRequestCancel(); | ||||
|     IMGUI_API void          NavMoveRequestApplyResult(); | ||||
|     IMGUI_API void          NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); | ||||
|   | ||||
| @@ -6155,18 +6155,29 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l | ||||
|     if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0) | ||||
|         interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f; | ||||
|  | ||||
|     // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. | ||||
|     // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). | ||||
|     // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. | ||||
|     const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; | ||||
|     // Compute open and multi-select states before ItemAdd() as it clear NextItem data. | ||||
|     bool is_open = TreeNodeUpdateNextOpen(id, flags); | ||||
|     if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) | ||||
|         window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); | ||||
|  | ||||
|     bool item_add = ItemAdd(interact_bb, id); | ||||
|     g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; | ||||
|     g.LastItemData.DisplayRect = frame_bb; | ||||
|  | ||||
|     // If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled: | ||||
|     // Store data for the current depth to allow returning to this node from any child item. | ||||
|     // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). | ||||
|     // It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default or move it to ImGuiStyle. | ||||
|     // Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase. | ||||
|     if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) | ||||
|         if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) | ||||
|         { | ||||
|             g.NavTreeNodeStack.resize(g.NavTreeNodeStack.Size + 1); | ||||
|             ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back(); | ||||
|             nav_tree_node_data->ID = id; | ||||
|             nav_tree_node_data->InFlags = g.LastItemData.InFlags; | ||||
|             nav_tree_node_data->NavRect = g.LastItemData.NavRect; | ||||
|             window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); | ||||
|         } | ||||
|  | ||||
|     const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; | ||||
|     if (!item_add) | ||||
|     { | ||||
|         if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) | ||||
| @@ -6336,12 +6347,14 @@ void ImGui::TreePop() | ||||
|     ImU32 tree_depth_mask = (1 << window->DC.TreeDepth); | ||||
|  | ||||
|     // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled) | ||||
|     if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) | ||||
|         if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask)) | ||||
|         { | ||||
|             SetNavID(window->IDStack.back(), g.NavLayer, 0, ImRect()); | ||||
|             NavMoveRequestCancel(); | ||||
|         } | ||||
|     if (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask) // Only set during request | ||||
|     { | ||||
|         ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back(); | ||||
|         IM_ASSERT(nav_tree_node_data->ID == window->IDStack.back()); | ||||
|         if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) | ||||
|             NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, nav_tree_node_data); | ||||
|         g.NavTreeNodeStack.pop_back(); | ||||
|     } | ||||
|     window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1; | ||||
|  | ||||
|     IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user