Nav: split NavMoveRequest into NavMoveSubmitted + NavMoveScoringItems to allow operation to defer a move request and provide result immediately + fix regular scoring needlesly running during init + some renaming.
constImRect&curr=g.NavScoringRect;// Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
constImRectcurr=g.NavScoringRect;// Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
g.NavScoringCount++;
// When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
// Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
// (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index),
// this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis.
if(((g.NavMoveDir==ImGuiDir_Up||g.NavMoveDir==ImGuiDir_Down)?dby:dbx)<0.0f)// moving bj to the right/down decreases distance
if(((move_dir==ImGuiDir_Up||move_dir==ImGuiDir_Down)?dby:dbx)<0.0f)// moving bj to the right/down decreases distance
//if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item
ImGuiWindow*window=g.NavWindow;
constfloatscroll_speed=IM_ROUND(window->CalcFontSize()*100*io.DeltaTime);// We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
// Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
// (preserve most state, which were already set by the NavMoveRequestForward() function)
// If we initiate a movement request and have no current NavId, we initiate a InitDefaultRequest that will be used as a fallback if the direction fails to find a match
// FIXME: Would be nice to call a single function to initiate a new request
if(g.NavMoveDir!=ImGuiDir_None)
{
IM_ASSERT(window!=NULL);
g.NavMoveRequest=true;
g.NavMoveRequestKeyMods=io.KeyMods;
g.NavMoveDirLast=g.NavMoveDir;
g.NavMoveSubmitted=g.NavMoveScoringItems=true;
g.NavMoveKeyMods=io.KeyMods;
g.NavMoveDirForDebug=g.NavMoveDir;
g.NavMoveResultLocal.Clear();
g.NavMoveResultLocalVisibleSet.Clear();
g.NavMoveResultLocalVisible.Clear();
g.NavMoveResultOther.Clear();
}
// Moving with no reference triggers a init request
if(g.NavMoveRequest&&g.NavId==0)
if(g.NavMoveSubmitted&&g.NavId==0)
{
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n",g.NavWindow->Name,g.NavLayer);
// When using gamepad, we project the reference nav bounding box into window visible area.
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
// (can't focus a visible object like we can with the mouse).
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
IM_ASSERT(!g.NavScoringRect.IsInverted());// Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
IM_ASSERT(!scoring_rect.IsInverted());// Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
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 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 (used by PageUp/PageDown)
ImGuiNavMoveFlags_AlsoScoreVisibleSet=1<<5,// Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown)
ImGuiNavMoveFlags_ScrollToEdge=1<<6,
ImGuiNavMoveFlags_Forwarded=1<<7
ImGuiNavMoveFlags_Forwarded=1<<7,
ImGuiNavMoveFlags_DebugNoResult=1<<8
};
enumImGuiNavLayer
@ -1511,27 +1512,31 @@ struct ImGuiContext
ImGuiKeyModFlagsNavJustMovedToKeyMods;
ImGuiIDNavNextActivateId;// Set by ActivateItem(), queued until next frame.
ImGuiInputSourceNavInputSource;// Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
ImRectNavScoringRect;// Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
intNavScoringCount;// Metrics for debugging
ImGuiNavLayerNavLayer;// Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
intNavIdTabCounter;// == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
boolNavIdIsAlive;// Nav widget has been seen this frame ~~ NavRectRel is valid
boolNavMousePosDirty;// When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
boolNavDisableHighlight;// When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
boolNavDisableMouseHover;// When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
// Navigation: Init & Move Requests
boolNavAnyRequest;// ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
boolNavInitRequest;// Init request for appearing window to select first item
boolNavInitRequestFromMove;
ImGuiIDNavInitResultId;// Init request result (first item of the window, or one for which SetItemDefaultFocus() was called)
ImRectNavInitResultRectRel;// Init request result rectangle (relative to parent window)
boolNavMoveRequest;// Move request for this frame
boolNavMoveRequestForwardToNextFrame;
ImGuiNavMoveFlagsNavMoveRequestFlags;
ImGuiKeyModFlagsNavMoveRequestKeyMods;
ImGuiDirNavMoveDir,NavMoveDirLast;// Direction of the move request (left/right/up/down), direction of the previous move request
boolNavMoveSubmitted;// Move request submitted, will process result on next NewFrame()
boolNavMoveScoringItems;// Move request submitted, still scoring incoming items
boolNavMoveForwardToNextFrame;
ImGuiNavMoveFlagsNavMoveFlags;
ImGuiKeyModFlagsNavMoveKeyMods;
ImGuiDirNavMoveDir;// Direction of the move request (left/right/up/down)
ImGuiDirNavMoveDirForDebug;
ImGuiDirNavMoveClipDir;// FIXME-NAV: Describe the purpose of this better. Might want to rename?
ImRectNavScoringRect;// Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
intNavScoringCount;// Metrics for debugging
ImGuiNavItemDataNavMoveResultLocal;// Best move request candidate within NavWindow
ImGuiNavItemDataNavMoveResultLocalVisibleSet;// Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavItemDataNavMoveResultLocalVisible;// Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavItemDataNavMoveResultOther;// Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering)