constImRect&curr=g.NavScoringRectScreen;// 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
cand.ClipWithFull(window->ClipRect);// This allows the scored item to not overlap other candidates in the parent window
}
// We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items)
// For example, this ensure that items in one column are not reached when moving vertically from items in another column.
floatdby=NavScoreItemDistInterval(ImLerp(cand.Min.y,cand.Max.y,0.2f),ImLerp(cand.Min.y,cand.Max.y,0.8f),ImLerp(curr.Min.y,curr.Max.y,0.2f),ImLerp(curr.Min.y,curr.Max.y,0.8f));// Scale down on Y to keep using box-distance for vertically touching items
if(dby!=0.0f&&dbx!=0.0f)
dbx=(dbx/1000.0f)+((dbx>0.0f)?+1.0f:-1.0f);
floatdist_box=ImFabs(dbx)+ImFabs(dby);
// Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter)
floatdist_center=ImFabs(dcx)+ImFabs(dcy);// L1 metric (need this for our connectedness guarantee)
// Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance
ImGuiDirquadrant;
floatdax=0.0f,day=0.0f,dist_axial=0.0f;
if(dbx!=0.0f||dby!=0.0f)
{
// For non-overlapping boxes, use distance between boxes
dax=dbx;
day=dby;
dist_axial=dist_box;
quadrant=ImGetDirQuadrantFromDelta(dbx,dby);
}
elseif(dcx!=0.0f||dcy!=0.0f)
{
// For overlapping boxes with different centers, use distance between centers
dax=dcx;
day=dcy;
dist_axial=dist_center;
quadrant=ImGetDirQuadrantFromDelta(dcx,dcy);
}
else
{
// Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter)
// Is it in the quadrant we're interesting in moving to?
boolnew_best=false;
if(quadrant==g.NavMoveDir)
{
// Does it beat the current best candidate?
if(dist_box<result->DistBox)
{
result->DistBox=dist_box;
result->DistCenter=dist_center;
returntrue;
}
if(dist_box==result->DistBox)
{
// Try using distance between center points to break ties
if(dist_center<result->DistCenter)
{
result->DistCenter=dist_center;
new_best=true;
}
elseif(dist_center==result->DistCenter)
{
// 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
new_best=true;
}
}
}
// Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches
// are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness)
// This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too.
// 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward.
// Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
if(result->DistBox==FLT_MAX&&dist_axial<result->DistAxial)// Check axial match
//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.
g.NavInitRequest=false;// Found a match, clear request
NavUpdateAnyRequestFlag();
}
}
// Process Move Request (scoring for navigation)
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
constImRect&curr=g.NavScoringRectScreen;// 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
cand.ClipWithFull(window->ClipRect);// This allows the scored item to not overlap other candidates in the parent window
}
// We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items)
// For example, this ensure that items in one column are not reached when moving vertically from items in another column.
floatdby=NavScoreItemDistInterval(ImLerp(cand.Min.y,cand.Max.y,0.2f),ImLerp(cand.Min.y,cand.Max.y,0.8f),ImLerp(curr.Min.y,curr.Max.y,0.2f),ImLerp(curr.Min.y,curr.Max.y,0.8f));// Scale down on Y to keep using box-distance for vertically touching items
if(dby!=0.0f&&dbx!=0.0f)
dbx=(dbx/1000.0f)+((dbx>0.0f)?+1.0f:-1.0f);
floatdist_box=ImFabs(dbx)+ImFabs(dby);
// Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter)
floatdist_center=ImFabs(dcx)+ImFabs(dcy);// L1 metric (need this for our connectedness guarantee)
// Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance
ImGuiDirquadrant;
floatdax=0.0f,day=0.0f,dist_axial=0.0f;
if(dbx!=0.0f||dby!=0.0f)
{
// For non-overlapping boxes, use distance between boxes
dax=dbx;
day=dby;
dist_axial=dist_box;
quadrant=ImGetDirQuadrantFromDelta(dbx,dby);
}
elseif(dcx!=0.0f||dcy!=0.0f)
{
// For overlapping boxes with different centers, use distance between centers
dax=dcx;
day=dcy;
dist_axial=dist_center;
quadrant=ImGetDirQuadrantFromDelta(dcx,dcy);
}
else
{
// Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter)
// Is it in the quadrant we're interesting in moving to?
boolnew_best=false;
if(quadrant==g.NavMoveDir)
{
// Does it beat the current best candidate?
if(dist_box<result->DistBox)
{
result->DistBox=dist_box;
result->DistCenter=dist_center;
returntrue;
}
if(dist_box==result->DistBox)
{
// Try using distance between center points to break ties
if(dist_center<result->DistCenter)
{
result->DistCenter=dist_center;
new_best=true;
}
elseif(dist_center==result->DistCenter)
{
// 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
new_best=true;
}
}
}
// Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches
// are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness)
// This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too.
// 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward.
// Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
if(result->DistBox==FLT_MAX&&dist_axial<result->DistAxial)// Check axial match
//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.
g.NavInitRequest=false;// Found a match, clear request
NavUpdateAnyRequestFlag();
}
}
// Process Move Request (scoring for navigation)
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)