From 84890a30743107d4b22e7796b5c038fa62294b87 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 27 Aug 2021 12:31:11 +0200 Subject: [PATCH] Nav: simplify wrap requests code (may soon be useable for tabbing) --- imgui.cpp | 25 ++++++++++++------------- imgui_internal.h | 8 ++------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ba7c9c57..367fc857 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8437,7 +8437,7 @@ void ImGui::EndPopup() IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls IM_ASSERT(g.BeginPopupStack.Size > 0); - // Make all menus and popups wrap around for now, may need to expose that policy. + // Make all menus and popups wrap around for now, may need to expose that policy (e.g. focus scope could include wrap/loop policy flags used by new move requests) if (g.NavWindow == window) NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY); @@ -8952,14 +8952,14 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im g.NavWindow->NavRectRel[g.NavLayer] = bb_rel; } -void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags) +// Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire +// popup is assembled and in case of appended popups it is not clear which EndPopup() call is final. +void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wrap_flags) { ImGuiContext& g = *GImGui; - - // Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire - // popup is assembled and in case of appended popups it is not clear which EndPopup() call is final. - g.NavWrapRequestWindow = window; - g.NavWrapRequestFlags = move_flags; + IM_ASSERT(wrap_flags != 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY + if (g.NavWindow == window && g.NavMoveRequest && g.NavLayer == ImGuiNavLayer_Main) + g.NavMoveRequestFlags |= wrap_flags; } // FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0). @@ -9105,8 +9105,6 @@ static void ImGui::NavUpdate() ImGuiIO& io = g.IO; io.WantSetMousePos = false; - g.NavWrapRequestWindow = NULL; - g.NavWrapRequestFlags = ImGuiNavMoveFlags_None; #if 0 if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); #endif @@ -9546,11 +9544,12 @@ static void ImGui::NavEndFrame() NavUpdateWindowingOverlay(); // Perform wrap-around in menus - ImGuiWindow* window = g.NavWrapRequestWindow; - ImGuiNavMoveFlags move_flags = g.NavWrapRequestFlags; - if (window != NULL && g.NavWindow == window && NavMoveRequestButNoResultYet() && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == ImGuiNavLayer_Main) + // FIXME-NAV: Wrap support could be moved to the scoring function and than WrapX would function without an extra frame. This is essentially same as tabbing! + ImGuiWindow* window = g.NavWindow; + const ImGuiNavMoveFlags move_flags = g.NavMoveRequestFlags; + const ImGuiNavMoveFlags wanted_flags = ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY; + if (window && NavMoveRequestButNoResultYet() && (g.NavMoveRequestFlags & wanted_flags) && g.NavMoveRequestForward == ImGuiNavForward_None) { - IM_ASSERT(move_flags != 0); // No points calling this with no wrapping ImRect bb_rel = window->NavRectRel[0]; ImGuiDir clip_dir = g.NavMoveDir; diff --git a/imgui_internal.h b/imgui_internal.h index 017e8de3..a1f67be9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -938,9 +938,9 @@ enum ImGuiNavMoveFlags_ ImGuiNavMoveFlags_LoopX = 1 << 0, // On failed request, restart from opposite side ImGuiNavMoveFlags_LoopY = 1 << 1, ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) - ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness + ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) - ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. + ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible (used by PageUp/PageDown) ImGuiNavMoveFlags_ScrollToEdge = 1 << 6 }; @@ -1534,8 +1534,6 @@ struct ImGuiContext ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavItemData NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) - ImGuiWindow* NavWrapRequestWindow; // Window which requested trying nav wrap-around. - ImGuiNavMoveFlags NavWrapRequestFlags; // Wrap-around operation flags. // Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize) ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most! @@ -1734,8 +1732,6 @@ struct ImGuiContext NavMoveRequestForward = ImGuiNavForward_None; NavMoveRequestKeyMods = ImGuiKeyModFlags_None; NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; - NavWrapRequestWindow = NULL; - NavWrapRequestFlags = ImGuiNavMoveFlags_None; NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;