forked from AyARL/UnityGUIExamples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMenuController.cs
More file actions
127 lines (107 loc) · 4.22 KB
/
Copy pathMenuController.cs
File metadata and controls
127 lines (107 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Builds a Navigation scheme for children of this game object that include a Selectable component (eg. Button, Toggle, InputField)
/// THIS CAN BE ACHIEVED IN THE EDITOR: Use the Navigation property on the Selectable to set it up, but in case you want a custom, dynamic system, this shows how to interact with various elements through script.
/// </summary>
public class MenuController : MonoBehaviour
{
// Assign in editor
[SerializeField]
private EventSystem eventSystem = null;
public enum NavigationMode { Vertical, Horizontal }
[SerializeField]
private NavigationMode navigationMode = NavigationMode.Vertical;
[SerializeField]
private bool circular = false;
[SerializeField]
private bool startingPoint = false;
private List<Selectable> menuElements = null; // All selectable UI elements inherit from UnityEngine.UI.Selectable - using this type in the list allows for mixing of different elements
void Start()
{
BuildNavigation();
}
private void BuildNavigation()
{
// grab all Selectables that are children on current gameObject
FindMenuElements();
// Set up the navigation for a circullar list following the order of objects in hierarchy and ignoring non-interactable elements
CreateNavigation();
// Set the first interactable element as selected in the EventSystem
if (startingPoint && menuElements.Count > 0)
{
Selectable firstSelected = menuElements.FirstOrDefault((e) => e.interactable);
if (firstSelected != null)
{
eventSystem.SetSelectedGameObject(firstSelected.gameObject, new BaseEventData(eventSystem));
}
else
{
eventSystem.SetSelectedGameObject(menuElements[0].gameObject, new BaseEventData(eventSystem));
}
}
}
private void FindMenuElements()
{
menuElements = new List<Selectable>();
foreach (Transform child in gameObject.transform)
{
Selectable selectabe = child.GetComponent<Selectable>();
if (selectabe != null)
{
menuElements.Add(selectabe);
}
}
}
private void CreateNavigation()
{
for (int i = 0; i < menuElements.Count; i++)
{
Selectable next = null;
Selectable previous = null;
FindNeighbours(i, ref next, ref previous);
// Create an initialise new Navigation object, then assign it to the current Selectable
Navigation navigation;
switch (navigationMode)
{
case NavigationMode.Vertical:
navigation = new Navigation() { mode = Navigation.Mode.Explicit, selectOnUp = previous, selectOnDown = next };
break;
case NavigationMode.Horizontal:
navigation = new Navigation() { mode = Navigation.Mode.Explicit, selectOnLeft = previous, selectOnRight = next };
break;
default:
navigation = new Navigation() { mode = Navigation.Mode.Explicit };
break;
}
menuElements[i].navigation = navigation;
}
}
private void FindNeighbours(int i, ref Selectable next, ref Selectable previous)
{
int nextIndex = i + 1;
int previousIndex = i - 1;
if (circular)
{
nextIndex %= menuElements.Count;
previousIndex = previousIndex < 0 ? menuElements.Count - 1 : previousIndex;
next = menuElements[nextIndex];
previous = menuElements[previousIndex];
}
else
{
if (nextIndex < menuElements.Count)
{
next = menuElements[nextIndex];
}
if (previousIndex >= 0)
{
previous = menuElements[previousIndex];
}
}
}
}