Search Unity

Events in UIElements

Discussion in 'UI Toolkit' started by luole1993, Nov 28, 2019.

  1. luole1993

    luole1993

    Joined:
    Jun 19, 2018
    Posts:
    5
    Hello.
    How to listen for keyboard click events in UIElements.
    I try to use UnityEngine.Event.current to capture keyboard click events but the UnityEngine.Event.current.keyCode I get is always None.
     
  2. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    UIElements is retained mode so the UI is made of objects that persist. As such, you can't (or ideally shouldn't) have code that constantly checks for keyboard states anymore. Instead, you can use UIElements' own event system to register for the
    KeyDownEvent
    (or
    KeyUpEvent
    ) on a specific element, using
    myElement.RegisterCallback<KeyDownEvent>((evt) => Debug.Log(evt.keyCode))
     
    nakkalokesh99 and a436t4ataf like this.
  3. luole1993

    luole1993

    Joined:
    Jun 19, 2018
    Posts:
    5
    Thanks.
     
  4. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    @uDamian surely this just makes things messy when you want your UI to controller inputs from the new input system?
     
  5. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    We haven't added full support in UIElements for the new Input System yet, but when we do, it will still be based on UI events (converted from the input system). It may not be
    KeyDownEvent
    , but the pattern should be similar.
     
  6. ilyaryzhenkov

    ilyaryzhenkov

    Joined:
    Mar 4, 2017
    Posts:
    6
    Any idea when UIElements & InputSystem will work together? Is it in scope for UIElements project or InputSystem project?
     
    RKar and Foxaphantsum like this.
  7. Foxaphantsum

    Foxaphantsum

    Joined:
    Jul 5, 2013
    Posts:
    139
    This would be good to know as well.
     
  8. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    Hello,

    The goal for the initial release is to use the new input system for touch detection.
    We are also looking into a good way for users to interface the two systems with custom logic.

    If there are specific things you're looking for do let us know in this thread or a new thread.
     
  9. Foxaphantsum

    Foxaphantsum

    Joined:
    Jul 5, 2013
    Posts:
    139
    If by touch do you mean pen support too? It'd be really useful to be able to use pen tablet inputs on things as well.
     
    Lars-Steenhoff likes this.
  10. ilyaryzhenkov

    ilyaryzhenkov

    Joined:
    Mar 4, 2017
    Posts:
    6
    I just want to completely disable old input events and use only new input system, but currently many things do not work in UI Elements. I don't need anything fancy, just basic text input and buttons.
     
  11. AlexiTheHusky

    AlexiTheHusky

    Joined:
    Jan 11, 2020
    Posts:
    3
    Here's a class I wrote based off the migration documentation:
    https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Migration.html

    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine.InputSystem;
    4.  
    5. namespace UnityEngine.UIElements
    6. {
    7.     [RequireComponent(typeof(EventSystem))]
    8.     public class InputSystemInputWrapper : InputWrapper
    9.     {
    10.         //Note - I created an input system asset named GameInput.  Yours may be different.
    11.         private GameInput m_input;
    12.  
    13.         private string _compositionString = "";
    14.         private Vector2 _lastImeCompositionCursorPos = Vector2.zero;
    15.         private IMECompositionMode _compositionMode = IMECompositionMode.Off;
    16.  
    17.  
    18.         private void Awake()
    19.         {
    20.             m_input = new GameInput(); //Note - I created an input system asset named GameInput.  Yours may be different.
    21.  
    22.             GetComponent<EventSystem>().inputOverride = this;
    23.         }
    24.  
    25.         private void Current_onIMECompositionChange(InputSystem.LowLevel.IMECompositionString composition)
    26.         {
    27.             if (_compositionMode == IMECompositionMode.Off)
    28.             {
    29.                 _compositionString = "";
    30.                 return;
    31.             }
    32.             //On/auto?
    33.             _compositionString = composition.ToString();
    34.         }
    35.  
    36.         private void OnEnable()
    37.         {
    38.             m_input.Enable();
    39.             Keyboard.current.onIMECompositionChange += Current_onIMECompositionChange;
    40.         }
    41.  
    42.         private void OnDisable()
    43.         {
    44.             m_input.Disable();
    45.             Keyboard.current.onIMECompositionChange -= Current_onIMECompositionChange;
    46.         }
    47.  
    48.         public override string compositionString
    49.         {
    50.             get { return _compositionString; }
    51.         }
    52.  
    53.         //Not supported by input system, but we can store the value I guess?
    54.         public override IMECompositionMode imeCompositionMode
    55.         {
    56.             get { return _compositionMode; }
    57.             set { _compositionMode = value; }
    58.         }
    59.  
    60.         //Read is not supported, but set is.
    61.         public override Vector2 compositionCursorPos
    62.         {
    63.             get { return _lastImeCompositionCursorPos; }
    64.             set { _lastImeCompositionCursorPos = value; Keyboard.current.SetIMECursorPosition(value); }
    65.         }
    66.  
    67.         public override bool mousePresent
    68.         {
    69.             get { return Mouse.current != null; }
    70.         }
    71.  
    72.         public override bool GetMouseButtonDown(int button)
    73.         {
    74.             if (button == 0) return Mouse.current.leftButton.wasPressedThisFrame;
    75.             if (button == 1) return Mouse.current.rightButton.wasPressedThisFrame;
    76.             if (button == 2) return Mouse.current.middleButton.wasPressedThisFrame;
    77.             return false;
    78.         }
    79.  
    80.         public override bool GetMouseButtonUp(int button)
    81.         {
    82.             if (button == 0) return Mouse.current.leftButton.wasReleasedThisFrame;
    83.             if (button == 1) return Mouse.current.rightButton.wasReleasedThisFrame;
    84.             if (button == 2) return Mouse.current.middleButton.wasReleasedThisFrame;
    85.             return false;
    86.         }
    87.  
    88.         public override bool GetMouseButton(int button)
    89.         {
    90.             if (button == 0) return Mouse.current.leftButton.isPressed;
    91.             if (button == 1) return Mouse.current.rightButton.isPressed;
    92.             if (button == 2) return Mouse.current.middleButton.isPressed;
    93.             return false;
    94.         }
    95.  
    96.         public override Vector2 mousePosition
    97.         {
    98.             get { return Mouse.current.position.ReadValue(); }
    99.         }
    100.  
    101.         //Note - Mapping not provided by https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Migration.html, guessed it instead.
    102.         public override Vector2 mouseScrollDelta
    103.         {
    104.             get { return Mouse.current.scroll.ReadValue(); }
    105.         }
    106.  
    107.         public override bool touchSupported
    108.         {
    109.             get { return Touchscreen.current != null; }
    110.         }
    111.  
    112.         public override int touchCount
    113.         {
    114.             get {
    115.                 if(!InputSystem.EnhancedTouch.EnhancedTouchSupport.enabled)
    116.                     InputSystem.EnhancedTouch.EnhancedTouchSupport.Enable();
    117.  
    118.                 return InputSystem.EnhancedTouch.Touch.activeTouches.Count;
    119.             }
    120.         }
    121.  
    122.         //Ugly.  Might need some work?
    123.         public override Touch GetTouch(int index)
    124.         {
    125.             if (!InputSystem.EnhancedTouch.EnhancedTouchSupport.enabled)
    126.                 InputSystem.EnhancedTouch.EnhancedTouchSupport.Enable();
    127.  
    128.             var result = new UnityEngine.Touch();
    129.             var t = InputSystem.EnhancedTouch.Touch.activeTouches[index];
    130.             result.position = t.screenPosition;
    131.             switch(t.phase)
    132.             {
    133.                 case InputSystem.TouchPhase.Began:
    134.                     result.phase = TouchPhase.Began;
    135.                     break;
    136.                 case InputSystem.TouchPhase.Canceled:
    137.                     result.phase = TouchPhase.Canceled;
    138.                     break;
    139.                 case InputSystem.TouchPhase.Ended:
    140.                     result.phase = TouchPhase.Ended;
    141.                     break;
    142.                 case InputSystem.TouchPhase.Moved:
    143.                     result.phase = TouchPhase.Moved;
    144.                     break;
    145.                 case InputSystem.TouchPhase.None:
    146.                 case InputSystem.TouchPhase.Stationary:
    147.                 default:
    148.                     result.phase = TouchPhase.Stationary;
    149.                     break;
    150.             }
    151.             result.deltaPosition = t.delta;
    152.             result.fingerId = t.finger.index;
    153.             result.deltaTime = (float)(t.time - t.startTime);
    154.             result.maximumPossiblePressure = 1f; //??
    155.             result.pressure = t.pressure;
    156.             result.radius = t.radius.magnitude; //??
    157.             result.radiusVariance = 0f; //??
    158.             result.rawPosition = t.screenPosition; //??
    159.             result.tapCount = t.tapCount;
    160.             result.type = TouchType.Direct; //??
    161.  
    162.  
    163.             return result;
    164.         }
    165.  
    166.  
    167.         public float GetGamePadHorizontalAxis()
    168.         {
    169.             //Missing this?
    170.             /* In GameInput UI
    171.              * - Add "UIGamePadHorizontal"
    172.              * - Action Type : Pass Through
    173.              * - Control Type: Axis
    174.              * - Add Binding "D-Pad/X [Gamepad]
    175.              */
    176.             return m_input.Player.UIGamePadHorizontal.ReadValue<float>();
    177.         }
    178.         public float GetGamePadVerticalAxis()
    179.         {
    180.             //Missing this?
    181.             /* In GameInput UI
    182.              * - Add "UIGamePadVertical"
    183.              * - Action Type : Pass Through
    184.              * - Control Type: Axis
    185.              * - Add Binding "D-Pad/Y [Gamepad]
    186.              */
    187.             return m_input.Player.UIGamePadVertical.ReadValue<float>();
    188.         }
    189.         public float GetGamePadSubmitButton()
    190.         {
    191.             //Missing this?
    192.             /* In GameInput UI
    193.              * - Add "UIGamePadSubmit"
    194.              * - Action Type : Pass Through
    195.              * - Control Type: Button
    196.              * - Add Binding "Button South [Gamepad]
    197.              */
    198.             return m_input.Player.UIGamePadSubmit.ReadValue<float>();
    199.         }
    200.  
    201.         public float GetGamePadCancelButton()
    202.         {
    203.             //Missing this?
    204.             /* In GameInput UI
    205.              * - Add "UIGamePadCancel"
    206.              * - Action Type : Pass Through
    207.              * - Control Type: Button
    208.              * - Add Binding "Button East [Gamepad]
    209.              */
    210.             return m_input.Player.UIGamePadCancel.ReadValue<float>();
    211.         }
    212.  
    213.         public override float GetAxisRaw(string axisName)
    214.         {
    215.             //No direct axis to GetAxisRaw results, but passthrough without filtering may provide what is needed.
    216.             //Have to manually bind them in the input designer UI.
    217.             switch(axisName)
    218.             {
    219.                 case "Vertical": return GetGamePadVerticalAxis();
    220.                 case "Horizontal": return GetGamePadHorizontalAxis();
    221.                 default:
    222.                     if (!LoggedAxis.Contains(axisName))
    223.                     {
    224.                         LoggedAxis.Add(axisName);
    225.                         Debug.Log($"InputSystemInputWrapper.GetAxisRaw(axisName:'{axisName}') - Not handled.  Must bind to something in the input builder ui then use ReadUnprocessedValue() method.");
    226.                     }
    227.  
    228.                     return 0;
    229.             }
    230.         }
    231.  
    232.         private List<string> LoggedAxis = new List<string>();
    233.         private List<string> LoggedButtonDown = new List<string>();
    234.  
    235.         public override bool GetButtonDown(string buttonName)
    236.         {
    237.             //No direct axis to GetAxisRaw results, but passthrough without filtering may provide what is needed.
    238.             //Have to manually bind them in the input designer UI.
    239.             //This binding might not be correct...  May need to bind to actual buttons for left/right etc or something idk.
    240.  
    241.             switch (buttonName)
    242.             {
    243.                 case "Vertical": return GetGamePadVerticalAxis() != 0;
    244.                 case "Horizontal": return GetGamePadHorizontalAxis() != 0;
    245.                 case "Submit": return GetGamePadSubmitButton() != 0;
    246.                 case "Cancel": return GetGamePadCancelButton() != 0;
    247.                 default:
    248.                     if (!LoggedButtonDown.Contains(buttonName))
    249.                     {
    250.                         LoggedButtonDown.Add(buttonName);
    251.                         Debug.Log($"InputSystemInputWrapper.GetButtonDown(buttonName:'{buttonName}') - Not handled.  Must bind to something in the input builder ui then use ReadUnprocessedValue() method.");
    252.  
    253.                     }
    254.                     return false;
    255.             }
    256.         }
    257.     }
    258. }
    259.  
     
  12. Katastroowl

    Katastroowl

    Joined:
    Jan 30, 2019
    Posts:
    2
    For now I will try to use the public InputWrapper inputOverride { get; set; } or edit the *.cs file from Event System UI Toolkit manually and directly (Didn't start yet, but think thats the approach that could work) -> However, the Use Case that belongs to that approach: When you have an always visible UI but also a FPS "kindof" Steering in a RTS related genre, when you move your character or unit, the UI Visual Elements > Components (e.g. Button that have the Property "focusable" set to true) are creating nice Disco-Light Effects because while moving your Unit (or in the specific case a Building Element for an engineer project) they change focus according to their tab order as intended, of course that should only happen while in UI Mode.
    So that is more ment to be a suggestion: Can you implement a Baseline option for the Unity to be able to deactivate A, W, S, D etc. Keys for set focus while UI is not in focus itself?
    Maybe something, methodologically, same as:
    Code (CSharp):
    1. UnityEngine.Cursor.lockState = UnityEngine.CursorLockMode.Confined;
    2.                 UnityEngine.Cursor.visible = true;
    That I use to switch forth and back between UI Mode and FPS Mode and it works for the Mouse perfectly, just add something like this for the other Input Methods :p if you agree ^o^ - Please give advice if there is already something like this and I missed it, thanks!
     
  13. RKar

    RKar

    Joined:
    Mar 6, 2019
    Posts:
    22
    But if I need to check the keyboard without binding to a specific element. And I don't want to use MonoBehaviour Update
     
  14. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    You could monitor for keyboard events on some root element. Events bubble up so even if another element is focused, if it doesn't use up the key event it should bubble up to the root.

    Otherwise, if you're just looking to know when keys are pressed outside the context of the UI, then you're not really in UI Toolkit territory anymore and should be able to use the new Input System directly.
     
  15. martymayfly

    martymayfly

    Joined:
    Mar 4, 2021
    Posts:
    8
    Hello @uDamian,
    I have watched your Ui toolkit demo and switch to UiElements, but i am stuck on a problem.
    How can i use EventSystem.current.IsPointerOverGameObject() with ui elements (Ui document) to understand the touch is on Ui or on my game area? Or a better advice?
    Thanks
     
  16. martymayfly

    martymayfly

    Joined:
    Mar 4, 2021
    Posts:
    8
    Anyone can help or have any ideas? @antoine-unity @uDamian