Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Navigation move ignore child order

Discussion in 'UI Toolkit' started by Lex4kraba, Apr 29, 2022.

  1. Lex4kraba

    Lex4kraba

    Joined:
    Jan 10, 2019
    Posts:
    2
    I have created two windows that can be moved.
    The active window moves to the foreground.
    If the windows are stacked on top of each other, then by controlling the keys, the focus is transferred by coordinates, ignoring the order of the children.
    As a result, the elements that are not visible are selected.

    Is this a bug? How can this be fixed?

    The video shows:
    1. Navigation when windows are free.
    2. Navigation when windows are stacked on top of each other. There's a problem here.
    3. Tab key navigation - there is no problem.
     
  2. Lex4kraba

    Lex4kraba

    Joined:
    Jan 10, 2019
    Posts:
    2
    Solved the problem by defining the next element manually via an event on the window.
    I'm still hoping for an answer from smarter people - how to solve this problem.


    Code (CSharp):
    1.  
    2. public static void OnNavigationMoveEvent(NavigationMoveEvent e, VisualElement ignore = null) {
    3.     var targetBound = (e.target as VisualElement).worldBound;
    4.     var distance = Mathf.Infinity;
    5.     var query = (e.currentTarget as VisualElement).Query();
    6.     VisualElement result = null;
    7.     if (e.direction == NavigationMoveEvent.Direction.Up) {
    8.         query.ForEach((VisualElement element) => {
    9.             if (element.focusable && element.worldBound.y < targetBound.y)
    10.                 _GetNextFocus(element, targetBound, ignore, ref result, ref distance);
    11.         });
    12.     } else if (e.direction == NavigationMoveEvent.Direction.Down) {
    13.         query.ForEach((VisualElement element) => {
    14.             if (element.focusable && element.worldBound.y > targetBound.y)
    15.                 _GetNextFocus(element, targetBound, ignore, ref result, ref distance);
    16.         });
    17.     } else if (e.direction == NavigationMoveEvent.Direction.Left) {
    18.         query.ForEach((VisualElement element) => {
    19.             if (element.focusable && element.worldBound.x < targetBound.x)
    20.                 _GetNextFocus(element, targetBound, ignore, ref result, ref distance);
    21.         });
    22.     } else if (e.direction == NavigationMoveEvent.Direction.Right) {
    23.         query.ForEach((VisualElement element) => {
    24.             if (element.focusable && element.worldBound.x > targetBound.x)
    25.                 _GetNextFocus(element, targetBound, ignore, ref result, ref distance);
    26.         });
    27.     }
    28.     if (result != null) {
    29.         e.PreventDefault();
    30.         result.Focus();
    31.     }
    32. }
    33.  
    34. private static void _GetNextFocus(VisualElement element, Rect targetBound, VisualElement ignore, ref VisualElement result, ref float distance) {
    35.     if (!element.ClassListContains("unity-base-field") && !element.ClassListContains("unity-base-field__input") && element != ignore) {
    36.         var tempDistance = Vector2.Distance(targetBound.position, element.worldBound.position);
    37.         if (tempDistance < distance) {
    38.             distance = tempDistance;
    39.             result = element;
    40.         }
    41.     }
    42. }
    43.