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. Dismiss Notice

Multiple EventSystem axes?

Discussion in 'UGUI & TextMesh Pro' started by DreamCore90, Feb 3, 2015.

  1. DreamCore90

    DreamCore90

    Joined:
    Dec 16, 2014
    Posts:
    21
    When you use the new 4.6 UI System, you need an EventSystem game object. This game object has a Standalone Input Module component attached to it, in which you can specify a horizontal and vertical axis to use with the HUD. However, I'm wondering if there is any way to use multiple axes for horizontal and vertical respectively, so that I can, for example, use both the analog stick and D-Pad to navigate the UI.

    Thanks!
     
  2. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
    Yes you can, you would just need to build your own input system for a gamepad and attach it to the event system.
    Look at the existing input systems in the ui source fir examples on how to do this
     
  3. DreamCore90

    DreamCore90

    Joined:
    Dec 16, 2014
    Posts:
    21
    I looked at the source code for BaseInputModule and StandaloneInputModule but because they are assemblies (.dlls) I don't have access to all the source code (only the interfaces if opened in Visual Studio, and no member variables etc. if opened in Mono Develop), so I don't understand how I'm supposed to create a new one based on that incomplete information.
     
  4. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    SimonDarksideJ likes this.
  5. JFR

    JFR

    Joined:
    Feb 21, 2014
    Posts:
    65
    Here I go necro posting, in case someone else wonders the same thing. The quickest way to do this is to simply add a second StandAloneInputHandler to your EventSystem game object. Leave all values you don't need duplicated blank and only add the ones that will act as input alternatives.
     
    mauriciofelippe likes this.
  6. mauriciofelippe

    mauriciofelippe

    Joined:
    Aug 9, 2017
    Posts:
    28
    So in case someone else needs this thing, here the code.
    Code (CSharp):
    1. using System;
    2. // using UnityEditor;
    3. using UnityEngine.Serialization;
    4. using UnityEngine;
    5. using UnityEngine.EventSystems;
    6.  
    7. // ReSharper disable once CheckNamespace
    8. public sealed class ControllerInputModule : PointerInputModule
    9. {
    10.     private float m_PrevActionTime;
    11.     private Vector2 m_LastMoveVector;
    12.     private int m_ConsecutiveMoveCount = 0;
    13.     private Vector2 m_LastMousePosition;
    14.     private Vector2 m_MousePosition;
    15.     private GameObject m_CurrentFocusedGameObject;
    16.     private PointerEventData m_InputPointerEvent;
    17.     [SerializeField]
    18.     private string m_HorizontalAxis = "Horizontal";
    19.     [SerializeField]
    20.     private string m_VerticalAxis = "Vertical";
    21.     [SerializeField]
    22.     private string m_HorizontalAxis2 = "Horizontal2";
    23.     [SerializeField]
    24.     private string m_VerticalAxis2 = "Vertical2";
    25.     [SerializeField]
    26.     private string m_SubmitButton = "Submit";
    27.     [SerializeField]
    28.     private string m_CancelButton = "Cancel";
    29.     [SerializeField]
    30.     private float m_InputActionsPerSecond = 10f;
    31.     [SerializeField]
    32.     private float m_RepeatDelay = 0.5f;
    33.     [SerializeField]
    34.     [FormerlySerializedAs("m_AllowActivationOnMobileDevice")]
    35.     private bool m_ForceModuleActive;
    36.  
    37.     private ControllerInputModule()
    38.     {
    39.     }
    40.  
    41.     [Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
    42.     public StandaloneInputModule.InputMode inputMode => StandaloneInputModule.InputMode.Mouse;
    43.  
    44.     [Obsolete("allowActivationOnMobileDevice has been deprecated. Use forceModuleActive instead (UnityUpgradable) -> forceModuleActive")]
    45.     public bool allowActivationOnMobileDevice
    46.     {
    47.       get => m_ForceModuleActive;
    48.       set => m_ForceModuleActive = value;
    49.     }
    50.  
    51.     public bool forceModuleActive
    52.     {
    53.       get => m_ForceModuleActive;
    54.       set => m_ForceModuleActive = value;
    55.     }
    56.  
    57.     public float inputActionsPerSecond
    58.     {
    59.       get => m_InputActionsPerSecond;
    60.       set => m_InputActionsPerSecond = value;
    61.     }
    62.  
    63.     public float repeatDelay
    64.     {
    65.       get => m_RepeatDelay;
    66.       set => m_RepeatDelay = value;
    67.     }
    68.  
    69.     public string horizontalAxis
    70.     {
    71.       get => m_HorizontalAxis;
    72.       set => m_HorizontalAxis = value;
    73.     }
    74.    
    75.     public string horizontalAxis2
    76.     {
    77.       get => m_HorizontalAxis;
    78.       set => m_HorizontalAxis = value;
    79.     }
    80.  
    81.     public string verticalAxis
    82.     {
    83.       get => m_VerticalAxis;
    84.       set => m_VerticalAxis = value;
    85.     }
    86.    
    87.     public string verticalAxis2
    88.     {
    89.       get => m_VerticalAxis;
    90.       set => m_VerticalAxis = value;
    91.     }
    92.  
    93.     public string submitButton
    94.     {
    95.       get => m_SubmitButton;
    96.       set => m_SubmitButton = value;
    97.     }
    98.  
    99.     public string cancelButton
    100.     {
    101.       get => m_CancelButton;
    102.       set => m_CancelButton = value;
    103.     }
    104.  
    105.     private bool ShouldIgnoreEventsOnNoFocus()
    106.     {
    107.       switch (SystemInfo.operatingSystemFamily)
    108.       {
    109.         case OperatingSystemFamily.MacOSX:
    110.         case OperatingSystemFamily.Windows:
    111.         case OperatingSystemFamily.Linux:
    112.           return true;
    113.         default:
    114.           return false;
    115.       }
    116.     }
    117.  
    118.     public override void UpdateModule()
    119.     {
    120.       if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
    121.       {
    122.         if (m_InputPointerEvent != null && m_InputPointerEvent.pointerDrag != null && m_InputPointerEvent.dragging)
    123.           ExecuteEvents.Execute(m_InputPointerEvent.pointerDrag, m_InputPointerEvent, ExecuteEvents.endDragHandler);
    124.         m_InputPointerEvent = null;
    125.       }
    126.       else
    127.       {
    128.         m_LastMousePosition = m_MousePosition;
    129.         m_MousePosition = input.mousePosition;
    130.       }
    131.     }
    132.  
    133.     public override bool IsModuleSupported() => m_ForceModuleActive || input.mousePresent || input.touchSupported;
    134.  
    135.     public override bool ShouldActivateModule()
    136.     {
    137.       if (!base.ShouldActivateModule())
    138.         return false;
    139.       var flag = m_ForceModuleActive | input.GetButtonDown(m_SubmitButton) | input.GetButtonDown(m_CancelButton) | !Mathf.Approximately(input.GetAxisRaw(m_HorizontalAxis), 0.0f) | !Mathf.Approximately(input.GetAxisRaw(m_VerticalAxis), 0.0f) | (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0 | input.GetMouseButtonDown(0);
    140.       if (input.touchCount > 0)
    141.         flag = true;
    142.       return flag;
    143.     }
    144.  
    145.     public override void ActivateModule()
    146.     {
    147.       if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
    148.         return;
    149.       base.ActivateModule();
    150.       m_MousePosition = input.mousePosition;
    151.       m_LastMousePosition = input.mousePosition;
    152.       var selectedGameObject = eventSystem.currentSelectedGameObject;
    153.       if (selectedGameObject == null)
    154.         selectedGameObject = eventSystem.firstSelectedGameObject;
    155.       eventSystem.SetSelectedGameObject(selectedGameObject, GetBaseEventData());
    156.     }
    157.  
    158.     public override void DeactivateModule()
    159.     {
    160.       base.DeactivateModule();
    161.       ClearSelection();
    162.     }
    163.  
    164.     public override void Process()
    165.     {
    166.       if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
    167.         return;
    168.       var selectedObject = SendUpdateEventToSelectedObject();
    169.       if (eventSystem.sendNavigationEvents)
    170.       {
    171.         if (!selectedObject)
    172.           selectedObject |= SendMoveEventToSelectedObject();
    173.         if (!selectedObject)
    174.           SendSubmitEventToSelectedObject();
    175.       }
    176.       // if (this.ProcessTouchEvents() || !this.input.mousePresent)
    177.       //   return;
    178.       // this.ProcessMouseEvent();
    179.     }
    180.  
    181.     // private bool ProcessTouchEvents()
    182.     // {
    183.     //   for (int index = 0; index < this.input.touchCount; ++index)
    184.     //   {
    185.     //     Touch touch = this.input.GetTouch(index);
    186.     //     if (touch.type != TouchType.Indirect)
    187.     //     {
    188.     //       bool pressed;
    189.     //       bool released;
    190.     //       PointerEventData pointerEventData = this.GetTouchPointerEventData(touch, out pressed, out released);
    191.     //       this.ProcessTouchPress(pointerEventData, pressed, released);
    192.     //       if (!released)
    193.     //       {
    194.     //         this.ProcessMove(pointerEventData);
    195.     //         this.ProcessDrag(pointerEventData);
    196.     //       }
    197.     //       else
    198.     //         this.RemovePointerData(pointerEventData);
    199.     //     }
    200.     //   }
    201.     //   return this.input.touchCount > 0;
    202.     // }
    203.  
    204.     // protected void ProcessTouchPress(PointerEventData pointerEvent, bool pressed, bool released)
    205.     // {
    206.     //   GameObject gameObject1 = pointerEvent.pointerCurrentRaycast.gameObject;
    207.     //   if (pressed)
    208.     //   {
    209.     //     pointerEvent.eligibleForClick = true;
    210.     //     pointerEvent.delta = Vector2.zero;
    211.     //     pointerEvent.dragging = false;
    212.     //     pointerEvent.useDragThreshold = true;
    213.     //     pointerEvent.pressPosition = pointerEvent.position;
    214.     //     pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
    215.     //     this.DeselectIfSelectionChanged(gameObject1, (BaseEventData) pointerEvent);
    216.     //     if ((UnityEngine.Object) pointerEvent.pointerEnter != (UnityEngine.Object) gameObject1)
    217.     //     {
    218.     //       this.HandlePointerExitAndEnter(pointerEvent, gameObject1);
    219.     //       pointerEvent.pointerEnter = gameObject1;
    220.     //     }
    221.     //     GameObject gameObject2 = ExecuteEvents.ExecuteHierarchy<IPointerDownHandler>(gameObject1, (BaseEventData) pointerEvent, ExecuteEvents.pointerDownHandler);
    222.     //     if ((UnityEngine.Object) gameObject2 == (UnityEngine.Object) null)
    223.     //       gameObject2 = ExecuteEvents.GetEventHandler<IPointerClickHandler>(gameObject1);
    224.     //     float unscaledTime = Time.unscaledTime;
    225.     //     if ((UnityEngine.Object) gameObject2 == (UnityEngine.Object) pointerEvent.lastPress)
    226.     //     {
    227.     //       if ((double) (unscaledTime - pointerEvent.clickTime) < 0.300000011920929)
    228.     //         ++pointerEvent.clickCount;
    229.     //       else
    230.     //         pointerEvent.clickCount = 1;
    231.     //       pointerEvent.clickTime = unscaledTime;
    232.     //     }
    233.     //     else
    234.     //       pointerEvent.clickCount = 1;
    235.     //     pointerEvent.pointerPress = gameObject2;
    236.     //     pointerEvent.rawPointerPress = gameObject1;
    237.     //     pointerEvent.clickTime = unscaledTime;
    238.     //     pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(gameObject1);
    239.     //     if ((UnityEngine.Object) pointerEvent.pointerDrag != (UnityEngine.Object) null)
    240.     //       ExecuteEvents.Execute<IInitializePotentialDragHandler>(pointerEvent.pointerDrag, (BaseEventData) pointerEvent, ExecuteEvents.initializePotentialDrag);
    241.     //     this.m_InputPointerEvent = pointerEvent;
    242.     //   }
    243.     //   if (!released)
    244.     //     return;
    245.     //   ExecuteEvents.Execute<IPointerUpHandler>(pointerEvent.pointerPress, (BaseEventData) pointerEvent, ExecuteEvents.pointerUpHandler);
    246.     //   GameObject eventHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(gameObject1);
    247.     //   if ((UnityEngine.Object) pointerEvent.pointerPress == (UnityEngine.Object) eventHandler && pointerEvent.eligibleForClick)
    248.     //     ExecuteEvents.Execute<IPointerClickHandler>(pointerEvent.pointerPress, (BaseEventData) pointerEvent, ExecuteEvents.pointerClickHandler);
    249.     //   else if ((UnityEngine.Object) pointerEvent.pointerDrag != (UnityEngine.Object) null && pointerEvent.dragging)
    250.     //     ExecuteEvents.ExecuteHierarchy<IDropHandler>(gameObject1, (BaseEventData) pointerEvent, ExecuteEvents.dropHandler);
    251.     //   pointerEvent.eligibleForClick = false;
    252.     //   pointerEvent.pointerPress = (GameObject) null;
    253.     //   pointerEvent.rawPointerPress = (GameObject) null;
    254.     //   if ((UnityEngine.Object) pointerEvent.pointerDrag != (UnityEngine.Object) null && pointerEvent.dragging)
    255.     //     ExecuteEvents.Execute<IEndDragHandler>(pointerEvent.pointerDrag, (BaseEventData) pointerEvent, ExecuteEvents.endDragHandler);
    256.     //   pointerEvent.dragging = false;
    257.     //   pointerEvent.pointerDrag = (GameObject) null;
    258.     //   ExecuteEvents.ExecuteHierarchy<IPointerExitHandler>(pointerEvent.pointerEnter, (BaseEventData) pointerEvent, ExecuteEvents.pointerExitHandler);
    259.     //   pointerEvent.pointerEnter = (GameObject) null;
    260.     //   this.m_InputPointerEvent = pointerEvent;
    261.     // }
    262.  
    263.     private bool SendSubmitEventToSelectedObject()
    264.     {
    265.       if (eventSystem.currentSelectedGameObject == null)
    266.         return false;
    267.       var baseEventData = GetBaseEventData();
    268.       if (input.GetButtonDown(m_SubmitButton))
    269.         ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, baseEventData, ExecuteEvents.submitHandler);
    270.       if (input.GetButtonDown(m_CancelButton))
    271.         ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, baseEventData, ExecuteEvents.cancelHandler);
    272.       return baseEventData.used;
    273.     }
    274.  
    275.     private Vector2 GetRawMoveVector()
    276.     {
    277.       var zero = Vector2.zero;
    278.       zero.x = input.GetAxisRaw(m_HorizontalAxis) + input.GetAxisRaw(m_HorizontalAxis2);
    279.       zero.y = input.GetAxisRaw(m_VerticalAxis) + input.GetAxisRaw(m_VerticalAxis2);
    280.       if (input.GetButtonDown(m_HorizontalAxis) || input.GetButtonDown(m_HorizontalAxis2))
    281.       {
    282.         if (zero.x < 0.0)
    283.           zero.x = -1f;
    284.         if (zero.x > 0.0)
    285.           zero.x = 1f;
    286.       }
    287.       if (input.GetButtonDown(m_VerticalAxis) || input.GetButtonDown(m_VerticalAxis2))
    288.       {
    289.         if (zero.y < 0.0)
    290.           zero.y = -1f;
    291.         if (zero.y > 0.0)
    292.           zero.y = 1f;
    293.       }
    294.       return zero;
    295.     }
    296.  
    297.     private bool SendMoveEventToSelectedObject()
    298.     {
    299.       var unscaledTime = Time.unscaledTime;
    300.       var rawMoveVector = GetRawMoveVector();
    301.       if (Mathf.Approximately(rawMoveVector.x, 0.0f) && Mathf.Approximately(rawMoveVector.y, 0.0f))
    302.       {
    303.         m_ConsecutiveMoveCount = 0;
    304.         return false;
    305.       }
    306.       var flag1 = input.GetButtonDown(m_HorizontalAxis) || input.GetButtonDown(m_VerticalAxis);
    307.       var flag2 = Vector2.Dot(rawMoveVector, m_LastMoveVector) > 0.0;
    308.       if (!flag1)
    309.         flag1 = !flag2 || m_ConsecutiveMoveCount != 1 ? unscaledTime > m_PrevActionTime + 1.0 / m_InputActionsPerSecond : unscaledTime > m_PrevActionTime + (double) m_RepeatDelay;
    310.       if (!flag1)
    311.         return false;
    312.       var axisEventData = GetAxisEventData(rawMoveVector.x, rawMoveVector.y, 0.6f);
    313.       if (axisEventData.moveDir != MoveDirection.None)
    314.       {
    315.         ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, axisEventData, ExecuteEvents.moveHandler);
    316.         if (!flag2)
    317.           m_ConsecutiveMoveCount = 0;
    318.         ++m_ConsecutiveMoveCount;
    319.         m_PrevActionTime = unscaledTime;
    320.         m_LastMoveVector = rawMoveVector;
    321.       }
    322.       else
    323.         m_ConsecutiveMoveCount = 0;
    324.       return axisEventData.used;
    325.     }
    326.  
    327.     private void ProcessMouseEvent() => ProcessMouseEvent(0);
    328.  
    329.     [Obsolete("This method is no longer checked, overriding it with return true does nothing!")]
    330.     private bool ForceAutoSelect() => false;
    331.  
    332.     private void ProcessMouseEvent(int id)
    333.     {
    334.       var pointerEventData = GetMousePointerEventData(id);
    335.       var eventData = pointerEventData.GetButtonState(PointerEventData.InputButton.Left).eventData;
    336.       m_CurrentFocusedGameObject = eventData.buttonData.pointerCurrentRaycast.gameObject;
    337.       ProcessMousePress(eventData);
    338.       ProcessMove(eventData.buttonData);
    339.       ProcessDrag(eventData.buttonData);
    340.       ProcessMousePress(pointerEventData.GetButtonState(PointerEventData.InputButton.Right).eventData);
    341.       ProcessDrag(pointerEventData.GetButtonState(PointerEventData.InputButton.Right).eventData.buttonData);
    342.       ProcessMousePress(pointerEventData.GetButtonState(PointerEventData.InputButton.Middle).eventData);
    343.       ProcessDrag(pointerEventData.GetButtonState(PointerEventData.InputButton.Middle).eventData.buttonData);
    344.       if (Mathf.Approximately(eventData.buttonData.scrollDelta.sqrMagnitude, 0.0f))
    345.         return;
    346.       ExecuteEvents.ExecuteHierarchy(ExecuteEvents.GetEventHandler<IScrollHandler>(eventData.buttonData.pointerCurrentRaycast.gameObject), eventData.buttonData, ExecuteEvents.scrollHandler);
    347.     }
    348.  
    349.     private bool SendUpdateEventToSelectedObject()
    350.     {
    351.       if (eventSystem.currentSelectedGameObject == null)
    352.         return false;
    353.       var baseEventData = GetBaseEventData();
    354.       ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, baseEventData, ExecuteEvents.updateSelectedHandler);
    355.       return baseEventData.used;
    356.     }
    357.  
    358.     private void ProcessMousePress(MouseButtonEventData data)
    359.     {
    360.       var buttonData = data.buttonData;
    361.       var gameObject1 = buttonData.pointerCurrentRaycast.gameObject;
    362.       if (data.PressedThisFrame())
    363.       {
    364.         buttonData.eligibleForClick = true;
    365.         buttonData.delta = Vector2.zero;
    366.         buttonData.dragging = false;
    367.         buttonData.useDragThreshold = true;
    368.         buttonData.pressPosition = buttonData.position;
    369.         buttonData.pointerPressRaycast = buttonData.pointerCurrentRaycast;
    370.         DeselectIfSelectionChanged(gameObject1, buttonData);
    371.         var gameObject2 = ExecuteEvents.ExecuteHierarchy(gameObject1, buttonData, ExecuteEvents.pointerDownHandler);
    372.         if (gameObject2 == null)
    373.           gameObject2 = ExecuteEvents.GetEventHandler<IPointerClickHandler>(gameObject1);
    374.         var unscaledTime = Time.unscaledTime;
    375.         if (gameObject2 == buttonData.lastPress)
    376.         {
    377.           if (unscaledTime - buttonData.clickTime < 0.300000011920929)
    378.             ++buttonData.clickCount;
    379.           else
    380.             buttonData.clickCount = 1;
    381.           buttonData.clickTime = unscaledTime;
    382.         }
    383.         else
    384.           buttonData.clickCount = 1;
    385.         buttonData.pointerPress = gameObject2;
    386.         buttonData.rawPointerPress = gameObject1;
    387.         buttonData.clickTime = unscaledTime;
    388.         buttonData.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(gameObject1);
    389.         if (buttonData.pointerDrag != null)
    390.           ExecuteEvents.Execute(buttonData.pointerDrag, buttonData, ExecuteEvents.initializePotentialDrag);
    391.         m_InputPointerEvent = buttonData;
    392.       }
    393.       if (!data.ReleasedThisFrame())
    394.         return;
    395.       ExecuteEvents.Execute(buttonData.pointerPress, buttonData, ExecuteEvents.pointerUpHandler);
    396.       var eventHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(gameObject1);
    397.       if (buttonData.pointerPress == eventHandler && buttonData.eligibleForClick)
    398.         ExecuteEvents.Execute(buttonData.pointerPress, buttonData, ExecuteEvents.pointerClickHandler);
    399.       else if (buttonData.pointerDrag != null && buttonData.dragging)
    400.         ExecuteEvents.ExecuteHierarchy(gameObject1, buttonData, ExecuteEvents.dropHandler);
    401.       buttonData.eligibleForClick = false;
    402.       buttonData.pointerPress = null;
    403.       buttonData.rawPointerPress = null;
    404.       if (buttonData.pointerDrag != null && buttonData.dragging)
    405.         ExecuteEvents.Execute(buttonData.pointerDrag, buttonData, ExecuteEvents.endDragHandler);
    406.       buttonData.dragging = false;
    407.       buttonData.pointerDrag = null;
    408.       if (gameObject1 != buttonData.pointerEnter)
    409.       {
    410.         HandlePointerExitAndEnter(buttonData, null);
    411.         HandlePointerExitAndEnter(buttonData, gameObject1);
    412.       }
    413.       m_InputPointerEvent = buttonData;
    414.     }
    415.  
    416.     private GameObject GetCurrentFocusedGameObject() => m_CurrentFocusedGameObject;
    417.  
    418.     [Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
    419.     public enum InputMode
    420.     {
    421.       Mouse,
    422.       Buttons,
    423.     }
    424.   }