From 3abf84dc76cce3133424c5a0de2159f02ae5f3cd Mon Sep 17 00:00:00 2001 From: Simon Jackson Date: Sun, 16 Jul 2017 19:29:47 +0100 Subject: [PATCH] Updated TabNavigation based off comments in #149 * Renamed to TabNavigationHelper (as per Unity specs) * Resolved FirstSelected errors when no starting GO selected in Event System * Added Circular tabbing for both Auto and Manual Resolves #149 --- Scripts/TabNavigation.cs | 90 ----------- Scripts/TabNavigationHelper.cs | 152 ++++++++++++++++++ ...on.cs.meta => TabNavigationHelper.cs.meta} | 0 3 files changed, 152 insertions(+), 90 deletions(-) delete mode 100644 Scripts/TabNavigation.cs create mode 100644 Scripts/TabNavigationHelper.cs rename Scripts/{TabNavigation.cs.meta => TabNavigationHelper.cs.meta} (100%) diff --git a/Scripts/TabNavigation.cs b/Scripts/TabNavigation.cs deleted file mode 100644 index 72e3a41..0000000 --- a/Scripts/TabNavigation.cs +++ /dev/null @@ -1,90 +0,0 @@ -/// Credit Melang -/// Sourced from - http://forum.unity3d.com/members/melang.593409/ -/// Updated omatase 10-18-14 - support for Shift + Tab as well -/// - bug fix to prevent crash if no control selected -/// - updated to support new semantics for EventSystem in later 4.6 builds -/// - autoselect "firstSelectedGameObject" since it doesn't seem to work automatically -/// Updated 08-29-15 - On request of Issue #13 on repo, added a manual navigation order. - -using UnityEngine.EventSystems; - -namespace UnityEngine.UI.Extensions -{ - public enum NavigationMode { Auto = 0, Manual = 1}; - [RequireComponent(typeof(EventSystem))] - [AddComponentMenu("Event/Extensions/Tab Navigation Helper")] - public class TabNavigationHelper : MonoBehaviour - { - private EventSystem _system; - [Tooltip("The path to take when user is tabbing through ui components.")] - public Selectable[] NavigationPath; - [Tooltip("Use the default Unity navigation system or a manual fixed order using Navigation Path")] - public NavigationMode NavigationMode; - - void Start() - { - _system = GetComponent(); - if (_system == null) - { - Debug.LogError("Needs to be attached to the Event System component in the scene"); - } - } - - public void Update() - { - Selectable next = null; - - if (Input.GetKeyDown(KeyCode.Tab) && Input.GetKey(KeyCode.LeftShift)) - { - if (_system.currentSelectedGameObject != null) - { - next = _system.currentSelectedGameObject.GetComponent().FindSelectableOnUp(); - } - else - { - next = _system.firstSelectedGameObject.GetComponent(); - } - } - else if (Input.GetKeyDown(KeyCode.Tab)) - { - if (_system.currentSelectedGameObject != null) - { - next = _system.currentSelectedGameObject.GetComponent().FindSelectableOnDown(); - } - else - { - next = _system.firstSelectedGameObject.GetComponent(); - } - } - else if(NavigationMode == NavigationMode.Manual) - { - for (var i = 0; i < NavigationPath.Length; i++) - { - if (_system.currentSelectedGameObject != NavigationPath[i].gameObject) continue; - - - next = i == (NavigationPath.Length - 1) ? NavigationPath[0] : NavigationPath[i + 1]; - - break; - } - } - else if (_system.currentSelectedGameObject == null) - { - next = _system.firstSelectedGameObject.GetComponent(); - } - - selectGameObject(next); - } - - private void selectGameObject(Selectable selectable) - { - if (selectable != null) - { - InputField inputfield = selectable.GetComponent(); - if (inputfield != null) inputfield.OnPointerClick(new PointerEventData(_system)); //if it's an input field, also set the text caret - - _system.SetSelectedGameObject(selectable.gameObject, new BaseEventData(_system)); - } - } - } -} \ No newline at end of file diff --git a/Scripts/TabNavigationHelper.cs b/Scripts/TabNavigationHelper.cs new file mode 100644 index 0000000..12a287e --- /dev/null +++ b/Scripts/TabNavigationHelper.cs @@ -0,0 +1,152 @@ +/// Credit Melang +/// Sourced from - http://forum.unity3d.com/members/melang.593409/ +/// Updated omatase 10-18-14 - support for Shift + Tab as well +/// - bug fix to prevent crash if no control selected +/// - updated to support new semantics for EventSystem in later 4.6 builds +/// - autoselect "firstSelectedGameObject" since it doesn't seem to work automatically +/// Updated 08-29-15 - On request of Issue #13 on repo, added a manual navigation order. + +using UnityEngine.EventSystems; + +namespace UnityEngine.UI.Extensions +{ + public enum NavigationMode { Auto = 0, Manual = 1}; + [RequireComponent(typeof(EventSystem))] + [AddComponentMenu("Event/Extensions/Tab Navigation Helper")] + public class TabNavigationHelper : MonoBehaviour + { + private EventSystem _system; + private Selectable StartingObject; + private Selectable LastObject; + [Tooltip("The path to take when user is tabbing through ui components.")] + public Selectable[] NavigationPath; + [Tooltip("Use the default Unity navigation system or a manual fixed order using Navigation Path")] + public NavigationMode NavigationMode; + [Tooltip("If True, this will loop the tab order from last to first automatically")] + public bool CircularNavigation; + + void Start() + { + _system = GetComponent(); + if (_system == null) + { + Debug.LogError("Needs to be attached to the Event System component in the scene"); + } + if (NavigationMode == NavigationMode.Manual && NavigationPath.Length > 0) + { + StartingObject = NavigationPath[0].gameObject.GetComponent(); + } + if (StartingObject == null && CircularNavigation) + { + SelectDefaultObject(out StartingObject); + } + } + + public void Update() + { + Selectable next = null; + if (LastObject == null && _system.currentSelectedGameObject != null) + { + //Find the last selectable object + next = _system.currentSelectedGameObject.GetComponent().FindSelectableOnDown(); + while (next != null) + { + LastObject = next; + next = next.FindSelectableOnDown(); + } + } + + if (Input.GetKeyDown(KeyCode.Tab) && Input.GetKey(KeyCode.LeftShift)) + { + if (NavigationMode == NavigationMode.Manual && NavigationPath.Length > 0) + { + for (var i = NavigationPath.Length - 1; i >= 0; i--) + { + if (_system.currentSelectedGameObject != NavigationPath[i].gameObject) continue; + + next = i == 0 ? NavigationPath[NavigationPath.Length - 1] : NavigationPath[i - 1]; + + break; + } + } + else + { + if (_system.currentSelectedGameObject != null) + { + next = _system.currentSelectedGameObject.GetComponent().FindSelectableOnUp(); + if (next == null && CircularNavigation) + { + next = LastObject; + } + } + else + { + SelectDefaultObject(out next); + } + } + } + else if (Input.GetKeyDown(KeyCode.Tab)) + { + if (NavigationMode == NavigationMode.Manual && NavigationPath.Length > 0) + { + for (var i = 0; i < NavigationPath.Length; i++) + { + if (_system.currentSelectedGameObject != NavigationPath[i].gameObject) continue; + + next = i == (NavigationPath.Length - 1) ? NavigationPath[0] : NavigationPath[i + 1]; + + break; + } + } + else + { + if (_system.currentSelectedGameObject != null) + { + next = _system.currentSelectedGameObject.GetComponent().FindSelectableOnDown(); + if (next == null && CircularNavigation) + { + next = StartingObject; + } + } + else + { + SelectDefaultObject(out next); + } + } + } + else if (_system.currentSelectedGameObject == null) + { + SelectDefaultObject(out next); + } + + if (CircularNavigation && StartingObject == null) + { + StartingObject = next; + } + selectGameObject(next); + } + + private void SelectDefaultObject(out Selectable next) + { + if (_system.firstSelectedGameObject) + { + next = _system.firstSelectedGameObject.GetComponent(); + } + else + { + next = null; + } + } + + private void selectGameObject(Selectable selectable) + { + if (selectable != null) + { + InputField inputfield = selectable.GetComponent(); + if (inputfield != null) inputfield.OnPointerClick(new PointerEventData(_system)); //if it's an input field, also set the text caret + + _system.SetSelectedGameObject(selectable.gameObject, new BaseEventData(_system)); + } + } + } +} \ No newline at end of file diff --git a/Scripts/TabNavigation.cs.meta b/Scripts/TabNavigationHelper.cs.meta similarity index 100% rename from Scripts/TabNavigation.cs.meta rename to Scripts/TabNavigationHelper.cs.meta