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

Resolved How to get effective focus on an UIDocument?

Discussion in 'UI Toolkit' started by dlorre, Jan 25, 2022.

  1. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    When the app starts, the UIDocument appears and the element are visually focused but they do not react to keypresses such as TAB or Enter for a button. If I click inside the panel, then the keyboard events start working...

    I have tried this code but it did not help:

    Code (CSharp):
    1.         eventSystem = EventSystem.current;
    2.      
    3.         root = GetComponent<UIDocument>().rootVisualElement;
    4.  
    5.  
    6.         var mainPanel = root.Q<VisualElement>("main-panel");
    7.         mainPanel.Focus();
    8.         eventSystem.SetSelectedGameObject(gameObject);
     
  2. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    Hello, I just tried it here with Unity 2021.2.6f1 and it's working without having to set focus, what version of Unity are you on?

    In any case, VisualElement is not
    focusable
    by default (Buttons, Text Fields, Toggles etc are focusable by default), so you could see if setting that made a difference.

    Let us know how it goes!
     
  3. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    Hello, I was on 2022 beta but I just tried on 2021 it is the same: visible focus but the enter key does not respond, then when I click on the button one time the enter key works. I have also tried build and run and it is the same or worse. Here is a mp4 showing the issue however the mouse is not visible and there is no sound but you can trust that I'm hitting enter just after starting the project and then I click the button and enter works.

    Here is the UXML I have made the panel focusable:

    Code (CSharp):
    1. <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    2.     <Style src="project://database/Assets/style.uss?fileID=7433441132597879392&amp;guid=8002b1740c3f9aa49b7dd9850e8d2a41&amp;type=3#style" />
    3.     <ui:VisualElement name="main-panel" focusable="true" style="width: 50%; height: 50%; background-color: rgb(212, 153, 153);">
    4.         <ui:Button text="Open Dropdown" name="open-dropdown" display-tooltip-when-elided="true" class="text-button" />
    5.         <ui:Button text="Increment Slider" name="increment-slider" display-tooltip-when-elided="true"  class="text-button" />
    6.         <ui:Button text="Decrement Slider" name="decrement-slider" display-tooltip-when-elided="true"  class="text-button" />
    7.         <ui:Button display-tooltip-when-elided="true" class="round-button" style="background-image: url(&apos;project://database/Assets/Download/MinimalIconPack/Sprites/PC.png?fileID=6624680770263344914&amp;guid=337d2ac5dfa08ec4495abab2f86b6c70&amp;type=3#PC_8&apos;);" />
    8.         <ui:Slider name="my-slider" picking-mode="Ignore" label="Slider" value="42" high-value="100" tabindex="4" />
    9.         <ui:Toggle label="Toggle" />
    10.         <ui:DropdownField name="dropdown" label="Count" />
    11.     </ui:VisualElement>
    12. </ui:UXML>
    13.  
    and the relevant part of the css:

    Code (CSharp):
    1. Button:hover {
    2.     border-color: black;
    3. }
    4.  
    5. Button:focus {
    6.     border-color: red;
    7. }
    8.  
    9. Button:hover {
    10.     background-color: yellow;
    11. }
    12. Button:focus {
    13.     background-color: green;
    14. }
    15. Button:hover,focus {
    16.     background-color: pink;
    17. }
    18.  
    ETA: I should mention that I'm using the new Input System
    ETA2: my goal is simple, I lay a few controls and they must be activated and navigated with the gamepad, for a variety of reasons it does not work. I have sent several bug reports about this.
     

    Attached Files:

    Last edited: Jan 25, 2022
  4. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    Oh that changes something! Do you have the EventSystem component on your scene? For the new input system that is necessary.
     
  5. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    Yes I do, you can look at the project i have sent several bug reports with it, last is 1396866
     
  6. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    Ok I have isolated the bug, it's caused by the new InputSystem: with the exact same scene using UI Toolkit, when you switch from old input system to new, after running the project then pressing enter won't work until you have clicked into the window. I guess I have to choose between UI Toolkit and new input system for my project because both won't work together.

    I've made a new bug report with the 2 projects using old and new input system: 1398316

    ETA: I have opened a bug thread in the Input System forum.

    https://forum.unity.com/threads/focus-issue-with-ui-toolkit-and-new-input-system.1230729/

    ETA2: it is caused by the event system, so it effectively makes it impossible for me to use the UI Toolkit with the New Input Sytem since an EvenSystem component is required.
     
    Last edited: Jan 26, 2022
  7. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    From what I understand with the event debugger, the keydown events are coming to GameView instead of the panel:

    upload_2022-1-27_14-1-43.png

    Once I click a button they go to the panel:

    upload_2022-1-27_14-2-34.png

    So, how can I make these events going to panel settings from the start and not after I have clicked one element?
     
  8. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    Ok, so the best solution is to ignore the EventSystem component and do something like this:

    Code (CSharp):
    1.         var controls = InputController.Instance.Controls;
    2.         controls.Gamepad.South.started += context => actionSubmit();
    3.  
    Code (CSharp):
    1.     private void actionSubmit()
    2.     {
    3.         var elem = root.focusController.focusedElement;
    4.         if (elem is Button button)
    5.         {
    6.             button.SendEvent(NavigationSubmitEvent.GetPooled());
    7.         }
    8.         if (elem is DropdownField)
    9.         {
    10.             var dropdown = elem as DropdownField;
    11.             {
    12.                 var ev = new OtherKeyDownEvent(KeyCode.KeypadEnter);
    13.                 dropdown.SendEvent(ev);
    14.             }
    15.         }
    16.     }
     
  9. uBenoitA

    uBenoitA

    Unity Technologies

    Joined:
    Apr 15, 2020
    Posts:
    198
    Yes, that's a little difference between getting UI Toolkit events through UGUI's EventSystem or getting them through the invisible DefaultEventSystem. UGUI doesn't send keyboard events to anything unless some object has focus, so in that case we have no chance to react to it. If I'm not mistaken, If you had no EventSystem in your scene you would receive those KeyDowns whether or not you have anything in focus. A possible workaround if you know your panel will want the KeyDown events for sure, would be to have some script like this:

    Code (CSharp):
    1. class EventSystemSelectionInitializer : MonoBehaviour
    2. {
    3.     public PanelSettings panelSettings; // drag your PanelSettings here in the inspector
    4.     void Start()
    5.     {
    6.         if (EventSystem.current != null)
    7.             EventSystem.current.SetSelectedGameObject(EventSystem.current.transform.Find(panelSettings.name).gameObject);
    8.     }
    9. }
    10.  
     
    Kinbury and dlorre like this.
  10. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    Thanks that is very helpful, I tried to select the UIDocument object but that did not work.

    On a side note I have noticed that even without an EventSytem the NavigationTab events are sent when the tab key is pressed on keyboard.
     
  11. Beacom

    Beacom

    Joined:
    Jan 8, 2016
    Posts:
    2
    The script shared above was necessary to add to the Event Handler in Unity 2022.2.1f1 in order to get keyboard input working without an initial mouse press as well when using the new Input package and UI Toolkit.
     
  12. g-t

    g-t

    Joined:
    Jun 5, 2020
    Posts:
    3
    Same for me.
    Using new input system + UI toolkit.
    Adding the script that uBenoitA posted to the event system in scene helped. Thank you! I was struggling with this for two days.
     
  13. BusyRoots

    BusyRoots

    Joined:
    Jul 25, 2017
    Posts:
    40
    This solution did not work for me. I had to add an additional PanelEventHandler Script (it's part of the UnityEngine.UIElements namespace) to the UIDocument GameObject and set the focus using this. I'm also using the (new) InputSystem.

    What's a bit strange is, that the EventSystem component in the scene already creates a PanelEventHandler as child component by itself when the scene started. So now I have 2 of them in the scene.
    But I also I have my old uGUI still in place, which will be replaced with some new UIToolkit elements. I assume both UIs somehow fight for the input event focus.