Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057
| 10843 | |
| 10844 | // Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057 |
| 10845 | static bool ImGui::NavScoreItem(ImGuiNavItemData* result) |
| 10846 | { |
| 10847 | ImGuiContext& g = *GImGui; |
| 10848 | ImGuiWindow* window = g.CurrentWindow; |
| 10849 | if (g.NavLayer != window->DC.NavLayerCurrent) |
| 10850 | return false; |
| 10851 | |
| 10852 | // FIXME: Those are not good variables names |
| 10853 | ImRect cand = g.LastItemData.NavRect; // Current item nav rectangle |
| 10854 | 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) |
| 10855 | g.NavScoringDebugCount++; |
| 10856 | |
| 10857 | // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring |
| 10858 | if (window->ParentWindow == g.NavWindow) |
| 10859 | { |
| 10860 | IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); |
| 10861 | if (!window->ClipRect.Overlaps(cand)) |
| 10862 | return false; |
| 10863 | cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window |
| 10864 | } |
| 10865 | |
| 10866 | // Compute distance between boxes |
| 10867 | // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. |
| 10868 | float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); |
| 10869 | 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 |
| 10870 | if (dby != 0.0f && dbx != 0.0f) |
| 10871 | dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); |
| 10872 | float dist_box = ImFabs(dbx) + ImFabs(dby); |
| 10873 | |
| 10874 | // 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) |
| 10875 | float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); |
| 10876 | float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); |
| 10877 | float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee) |
| 10878 | |
| 10879 | // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance |
| 10880 | ImGuiDir quadrant; |
| 10881 | float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; |
| 10882 | if (dbx != 0.0f || dby != 0.0f) |
| 10883 | { |
| 10884 | // For non-overlapping boxes, use distance between boxes |
| 10885 | dax = dbx; |
| 10886 | day = dby; |
| 10887 | dist_axial = dist_box; |
| 10888 | quadrant = ImGetDirQuadrantFromDelta(dbx, dby); |
| 10889 | } |
| 10890 | else if (dcx != 0.0f || dcy != 0.0f) |
| 10891 | { |
| 10892 | // For overlapping boxes with different centers, use distance between centers |
| 10893 | dax = dcx; |
| 10894 | day = dcy; |
| 10895 | dist_axial = dist_center; |
| 10896 | quadrant = ImGetDirQuadrantFromDelta(dcx, dcy); |
| 10897 | } |
| 10898 | else |
| 10899 | { |
| 10900 | // 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) |
| 10901 | quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; |
| 10902 | } |
nothing calls this directly
no test coverage detected