Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057
| 11101 | |
| 11102 | // Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057 |
| 11103 | static bool ImGui::NavScoreItem(ImGuiNavItemData* result) |
| 11104 | { |
| 11105 | ImGuiContext& g = *GImGui; |
| 11106 | ImGuiWindow* window = g.CurrentWindow; |
| 11107 | if (g.NavLayer != window->DC.NavLayerCurrent) |
| 11108 | return false; |
| 11109 | |
| 11110 | // FIXME: Those are not good variables names |
| 11111 | ImRect cand = g.LastItemData.NavRect; // Current item nav rectangle |
| 11112 | 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) |
| 11113 | g.NavScoringDebugCount++; |
| 11114 | |
| 11115 | // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring |
| 11116 | if (window->ParentWindow == g.NavWindow) |
| 11117 | { |
| 11118 | IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); |
| 11119 | if (!window->ClipRect.Overlaps(cand)) |
| 11120 | return false; |
| 11121 | cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window |
| 11122 | } |
| 11123 | |
| 11124 | // 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) |
| 11125 | // For example, this ensures that items in one column are not reached when moving vertically from items in another column. |
| 11126 | NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect); |
| 11127 | |
| 11128 | // Compute distance between boxes |
| 11129 | // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. |
| 11130 | float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); |
| 11131 | 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 |
| 11132 | if (dby != 0.0f && dbx != 0.0f) |
| 11133 | dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); |
| 11134 | float dist_box = ImFabs(dbx) + ImFabs(dby); |
| 11135 | |
| 11136 | // 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) |
| 11137 | float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); |
| 11138 | float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); |
| 11139 | float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee) |
| 11140 | |
| 11141 | // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance |
| 11142 | ImGuiDir quadrant; |
| 11143 | float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; |
| 11144 | if (dbx != 0.0f || dby != 0.0f) |
| 11145 | { |
| 11146 | // For non-overlapping boxes, use distance between boxes |
| 11147 | dax = dbx; |
| 11148 | day = dby; |
| 11149 | dist_axial = dist_box; |
| 11150 | quadrant = ImGetDirQuadrantFromDelta(dbx, dby); |
| 11151 | } |
| 11152 | else if (dcx != 0.0f || dcy != 0.0f) |
| 11153 | { |
| 11154 | // For overlapping boxes with different centers, use distance between centers |
| 11155 | dax = dcx; |
| 11156 | day = dcy; |
| 11157 | dist_axial = dist_center; |
| 11158 | quadrant = ImGetDirQuadrantFromDelta(dcx, dcy); |
| 11159 | } |
| 11160 | else |
nothing calls this directly
no test coverage detected