Search Unity

A few questions

Discussion in 'UI Toolkit' started by tertle, Jul 30, 2020.

  1. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Q1. How to focus a panel at runtime?
    upload_2020-7-30_21-28-50.png

    Panel A, the toolbar panel panel exists, it has like textfields etc.
    Panel B, the console overlay is by default hidden, but can be shown (like above image) at times.

    The problem I'm running into is, if the textfield in Panel A is focused when I load the console, it keeps focus in the EventSystem (input), even if the textfield is set to Focus on the new panel (because I've realized Focus() appears to be local to panel.)

    Reading EventSystem I feel like I could do this with a little reflection by setting focused Panel but as I'm not super experienced with this, I wanted to check before I started hacking away at a solution if there was a better way?

    Q2. How do I make a VisualElement stop all events passing through to another panel?
    In above example, I can still click on the buttons behind the top panel.
    I can kind of stop this by using this extension method

    Code (CSharp):
    1.         public static void BlockInputEvents(this VisualElement element)
    2.         {
    3.             element.RegisterCallback<MouseDownEvent>(StopPropagation);
    4.             element.RegisterCallback<MouseUpEvent>(StopPropagation);
    5.             element.RegisterCallback<KeyDownEvent>(StopPropagation);
    6.             element.RegisterCallback<KeyUpEvent>(StopPropagation);
    7.         }
    8.  
    9.         private static void StopPropagation(EventBase e)
    10.         {
    11.             e.StopPropagation();
    12.         }
    13.  
    14. //
    15. var root = this.document.rootVisualElement;
    16. root.BlockInputEvents();
    17.  
    But is there a better way?

    Q3. How do I prevent a key being sent to a text field?


    I thought I could could this by stopping the KeyDownEvent either on the actual TextField or the TextInput but neither worked

    Code (CSharp):
    1. this.inputField = root.Q<TextField>(InputName);
    2. this.inputField.RegisterCallback<KeyDownEvent>(evt =>
    3. {
    4.     if (evt.keyCode == CoreSettings.Instance.ShowConsole)
    5.     {
    6.         evt.PreventDefault();
    7.     }
    8. });
    9.  
    10. this.inputFieldInput = this.inputField.Q(TextField.textInputUssName);
    11. this.inputFieldInput.RegisterCallback<KeyDownEvent>(evt =>
    12. {
    13.     if (evt.keyCode == CoreSettings.Instance.ShowConsole)
    14.     {
    15.         evt.PreventDefault();
    16.     }
    17. });
    I kind of hacked this behaviour by setting this.inputField.isReadOnly on keydown, and unsetting it on keyup... seems like a pretty silly workaround though.

    Thanks in advanced!
     
  2. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    It sounds to me that you're still using the unreleased and now obsolete `com.unity.ui.runtime` package. If that's the case, please uninstall it and install the new `com.unity.ui` package. More info here:
    https://forum.unity.com/threads/ui-toolkit-1-0-preview-available.927822/

    I think the above issue was solved in the new implementation of runtime, where Panels are now assets (in the form of PanelSettings asset) and what you have in the scene are UIDocument components that can share a Panel. There's no reason why you should need 2 panels to do a console window on top of another part of your UI. You do all this in the same panel, by just displaying a different subtree of elements on top of the existing elements. Focus would then be handled properly by default.
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    I am not. I am using "com.unity.ui": "1.0.0-preview.6",

    They are separate panels because they are separate packages with no knowledge about each other. For ease of use the debug library is designed to be completely standalone with no setup required that we can just import into any project and it just works. Hence it sets itself up on its own panel with a really high sort layer and is stripped in release builds.

    You can't really expect all packages (especially on asset store) to be designed to share the same root panel?
     
    Last edited: Jul 31, 2020
    lclemens likes this.
  4. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    I see. Then here's what we recommend you try:
    1. PanelSettings asset should have a Sort Order setting you can use to make sure your Debug panel is always on top.
    2. Behind all your debug UI, you can have a VisualElement that takes up the entire screen using absolute positioning and left/right/top/bottom set to 0. This "layer" element can prevent all events from passing through the Debug UI. The Panel's Sort Order should also be the order in which Events are passed from Panel to Panel so if you prevent the propagation of all mouse and keyboard events, they should no longer be received by the Panels behind.