Tanoda
UITabNavigator.cs
Go to the documentation of this file.
1 using System.Collections.Generic;
2 using UnityEngine;
4 using UnityEngine.UI;
5
6 public class UITabNavigator : MonoBehaviour
7 {
8 private void Awake()
9 {
10 this._orderedSelectables = new List<Selectable>();
11 }
12
13 private void Start()
14 {
15 this.SortSelectables();
16 }
17
18 private void Update()
19 {
20 if (Input.GetKeyDown(KeyCode.Tab))
21 {
23 // Navigate backward when holding shift, else navigate forward.
24 this.HandleHotkeySelect(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift), true);
25 }
26 }
27
31 public void SortSelectables()
32 {
33 List<Selectable> originalSelectables = Selectable.allSelectables;
34 int totalSelectables = originalSelectables.Count;
35 this._orderedSelectables = new List<Selectable>(totalSelectables);
36 for (int index = 0; index < totalSelectables; ++index)
37 {
38 Selectable selectable = originalSelectables[index];
39 this._orderedSelectables.Insert(
40 this.FindSortedIndexForSelectable(index, selectable), selectable);
41 }
42 }
43
44 private void HandleHotkeySelect(bool isNavigateBackward, bool isWrapAround)
45 {
46 GameObject selectedObject = EventSystem.current.currentSelectedGameObject;
47 if (selectedObject != null && selectedObject.activeInHierarchy) // Ensure a selection exists and is not an inactive object.
48 {
49 Selectable currentSelection = selectedObject.GetComponent<Selectable>();
50 if (currentSelection != null)
51 {
52 Selectable nextSelection = this.FindNextSelectable(
53 this._orderedSelectables.IndexOf(currentSelection), isNavigateBackward, isWrapAround);
54 if (nextSelection != null)
55 {
56 nextSelection.Select();
57 }
58 }
59 else
60 {
61 this.SelectFirstSelectable();
62 }
63 }
64 else
65 {
66 this.SelectFirstSelectable();
67 }
68 }
69
70 private void SelectFirstSelectable()
71 {
72 if (this._orderedSelectables != null && this._orderedSelectables.Count > 0)
73 {
74 Selectable firstSelectable = this._orderedSelectables[0];
75 firstSelectable.Select();
76 }
77 }
78
82 private Selectable FindNextSelectable(int currentSelectableIndex, bool isNavigateBackward, bool isWrapAround)
83 {
84 Selectable nextSelection = null;
85
86 int totalSelectables = this._orderedSelectables.Count;
87 if (totalSelectables > 1)
88 {
89 if (isNavigateBackward)
90 {
91 if (currentSelectableIndex == 0)
92 {
93 nextSelection = (isWrapAround) ? this._orderedSelectables[totalSelectables - 1] : null;
94 }
95 else
96 {
97 nextSelection = this._orderedSelectables[currentSelectableIndex - 1];
98 }
99 }
100 else // Navigate forward.
101 {
102 if (currentSelectableIndex == (totalSelectables - 1))
103 {
104 nextSelection = (isWrapAround) ? this._orderedSelectables[0] : null;
105 }
106 else
107 {
108 nextSelection = this._orderedSelectables[currentSelectableIndex + 1];
109 }
110 }
111 }
112
113 return nextSelection;
114 }
115
119 private int FindSortedIndexForSelectable(int selectableIndex, Selectable selectableToSort)
120 {
121 int sortedIndex = selectableIndex;
122 if (selectableIndex > 0)
123 {
124 int previousIndex = selectableIndex - 1;
125 Vector3 previousSelectablePosition = this._orderedSelectables[previousIndex].transform.position;
126 Vector3 selectablePositionToSort = selectableToSort.transform.position;
127
128 if ((previousSelectablePosition.y < selectablePositionToSort.y)
129 || (previousSelectablePosition.y == selectablePositionToSort.y
130 && previousSelectablePosition.x > selectablePositionToSort.x))
131 {
132 // Previous selectable is in front, try the previous index:
133 sortedIndex = this.FindSortedIndexForSelectable(previousIndex, selectableToSort);
134 }
135 }
136
137 return sortedIndex;
138 }
139
140 private List<Selectable> _orderedSelectables = null;
141 }
void SortSelectables()
Iterates through all selectables in scene and orders them based on their position.