Author Topic: Tab to cycle through controls?  (Read 9037 times)

pushxtonotdie

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 14
    • View Profile
Tab to cycle through controls?
« on: June 13, 2013, 12:14:51 PM »
I'm looking into handling focus management in NGUI, ie: when pressing 'tab' in a text field, I would like it to cycle to the next control. Has anyone accomplished this? Is there something similar to this built into NGUI i can turn on?

Cheers!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Tab to cycle through controls?
« Reply #1 on: June 13, 2013, 05:20:51 PM »
if (Input.GetKeyDown(KeyCode.Tab)) input.selected = false, select something else.

There is a script to make this easy for buttons and such, but I don't think it's going to work on inputs, so the code above should get you started.

pushxtonotdie

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 14
    • View Profile
Re: Tab to cycle through controls?
« Reply #2 on: June 14, 2013, 11:47:11 AM »
So apparently there is a selectOnTab property that works well for my needs, but unfortunately it seems that when building for iOS this is not part of UIInput's update() so it wasn't getting used. Copying this from the other update loop has gotten this working for me in the editor:

  1. if(selected)
  2. {
  3.   if (selectOnTab != null && Input.GetKeyDown(KeyCode.Tab))
  4.   {
  5.     UICamera.selectedObject = selectOnTab;
  6.   }
  7. }
  8.  

Sadly due to the way iOS keyboards work in Unity, this doesn't tab with bluetooth keyboards on iOS.

Quarkism

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 48
    • View Profile
Re: Tab to cycle through controls?
« Reply #3 on: June 14, 2013, 04:13:25 PM »
I ended writing my own solution. It has two parts. A child script (placed on the control) and a parent script (placed on the parent nodes. The child 'finds' the parent on awake and adds itself to a list. The parent handles all input, and selects the child.

Its a superior solution because it supports dynamic adding of elements (i.e. datalists). Moreover when designing your presentation layer It allot less work to simply give the controls an index value then to manually bind them to one another.

You will need to make some changes (IOC / Pause / Find In Parent)..... That is unless you magically have access to my infrastructure library.

  1.  /// <summary>
  2.     /// UI Controller script
  3.     /// </summary>
  4.     [RequireComponent(typeof(Collider))]
  5.     [AddComponentMenu("MainUI/Presentation/InputChild")]
  6.     public class InputChild : MonoBehaviour
  7.     {
  8.         /// <summary>
  9.         /// determines l/r selection order
  10.         /// </summary>
  11.         public int Col;
  12.  
  13.         /// <summary>
  14.         /// determines up/down selection order
  15.         /// </summary>
  16.         public int Row;
  17.  
  18.         /// <summary>
  19.         /// Determines Tab order
  20.         /// </summary>
  21.         public int TabIndex = 0;
  22.        
  23.         private InputController controller;
  24.  
  25.         public void Awake()
  26.         {
  27.             controller = this.FindInParent<InputController>();
  28.         }
  29.  
  30.         void OnEnable()
  31.         {
  32.             //   if(controller)
  33.             controller.Add(this);
  34.         }
  35.  
  36.         void OnDisable()
  37.         {
  38.             // if (controller)
  39.             controller.Remove(this);
  40.  
  41.             if (UICamera.selectedObject == gameObject)
  42.             {
  43.                 UICamera.selectedObject = null;
  44.             }
  45.         }
  46.  
  47.         void OnHover(bool isHover)
  48.         {
  49.             if (enabled && isHover)
  50.             {
  51.                 UICamera.selectedObject = gameObject;
  52.             }
  53.             else if (UICamera.selectedObject == gameObject)
  54.             {
  55.                 UICamera.selectedObject = null;
  56.             }
  57.         }
  58.  
  59.         void OnKey(KeyCode key)
  60.         {
  61.             if (controller.Paused)
  62.                 return;
  63.  
  64.             if (enabled && NGUITools.GetActive(gameObject))
  65.             {
  66.                 switch (key)
  67.                 {
  68.                     case KeyCode.LeftArrow:
  69.                         controller.GoLeft(this);
  70.                         break;
  71.                     case KeyCode.RightArrow:
  72.                         controller.GoRight(this);
  73.                         break;
  74.                     case KeyCode.UpArrow:
  75.                         controller.GoUp(this);
  76.                         break;
  77.                     case KeyCode.DownArrow:
  78.                         controller.GoDown(this);
  79.                         break;
  80.                     case KeyCode.Space:
  81.                     case KeyCode.Return:
  82.                         controller.GoInvoke(this);
  83.                         break;
  84.                     case KeyCode.Tab:
  85.                         if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
  86.                         {
  87.                             controller.GoBack(this);
  88.                         }
  89.                         else
  90.                         {
  91.                             controller.GoNext(this);
  92.                         }
  93.                         break;
  94.                 }
  95.             }
  96.         }
  97.     }

  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using Avarice.Ioc;
  4. using MainUI.ViewModels;
  5. using UnityEngine;
  6.  
  7. namespace MainUI.Presentation
  8. {
  9.     /// <summary>
  10.     /// UI Controller script. place on root.
  11.     /// </summary>
  12.     [AddComponentMenu("MainUI/Presentation/InputController")]
  13.     public class InputController : MonoBehaviour
  14.     {
  15.         protected readonly List<InputChild> Children = new List<InputChild>();
  16.  
  17.         public bool DisableOnPause = true;
  18.  
  19.         public bool SelectOnAwake = true;
  20.  
  21.         private PauseContext _pauseContext;
  22.  
  23.         public bool Paused
  24.         {
  25.             get { return DisableOnPause && _pauseContext.IsPaused; }
  26.         }
  27.  
  28.         private void Start()
  29.         {
  30.             _pauseContext = IocContainer.GetFirst<PauseContext>();
  31.         }
  32.  
  33.         void OnEnable()
  34.         {
  35.             Invoke("SelectDefault", .25f);
  36.         }
  37.  
  38.  
  39.         public void Add(InputChild child)
  40.         {
  41.             Children.Add(child);
  42.         }
  43.  
  44.         public void Remove(InputChild child)
  45.         {
  46.             Children.Remove(child);
  47.         }
  48.  
  49.         public void GoInvoke(InputChild child)
  50.         {
  51.  
  52.             child.gameObject.BroadcastMessage("OnPress", true);
  53.         }
  54.  
  55.         public void GoNext(InputChild child)
  56.         {
  57.             var ordered = Children.OrderBy(o => o.TabIndex);
  58.  
  59.             var next = ordered.FirstOrDefault(o => o.TabIndex > child.TabIndex) ?? ordered.FirstOrDefault();
  60.  
  61.             UICamera.selectedObject = next == null ? null : next.gameObject;
  62.  
  63.         }
  64.  
  65.         public void GoBack(InputChild child)
  66.         {
  67.             var ordered = Children.OrderBy(o => o.TabIndex);
  68.  
  69.             var next = ordered.LastOrDefault(o => o.TabIndex < child.TabIndex) ?? ordered.LastOrDefault();
  70.  
  71.             UICamera.selectedObject = next == null ? null : next.gameObject;
  72.         }
  73.  
  74.         public void GoLeft(InputChild child)
  75.         {
  76.             var ordered = Children.Where(o => o.Row == child.Row).OrderBy(o => o.Col);
  77.  
  78.             var next = ordered.LastOrDefault(o => o.Col < child.Col) ?? ordered.LastOrDefault();
  79.  
  80.             UICamera.selectedObject = next == null ? null : next.gameObject;
  81.         }
  82.  
  83.         public void GoRight(InputChild child)
  84.         {
  85.             var ordered = Children.Where(o => o.Row == child.Row).OrderBy(o => o.Col);
  86.  
  87.             var next = ordered.FirstOrDefault(o => o.Col > child.Col) ?? ordered.FirstOrDefault();
  88.  
  89.             UICamera.selectedObject = next == null ? null : next.gameObject;
  90.         }
  91.  
  92.         public void GoUp(InputChild child)
  93.         {
  94.             var ordered = Children.Where(o => o.Col == child.Col).OrderBy(o => o.Row);
  95.  
  96.             var next = ordered.LastOrDefault(o => o.Row < child.Row) ?? ordered.LastOrDefault();
  97.  
  98.             UICamera.selectedObject = next == null ? null : next.gameObject;
  99.  
  100.         }
  101.  
  102.         public void GoDown(InputChild child)
  103.         {
  104.             var ordered = Children.Where(o => o.Col == child.Col).OrderBy(o => o.Row);
  105.  
  106.             var next = ordered.FirstOrDefault(o => o.Row > child.Row) ??
  107.                        ordered.FirstOrDefault();
  108.  
  109.             UICamera.selectedObject = next == null ? null : next.gameObject;
  110.         }
  111.  
  112.         private void Update()
  113.         {
  114.             if (Paused)
  115.                 return;
  116.  
  117.             if (UICamera.selectedObject == null || !NGUITools.GetActive(UICamera.selectedObject))
  118.             {
  119.                 if (Input.GetKeyDown(KeyCode.LeftArrow)
  120.                     || Input.GetKeyDown(KeyCode.RightArrow)
  121.                     || Input.GetKeyDown(KeyCode.UpArrow)
  122.                     || Input.GetKeyDown(KeyCode.DownArrow)
  123.                     || Input.GetKeyDown(KeyCode.Tab)
  124.                     )
  125.                 {
  126.                     UICamera.selectedObject = Children.OrderBy(o => o.TabIndex).First().gameObject;
  127.                 }
  128.             }
  129.         }
  130.  
  131.         void SelectDefault()
  132.         {
  133.             if (SelectOnAwake)
  134.             {
  135.                 if (UICamera.selectedObject == null || !NGUITools.GetActive(UICamera.selectedObject))
  136.                 {
  137.                     var inp = Children.OrderBy(o => o.TabIndex).FirstOrDefault();
  138.  
  139.                     if (inp != null)
  140.                     {
  141.                         UICamera.selectedObject = inp.gameObject;
  142.                     }
  143.                 }
  144.             }
  145.         }
  146.     }
  147. }
« Last Edit: June 14, 2013, 04:24:05 PM by Quarkism »

pushxtonotdie

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 14
    • View Profile
Re: Tab to cycle through controls?
« Reply #4 on: June 14, 2013, 04:28:01 PM »
The magic of posting on forums. Thanks so much Quarkism for that code! Its always nice to have code to work off of. At a glance, your isolation of the code to just the 'slice' of functionality is just my style.

Thanks again!