Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057
| 8648 | |
| 8649 | // Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057 |
| 8650 | static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand) |
| 8651 | { |
| 8652 | ImGuiContext& g = *GImGui; |
| 8653 | ImGuiWindow* window = g.CurrentWindow; |
| 8654 | if (g.NavLayer != window->DC.NavLayerCurrent) |
| 8655 | return false; |
| 8656 | |
| 8657 | const ImRect& 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) |
| 8658 | g.NavScoringCount++; |
| 8659 | |
| 8660 | // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring |
| 8661 | if (window->ParentWindow == g.NavWindow) |
| 8662 | { |
| 8663 | IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); |
| 8664 | if (!window->ClipRect.Overlaps(cand)) |
| 8665 | return false; |
| 8666 | cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window |
| 8667 | } |
| 8668 | |
| 8669 | // 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) |
| 8670 | // For example, this ensure that items in one column are not reached when moving vertically from items in another column. |
| 8671 | NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect); |
| 8672 | |
| 8673 | // Compute distance between boxes |
| 8674 | // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. |
| 8675 | float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); |
| 8676 | float dby = 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 |
| 8677 | if (dby != 0.0f && dbx != 0.0f) |
| 8678 | dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); |
| 8679 | float dist_box = ImFabs(dbx) + ImFabs(dby); |
| 8680 | |
| 8681 | // 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) |
| 8682 | float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); |
| 8683 | float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); |
| 8684 | float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee) |
| 8685 | |
| 8686 | // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance |
| 8687 | ImGuiDir quadrant; |
| 8688 | float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; |
| 8689 | if (dbx != 0.0f || dby != 0.0f) |
| 8690 | { |
| 8691 | // For non-overlapping boxes, use distance between boxes |
| 8692 | dax = dbx; |
| 8693 | day = dby; |
| 8694 | dist_axial = dist_box; |
| 8695 | quadrant = ImGetDirQuadrantFromDelta(dbx, dby); |
| 8696 | } |
| 8697 | else if (dcx != 0.0f || dcy != 0.0f) |
| 8698 | { |
| 8699 | // For overlapping boxes with different centers, use distance between centers |
| 8700 | dax = dcx; |
| 8701 | day = dcy; |
| 8702 | dist_axial = dist_center; |
| 8703 | quadrant = ImGetDirQuadrantFromDelta(dcx, dcy); |
| 8704 | } |
| 8705 | else |
| 8706 | { |
| 8707 | // 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) |
nothing calls this directly
no test coverage detected