public static Selectable FindNextSelectable( Selectable selectable, Transform transform, List <Selectable> allSelectables, Vector3 direction) { RectTransform rectTransform1 = transform as RectTransform; if (Object.op_Equality((Object)rectTransform1, (Object)null)) { return((Selectable)null); } ((Vector3) ref direction).Normalize(); Vector2 dir = Vector2.op_Implicit(direction); Vector2 vector2_1 = Vector2.op_Implicit(UITools.GetPointOnRectEdge(rectTransform1, dir)); bool flag = Vector2.op_Equality(dir, Vector2.op_Multiply(Vector2.get_right(), -1f)) || Vector2.op_Equality(dir, Vector2.get_right()); float num1 = float.PositiveInfinity; float num2 = float.PositiveInfinity; Selectable selectable1 = (Selectable)null; Selectable selectable2 = (Selectable)null; Vector2 vector2_2 = Vector2.op_Addition(vector2_1, Vector2.op_Multiply(dir, 999999f)); for (int index = 0; index < allSelectables.Count; ++index) { Selectable allSelectable = allSelectables[index]; if (!Object.op_Equality((Object)allSelectable, (Object)selectable) && !Object.op_Equality((Object)allSelectable, (Object)null)) { Navigation navigation = allSelectable.get_navigation(); if (((Navigation) ref navigation).get_mode() != null && (allSelectable.IsInteractable() || (int)ReflectionTools.GetPrivateField <Selectable, bool>((M0)allSelectable, "m_GroupsAllowInteraction") != 0)) { RectTransform transform1 = ((Component)allSelectable).get_transform() as RectTransform; if (!Object.op_Equality((Object)transform1, (Object)null)) { Rect rect1 = UITools.InvertY(UITools.TransformRectTo((Transform)transform1, transform, transform1.get_rect())); float num3; if (MathTools.LineIntersectsRect(vector2_1, vector2_2, rect1, ref num3)) { if (flag) { num3 *= 0.25f; } if ((double)num3 < (double)num2) { num2 = num3; selectable2 = allSelectable; } } RectTransform rectTransform2 = transform1; Transform transform2 = transform; Rect rect2 = transform1.get_rect(); Vector3 vector3 = Vector2.op_Implicit(((Rect) ref rect2).get_center()); Vector2 vector2_3 = Vector2.op_Subtraction(Vector2.op_Implicit(UnityTools.TransformPoint((Transform)rectTransform2, transform2, vector3)), vector2_1); if ((double)Mathf.Abs(Vector2.Angle(dir, vector2_3)) <= 75.0) { float sqrMagnitude = ((Vector2) ref vector2_3).get_sqrMagnitude(); if ((double)sqrMagnitude < (double)num1) { num1 = sqrMagnitude; selectable1 = allSelectable; } } } } } } if (!Object.op_Inequality((Object)selectable2, (Object)null) || !Object.op_Inequality((Object)selectable1, (Object)null)) { return(selectable2 ?? selectable1); } return((double)num2 > (double)num1 ? selectable1 : selectable2); }
// Find the next selectable object in the specified world-space direction. public static Selectable FindNextSelectable(Selectable selectable, Transform transform, Vector3 direction) { RectTransform rectTransform = transform as RectTransform; if (rectTransform == null) { return(null); } IList <Selectable> allSelectables; int selectableCount; #if UNITY_2019_PLUS // Resize array as needed to fit all Selectables if (Selectable.allSelectableCount > s_reusableAllSelectables.Length) { s_reusableAllSelectables = new Selectable[Selectable.allSelectableCount]; } // Unity made a breaking API change in 2019.1.5 that removed the ref keyword. There is no clean way to catch it. #if UNITY_2019_1_0 || UNITY_2019_1_1 || UNITY_2019_1_2 || UNITY_2019_1_3 || UNITY_2019_1_4 // 2019.1 up to 2019.1.4 selectableCount = Selectable.AllSelectablesNoAlloc(ref s_reusableAllSelectables); allSelectables = s_reusableAllSelectables; #else // all future versions selectableCount = Selectable.AllSelectablesNoAlloc(ref s_reusableAllSelectables); allSelectables = s_reusableAllSelectables; #endif #else // pre-2019 versions allSelectables = Selectable.allSelectables; selectableCount = allSelectables.Count; #endif direction.Normalize(); Vector2 localDir = direction; Vector2 searchStartPos = Rewired.UI.ControlMapper.UITools.GetPointOnRectEdge(rectTransform, localDir); // search from point on rect edge from center out in direction bool isHoriz = localDir == Vector2.right * -1f || localDir == Vector2.right; float minCenterDistSqMag = Mathf.Infinity; float minDirectLineSqMag = Mathf.Infinity; Selectable bestCenterDistPick = null; Selectable bestDirectLinePick = null; const float length = 999999f; // Mathf.Infinity fails Vector2 directLineCastEndPos = searchStartPos + localDir * length; for (int i = 0; i < selectableCount; ++i) { Selectable targetSelectable = allSelectables[i]; if (targetSelectable == selectable || targetSelectable == null) { continue; // skip if self or null } if (targetSelectable.navigation.mode == Navigation.Mode.None) { continue; // skip if non-navigable } // Allow selection of non-interactable elements because it makes navigating easier and more predictable // but the CanvasGroup interactable value is private in Selectable #if !UNITY_WSA // Reflect to get group intaractability if non-interactable bool canvasGroupAllowsInteraction = targetSelectable.IsInteractable() || Rewired.Utils.ReflectionTools.GetPrivateField <Selectable, bool>(targetSelectable, "m_GroupsAllowInteraction"); if (!canvasGroupAllowsInteraction) { continue; // skip if disabled by canvas group, otherwise allow it } #else // Can't do private field reflection in Metro if (!targetSelectable.IsInteractable()) { continue; // skip if disabled } #endif var targetSelectableRectTransform = targetSelectable.transform as RectTransform; if (targetSelectableRectTransform == null) { continue; } // Check direct line cast from center edge of object in direction pressed float directLineSqMag; Rect targetSelecableRect = UITools.InvertY(UITools.TransformRectTo(targetSelectableRectTransform, transform, targetSelectableRectTransform.rect)); // Check for direct line rect intersection if (Rewired.Utils.MathTools.LineIntersectsRect(searchStartPos, directLineCastEndPos, targetSelecableRect, out directLineSqMag)) { if (isHoriz) { directLineSqMag *= 0.25f; // give extra bonus to horizontal directions because most of the UI groups are laid out horizontally } if (directLineSqMag < minDirectLineSqMag) { minDirectLineSqMag = directLineSqMag; bestDirectLinePick = targetSelectable; } } // Check distance to center Vector2 targetSelectableCenter = Rewired.Utils.UnityTools.TransformPoint(targetSelectableRectTransform, transform, targetSelectableRectTransform.rect.center); Vector2 searchPosToTargetSelectableCenter = targetSelectableCenter - searchStartPos; const float maxSafeAngle = 75.0f; // Get the angle the target center deviates from straight float angle = Mathf.Abs(Vector2.Angle(localDir, searchPosToTargetSelectableCenter)); if (angle > maxSafeAngle) { continue; // only consider if within a reasonable angle of the desired direction } float score = searchPosToTargetSelectableCenter.sqrMagnitude; // Lower score is better if (score < minCenterDistSqMag) { minCenterDistSqMag = score; bestCenterDistPick = targetSelectable; } } // Choose between direct line and center dist if (bestDirectLinePick != null && bestCenterDistPick != null) { if (minDirectLineSqMag > minCenterDistSqMag) { return(bestCenterDistPick); } return(bestDirectLinePick); } #if UNITY_2019_PLUS System.Array.Clear(s_reusableAllSelectables, 0, s_reusableAllSelectables.Length); #endif return(bestDirectLinePick ?? bestCenterDistPick); }
// Token: 0x060031B8 RID: 12728 RVA: 0x00146100 File Offset: 0x00144300 public static Selectable FindNextSelectable(Selectable selectable, Transform transform, List <Selectable> allSelectables, Vector3 direction) { RectTransform rectTransform = transform as RectTransform; if (rectTransform == null) { return(null); } direction.Normalize(); Vector2 vector = direction; Vector2 vector2 = UITools.GetPointOnRectEdge(rectTransform, vector); bool flag = vector == Vector2.right * -1f || vector == Vector2.right; float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; Selectable selectable2 = null; Selectable selectable3 = null; Vector2 point = vector2 + vector * 999999f; for (int i = 0; i < allSelectables.Count; i++) { Selectable selectable4 = allSelectables[i]; if (!(selectable4 == selectable) && !(selectable4 == null) && selectable4.navigation.mode != Navigation.Mode.None && (selectable4.IsInteractable() || ReflectionTools.GetPrivateField <Selectable, bool>(selectable4, "m_GroupsAllowInteraction"))) { RectTransform rectTransform2 = selectable4.transform as RectTransform; if (!(rectTransform2 == null)) { Rect rect = UITools.InvertY(UITools.TransformRectTo(rectTransform2, transform, rectTransform2.rect)); float num3; if (MathTools.LineIntersectsRect(vector2, point, rect, out num3)) { if (flag) { num3 *= 0.25f; } if (num3 < num2) { num2 = num3; selectable3 = selectable4; } } Vector2 to = UnityTools.TransformPoint(rectTransform2, transform, rectTransform2.rect.center) - vector2; if (Mathf.Abs(Vector2.Angle(vector, to)) <= 75f) { float sqrMagnitude = to.sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; selectable2 = selectable4; } } } } } if (!(selectable3 != null) || !(selectable2 != null)) { return(selectable3 ?? selectable2); } if (num2 > num) { return(selectable2); } return(selectable3); }