Search Unity

Unity UI Custom UI Cursor Position and UI-Interaction

Discussion in 'UGUI & TextMesh Pro' started by Refzlund, Mar 7, 2019.

  1. Refzlund

    Refzlund

    Joined:
    Oct 15, 2016
    Posts:
    11
    Hey everyone!

    I have made a simple script to simulate the cursor for the player in an RPG-styled game. The reason being the system cursors position cannot be changed:
    I needed the camera to orbit the player when holding down a mousebutton. When doing so, I wanted the cursor to go invisible and stay in place, so when the mousebutton was released, the cursor would be at the position the player left it in.​

    I achieved this with
    Code (CSharp):
    1. public class PlayerCursor : MonoBehaviour {
    2.     public Texture2D cursor;
    3.  
    4.     [HideInInspector] public Vector2 cursorPosition;
    5.     [HideInInspector] public static bool visible = true;
    6.     private void Start () {
    7.         Cursor.lockState = CursorLockMode.Locked;
    8.         cursorPosition = Input.mousePosition;
    9.     }
    10.  
    11.     private void Update () {
    12.         if (Cursor.lockState == CursorLockMode.Locked) {
    13.             if (visible)
    14.                 cursorPosition += new Vector2 (Input.GetAxisRaw ("Mouse X") * 20, -Input.GetAxisRaw ("Mouse Y") * 20);
    15.         } else
    16.             ShowCursor (false);
    17.     }
    18.  
    19.     public void ShowCursor (bool show) {
    20.         visible = show;
    21.     }
    22.  
    23.     private void OnGUI () {
    24.         if (cursorPosition.x < 0)
    25.             cursorPosition = new Vector2 (0, cursorPosition.y);
    26.         if (cursorPosition.x > Screen.width)
    27.             cursorPosition = new Vector2 (Screen.width, cursorPosition.y);
    28.         if (cursorPosition.y < 0)
    29.             cursorPosition = new Vector2 (cursorPosition.x, 0);
    30.         if (cursorPosition.y > Screen.height)
    31.             cursorPosition = new Vector2 (cursorPosition.x, Screen.height);
    32.         if (visible)
    33.             GUI.DrawTexture (new Rect (cursorPosition.x, cursorPosition.y, 35, 35), cursor, ScaleMode.ScaleAndCrop, true, 0);
    34.     }
    35. }
    Unfortunately, this "fake" cursor cannot interact with the UI elements. Now the question remains — Is it possible to create an object which has the function as the mouse cursor in terms of the interaction with the UI?

    Note: I am using the new UI system. The OnGUI is ONLY for the purpose of rendering the cursor.

    OBS: Keep in mind, that I have the exact same Vector2 positions as if we were to get Input.mousePosition.

    Thank you for your time.

    Best regards,
    Arthur Refslund
     
    moatdd and luvjungle like this.
  2. Refzlund

    Refzlund

    Joined:
    Oct 15, 2016
    Posts:
    11
    Waow, okay. So after researching this for a few hours, I've solved the issue. This may contains bugs, but for now it works. And I'll leave it if anyone has a need of this for whatever reason.

    My approach is super lazy and can most likely be done more efficiently. I just didn't bother reinventing the wheel.

    When EventSystem is created by Unity, it also has a StandaloneInputModule.cs script. This script contains the mouse interaction. The GitHub link can be found here: https://github.com/tenpn/unity3d-ui/tree/master/UnityEngine.UI/EventSystem/InputModules

    I copied everything from StandaloneInputModule into my own little "CustomInputModule". I pasted my own code in there. The main use of my own code is the mouse position called mousePos.

    I replaced all instances of "Input.mousePosition" with "mousePos", since I have that.

    The script starts at void Process(), goes over to void ProcessMouseEvent(). The first line here mouseData =
    GetMousePointerEventData (); includes "Input.mousePosition", so I went to one of the other scripts in GitHub and copy/pasta'd it into my own script. It will show a warning, but nevermind that. Again, replacing Input.mousePosition with mousePos.

    Back to ProcessMouseEvent() we have "ProcessMove" and "ProcessDrag". For some reason these didn't change the "pointerEnter" toolbox in the bottom left of the Inspector:
    upload_2019-3-7_19-7-19.png

    I literally went ahead and found these function in one of the other scripts. Copied into my own and changed the function name to "_ProcessMove". Dragging didn't work either, so I did the same thing with "ProcessDrag", and voilá - The custom mouse now thinks it's the real thing. I kind of feel sorry for it.

    Here's my code:
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Text;
    5. using UnityEngine;
    6. using UnityEngine.EventSystems;
    7. public class CustomInputModule : PointerInputModule {
    8.     private float m_NextAction;
    9.  
    10.     private Vector2 m_LastMousePosition;
    11.     private Vector2 m_MousePosition;
    12.  
    13.     protected CustomInputModule () { }
    14.  
    15.     [Obsolete ("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
    16.     public enum InputMode {
    17.         Mouse,
    18.         Buttons
    19.     }
    20.  
    21.     [Obsolete ("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
    22.     public InputMode inputMode {
    23.         get { return InputMode.Mouse; }
    24.     }
    25.  
    26.     [SerializeField]
    27.     private string m_HorizontalAxis = "Horizontal";
    28.  
    29.     /// <summary>
    30.     /// Name of the vertical axis for movement (if axis events are used).
    31.     /// </summary>
    32.     [SerializeField]
    33.     private string m_VerticalAxis = "Vertical";
    34.  
    35.     /// <summary>
    36.     /// Name of the submit button.
    37.     /// </summary>
    38.     [SerializeField]
    39.     private string m_SubmitButton = "Submit";
    40.  
    41.     /// <summary>
    42.     /// Name of the submit button.
    43.     /// </summary>
    44.     [SerializeField]
    45.     private string m_CancelButton = "Cancel";
    46.  
    47.     [SerializeField]
    48.     private float m_InputActionsPerSecond = 10;
    49.  
    50.     [SerializeField]
    51.     private bool m_AllowActivationOnMobileDevice;
    52.  
    53.     public bool allowActivationOnMobileDevice {
    54.         get { return m_AllowActivationOnMobileDevice; }
    55.         set { m_AllowActivationOnMobileDevice = value; }
    56.     }
    57.  
    58.     public float inputActionsPerSecond {
    59.         get { return m_InputActionsPerSecond; }
    60.         set { m_InputActionsPerSecond = value; }
    61.     }
    62.  
    63.     /// <summary>
    64.     /// Name of the horizontal axis for movement (if axis events are used).
    65.     /// </summary>
    66.     public string horizontalAxis {
    67.         get { return m_HorizontalAxis; }
    68.         set { m_HorizontalAxis = value; }
    69.     }
    70.  
    71.     /// <summary>
    72.     /// Name of the vertical axis for movement (if axis events are used).
    73.     /// </summary>
    74.     public string verticalAxis {
    75.         get { return m_VerticalAxis; }
    76.         set { m_VerticalAxis = value; }
    77.     }
    78.  
    79.     public string submitButton {
    80.         get { return m_SubmitButton; }
    81.         set { m_SubmitButton = value; }
    82.     }
    83.  
    84.     public string cancelButton {
    85.         get { return m_CancelButton; }
    86.         set { m_CancelButton = value; }
    87.     }
    88.  
    89.     public Texture2D cursor;
    90.     [HideInInspector] public Vector2 cursorPosition;
    91.     public Vector2 mousePos;
    92.     [HideInInspector] public static bool visible = true;
    93.     protected override void Start () {
    94.         Cursor.lockState = CursorLockMode.Locked;
    95.     }
    96.  
    97.     private void Update () {
    98.         if (Cursor.lockState == CursorLockMode.Locked) {
    99.             if (visible) {
    100.                 cursorPosition += new Vector2 (Input.GetAxisRaw ("Mouse X") * 20, -Input.GetAxisRaw ("Mouse Y") * 20);
    101.                 mousePos = new Vector2 (cursorPosition.x, (cursorPosition.y - Screen.height) * -1);
    102.             }
    103.         } else
    104.             ShowCursor (false);
    105.     }
    106.  
    107.     public void ShowCursor (bool show) {
    108.         visible = show;
    109.     }
    110.  
    111.     private void OnGUI () {
    112.         if (cursorPosition.x < 0)
    113.             cursorPosition = new Vector2 (0, cursorPosition.y);
    114.         if (cursorPosition.x > Screen.width)
    115.             cursorPosition = new Vector2 (Screen.width, cursorPosition.y);
    116.         if (cursorPosition.y < 0)
    117.             cursorPosition = new Vector2 (cursorPosition.x, 0);
    118.         if (cursorPosition.y > Screen.height)
    119.             cursorPosition = new Vector2 (cursorPosition.x, Screen.height);
    120.         if (visible)
    121.             GUI.DrawTexture (new Rect (cursorPosition.x, cursorPosition.y, 35, 35), cursor, ScaleMode.ScaleAndCrop, true, 0);
    122.     }
    123.  
    124.     public override void UpdateModule () {
    125.         m_LastMousePosition = m_MousePosition;
    126.         m_MousePosition = new Vector2 (cursorPosition.x, (cursorPosition.y - Screen.height) * -1);
    127.     }
    128.  
    129.     public override bool IsModuleSupported () {
    130.         // Check for mouse presence instead of whether touch is supported,
    131.         // as you can connect mouse to a tablet and in that case we'd want
    132.         // to use StandaloneInputModule for non-touch input events.
    133.         return m_AllowActivationOnMobileDevice || Input.mousePresent;
    134.     }
    135.  
    136.     public override bool ShouldActivateModule () {
    137.         if (!base.ShouldActivateModule ())
    138.             return false;
    139.  
    140.         var shouldActivate = Input.GetButtonDown (m_SubmitButton);
    141.         shouldActivate |= Input.GetButtonDown (m_CancelButton);
    142.         shouldActivate |= !Mathf.Approximately (Input.GetAxisRaw (m_HorizontalAxis), 0.0f);
    143.         shouldActivate |= !Mathf.Approximately (Input.GetAxisRaw (m_VerticalAxis), 0.0f);
    144.         shouldActivate |= (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0f;
    145.         shouldActivate |= Input.GetMouseButtonDown (0);
    146.         return shouldActivate;
    147.     }
    148.  
    149.     public override void ActivateModule () {
    150.         base.ActivateModule ();
    151.         m_MousePosition = mousePos;
    152.         m_LastMousePosition = mousePos;
    153.  
    154.         var toSelect = eventSystem.currentSelectedGameObject;
    155.         if (toSelect == null)
    156.             toSelect = eventSystem.lastSelectedGameObject;
    157.         if (toSelect == null)
    158.             toSelect = eventSystem.firstSelectedGameObject;
    159.  
    160.         eventSystem.SetSelectedGameObject (toSelect, GetBaseEventData ());
    161.     }
    162.  
    163.     public override void DeactivateModule () {
    164.         base.DeactivateModule ();
    165.         ClearSelection ();
    166.     }
    167.  
    168.     public override void Process () {
    169.         bool usedEvent = SendUpdateEventToSelectedObject ();
    170.  
    171.         if (eventSystem.sendNavigationEvents) {
    172.             if (!usedEvent)
    173.                 usedEvent |= SendMoveEventToSelectedObject ();
    174.  
    175.             if (!usedEvent)
    176.                 SendSubmitEventToSelectedObject ();
    177.         }
    178.  
    179.         ProcessMouseEvent ();
    180.     }
    181.  
    182.     /// <summary>
    183.     /// Process submit keys.
    184.     /// </summary>
    185.     private bool SendSubmitEventToSelectedObject () {
    186.         if (eventSystem.currentSelectedGameObject == null)
    187.             return false;
    188.  
    189.         var data = GetBaseEventData ();
    190.         if (Input.GetButtonDown (m_SubmitButton))
    191.             ExecuteEvents.Execute (eventSystem.currentSelectedGameObject, data, ExecuteEvents.submitHandler);
    192.  
    193.         if (Input.GetButtonDown (m_CancelButton))
    194.             ExecuteEvents.Execute (eventSystem.currentSelectedGameObject, data, ExecuteEvents.cancelHandler);
    195.         return data.used;
    196.     }
    197.  
    198.     private bool AllowMoveEventProcessing (float time) {
    199.         bool allow = Input.GetButtonDown (m_HorizontalAxis);
    200.         allow |= Input.GetButtonDown (m_VerticalAxis);
    201.         allow |= (time > m_NextAction);
    202.         return allow;
    203.     }
    204.  
    205.     private Vector2 GetRawMoveVector () {
    206.         Vector2 move = Vector2.zero;
    207.         move.x = Input.GetAxisRaw (m_HorizontalAxis);
    208.         move.y = Input.GetAxisRaw (m_VerticalAxis);
    209.         print (move.x);
    210.  
    211.         if (Input.GetButtonDown (m_HorizontalAxis)) {
    212.             if (move.x < 0)
    213.                 move.x = -1f;
    214.             if (move.x > 0)
    215.                 move.x = 1f;
    216.         }
    217.         if (Input.GetButtonDown (m_VerticalAxis)) {
    218.             if (move.y < 0)
    219.                 move.y = -1f;
    220.             if (move.y > 0)
    221.                 move.y = 1f;
    222.         }
    223.         return move;
    224.     }
    225.  
    226.     /// <summary>
    227.     /// Process keyboard events.
    228.     /// </summary>
    229.     private bool SendMoveEventToSelectedObject () {
    230.         float time = Time.unscaledTime;
    231.  
    232.         if (!AllowMoveEventProcessing (time))
    233.             return false;
    234.  
    235.         Vector2 movement = GetRawMoveVector ();
    236.         // Debug.Log(m_ProcessingEvent.rawType + " axis:" + m_AllowAxisEvents + " value:" + "(" + x + "," + y + ")");
    237.         var axisEventData = GetAxisEventData (movement.x, movement.y, 0.6f);
    238.         if (!Mathf.Approximately (axisEventData.moveVector.x, 0f) ||
    239.             !Mathf.Approximately (axisEventData.moveVector.y, 0f)) {
    240.             ExecuteEvents.Execute (eventSystem.currentSelectedGameObject, axisEventData, ExecuteEvents.moveHandler);
    241.         }
    242.         m_NextAction = time + 1f / m_InputActionsPerSecond;
    243.         return axisEventData.used;
    244.     }
    245.  
    246.     public const int kMouseLeftId = -1;
    247.     public const int kMouseRightId = -2;
    248.     public const int kMouseMiddleId = -3;
    249.  
    250.     private readonly MouseState m_MouseState = new MouseState ();
    251.     protected virtual MouseState GetMousePointerEventData () {
    252.         // Populate the left button...
    253.         PointerEventData leftData;
    254.         var created = GetPointerData (kMouseLeftId, out leftData, true);
    255.  
    256.         leftData.Reset ();
    257.  
    258.         if (created)
    259.             leftData.position = m_MousePosition;
    260.  
    261.         Vector2 pos = m_MousePosition;
    262.         leftData.delta = pos - leftData.position;
    263.         leftData.position = pos;
    264.         leftData.scrollDelta = Input.mouseScrollDelta;
    265.         leftData.button = PointerEventData.InputButton.Left;
    266.         eventSystem.RaycastAll (leftData, m_RaycastResultCache);
    267.         var raycast = FindFirstRaycast (m_RaycastResultCache);
    268.  
    269.         leftData.pointerCurrentRaycast = raycast;
    270.         m_RaycastResultCache.Clear ();
    271.  
    272.         // copy the apropriate data into right and middle slots
    273.         PointerEventData rightData;
    274.         GetPointerData (kMouseRightId, out rightData, true);
    275.         CopyFromTo (leftData, rightData);
    276.         rightData.button = PointerEventData.InputButton.Right;
    277.  
    278.         PointerEventData middleData;
    279.         GetPointerData (kMouseMiddleId, out middleData, true);
    280.         CopyFromTo (leftData, middleData);
    281.         middleData.button = PointerEventData.InputButton.Middle;
    282.  
    283.         m_MouseState.SetButtonState (PointerEventData.InputButton.Left, StateForMouseButton (0), leftData);
    284.         m_MouseState.SetButtonState (PointerEventData.InputButton.Right, StateForMouseButton (1), rightData);
    285.         m_MouseState.SetButtonState (PointerEventData.InputButton.Middle, StateForMouseButton (2), middleData);
    286.  
    287.         return m_MouseState;
    288.     }
    289.  
    290.     private static bool ShouldStartDrag (Vector2 pressPos, Vector2 currentPos, float threshold, bool useDragThreshold) {
    291.         if (!useDragThreshold)
    292.             return true;
    293.  
    294.         return (pressPos - currentPos).sqrMagnitude >= threshold * threshold;
    295.     }
    296.  
    297.     protected virtual void _ProcessMove (PointerEventData pointerEvent) {
    298.         var targetGO = pointerEvent.pointerCurrentRaycast.gameObject;
    299.         HandlePointerExitAndEnter (pointerEvent, targetGO);
    300.     }
    301.  
    302.     protected virtual void _ProcessDrag (PointerEventData pointerEvent) {
    303.         bool moving = pointerEvent.IsPointerMoving ();
    304.  
    305.         if (moving && pointerEvent.pointerDrag != null &&
    306.             !pointerEvent.dragging &&
    307.             ShouldStartDrag (pointerEvent.pressPosition, pointerEvent.position, eventSystem.pixelDragThreshold, pointerEvent.useDragThreshold)) {
    308.             ExecuteEvents.Execute (pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.beginDragHandler);
    309.             pointerEvent.dragging = true;
    310.         }
    311.  
    312.         // Drag notification
    313.         if (pointerEvent.dragging && moving && pointerEvent.pointerDrag != null) {
    314.             // Before doing drag we should cancel any pointer down state
    315.             // And clear selection!
    316.             if (pointerEvent.pointerPress != pointerEvent.pointerDrag) {
    317.                 ExecuteEvents.Execute (pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
    318.  
    319.                 pointerEvent.eligibleForClick = false;
    320.                 pointerEvent.pointerPress = null;
    321.                 pointerEvent.rawPointerPress = null;
    322.             }
    323.             ExecuteEvents.Execute (pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.dragHandler);
    324.         }
    325.     }
    326.  
    327.     /// <summary>
    328.     /// Process all mouse events.
    329.     /// </summary>
    330.     private void ProcessMouseEvent () {
    331.         var mouseData = GetMousePointerEventData ();
    332.  
    333.         var pressed = mouseData.AnyPressesThisFrame ();
    334.         var released = mouseData.AnyReleasesThisFrame ();
    335.  
    336.         var leftButtonData = mouseData.GetButtonState (PointerEventData.InputButton.Left).eventData;
    337.  
    338.         if (!UseMouse (pressed, released, leftButtonData.buttonData))
    339.             return;
    340.  
    341.         // Process the first mouse button fully
    342.         ProcessMousePress (leftButtonData);
    343.         print (leftButtonData.buttonData.pointerCurrentRaycast.gameObject);
    344.         _ProcessMove (leftButtonData.buttonData);
    345.         _ProcessDrag (leftButtonData.buttonData);
    346.  
    347.         // Now process right / middle clicks
    348.         ProcessMousePress (mouseData.GetButtonState (PointerEventData.InputButton.Right).eventData);
    349.         _ProcessDrag (mouseData.GetButtonState (PointerEventData.InputButton.Right).eventData.buttonData);
    350.         ProcessMousePress (mouseData.GetButtonState (PointerEventData.InputButton.Middle).eventData);
    351.         _ProcessDrag (mouseData.GetButtonState (PointerEventData.InputButton.Middle).eventData.buttonData);
    352.  
    353.         if (!Mathf.Approximately (leftButtonData.buttonData.scrollDelta.sqrMagnitude, 0.0f)) {
    354.             var scrollHandler = ExecuteEvents.GetEventHandler<IScrollHandler> (leftButtonData.buttonData.pointerCurrentRaycast.gameObject);
    355.             ExecuteEvents.ExecuteHierarchy (scrollHandler, leftButtonData.buttonData, ExecuteEvents.scrollHandler);
    356.         }
    357.  
    358.     }
    359.  
    360.     private static bool UseMouse (bool pressed, bool released, PointerEventData pointerData) {
    361.         if (pressed || released || pointerData.IsPointerMoving () || pointerData.IsScrolling ())
    362.             return true;
    363.  
    364.         return false;
    365.     }
    366.  
    367.     private bool SendUpdateEventToSelectedObject () {
    368.         if (eventSystem.currentSelectedGameObject == null)
    369.             return false;
    370.  
    371.         var data = GetBaseEventData ();
    372.         ExecuteEvents.Execute (eventSystem.currentSelectedGameObject, data, ExecuteEvents.updateSelectedHandler);
    373.         return data.used;
    374.     }
    375.  
    376.     /// <summary>
    377.     /// Process the current mouse press.
    378.     /// </summary>
    379.     private void ProcessMousePress (MouseButtonEventData data) {
    380.         var pointerEvent = data.buttonData;
    381.         var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
    382.  
    383.         // PointerDown notification
    384.         if (data.PressedThisFrame ()) {
    385.             pointerEvent.eligibleForClick = true;
    386.             pointerEvent.delta = Vector2.zero;
    387.             pointerEvent.dragging = false;
    388.             pointerEvent.useDragThreshold = true;
    389.             pointerEvent.pressPosition = pointerEvent.position;
    390.             pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
    391.  
    392.             DeselectIfSelectionChanged (currentOverGo, pointerEvent);
    393.  
    394.             // search for the control that will receive the press
    395.             // if we can't find a press handler set the press
    396.             // handler to be what would receive a click.
    397.             var newPressed = ExecuteEvents.ExecuteHierarchy (currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
    398.  
    399.             // didnt find a press handler... search for a click handler
    400.             if (newPressed == null)
    401.                 newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler> (currentOverGo);
    402.  
    403.             // Debug.Log("Pressed: " + newPressed);
    404.  
    405.             float time = Time.unscaledTime;
    406.  
    407.             if (newPressed == pointerEvent.lastPress) {
    408.                 var diffTime = time - pointerEvent.clickTime;
    409.                 if (diffTime < 0.3f)
    410.                     ++pointerEvent.clickCount;
    411.                 else
    412.                     pointerEvent.clickCount = 1;
    413.  
    414.                 pointerEvent.clickTime = time;
    415.             } else {
    416.                 pointerEvent.clickCount = 1;
    417.             }
    418.  
    419.             pointerEvent.pointerPress = newPressed;
    420.             pointerEvent.rawPointerPress = currentOverGo;
    421.  
    422.             pointerEvent.clickTime = time;
    423.  
    424.             // Save the drag handler as well
    425.             pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler> (currentOverGo);
    426.  
    427.             if (pointerEvent.pointerDrag != null)
    428.                 ExecuteEvents.Execute (pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
    429.         }
    430.  
    431.         // PointerUp notification
    432.         if (data.ReleasedThisFrame ()) {
    433.             // Debug.Log("Executing pressup on: " + pointer.pointerPress);
    434.             ExecuteEvents.Execute (pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
    435.  
    436.             // Debug.Log("KeyCode: " + pointer.eventData.keyCode);
    437.  
    438.             // see if we mouse up on the same element that we clicked on...
    439.             var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler> (currentOverGo);
    440.  
    441.             // PointerClick and Drop events
    442.             if (pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick) {
    443.                 ExecuteEvents.Execute (pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler);
    444.             } else if (pointerEvent.pointerDrag != null) {
    445.                 ExecuteEvents.ExecuteHierarchy (currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
    446.             }
    447.  
    448.             pointerEvent.eligibleForClick = false;
    449.             pointerEvent.pointerPress = null;
    450.             pointerEvent.rawPointerPress = null;
    451.  
    452.             if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
    453.                 ExecuteEvents.Execute (pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
    454.  
    455.             pointerEvent.dragging = false;
    456.             pointerEvent.pointerDrag = null;
    457.  
    458.             // redo pointer enter / exit to refresh state
    459.             // so that if we moused over somethign that ignored it before
    460.             // due to having pressed on something else
    461.             // it now gets it.
    462.             if (currentOverGo != pointerEvent.pointerEnter) {
    463.                 HandlePointerExitAndEnter (pointerEvent, null);
    464.                 HandlePointerExitAndEnter (pointerEvent, currentOverGo);
    465.             }
    466.         }
    467.     }
    468. }
    Question me not.
     

    Attached Files:

    Studiomaurer and yinyinh like this.
  3. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    245
  4. Tobs-

    Tobs-

    Joined:
    Feb 12, 2016
    Posts:
    17
    I solved this issue by sub-classing the UnityEngine.EventSystem.BaseInput class and override the property mousePosition:
    Code (CSharp):
    1. public class MyBaseInput : BaseInput
    2.     {
    3.         public Vector2 CursorPosition = Vector2.zero;
    4.  
    5.         public override Vector2 mousePosition
    6.         {
    7.             get { return this.CursorPosition; }
    8.         }
    9.     }
    Next I also sub-classed the StandaloneInputModule:
    Code (CSharp):
    1. [RequireComponent(typeof(MyBaseInput))]
    2.     public class MyInputModule : StandaloneInputModule
    3.     {
    4.         protected override void Start()
    5.         {
    6.             this.inputOverride = GetComponent<MyBaseInput>();
    7.             base.Start();
    8.         }
    9.     }
    Then add the MyInputModule to the EventSystem. You now can provide our own cursor position.

    Cheers,
    Tobs.
     
  5. yuliyF

    yuliyF

    Joined:
    Nov 15, 2012
    Posts:
    197
    Hey, guys, how can I simulate mouse click using MyInputModule?
     
  6. NikodemGrz

    NikodemGrz

    Joined:
    Mar 3, 2019
    Posts:
    9
    So here is a non jittery version (talking about dragging scrollbars etc) that works fine for me in Unity 2019.3.
    Needs to be (stress)tested though.


    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3.  
    4. public class MyInputModule : StandaloneInputModule
    5. {
    6.     public CursorLockMode CursorLockMode = CursorLockMode.Locked;
    7.  
    8.     public override void Process()
    9.     {
    10.         Cursor.lockState = CursorLockMode.None;
    11.  
    12.         base.Process();
    13.  
    14.         bool isDragging = false;
    15.         foreach (PointerEventData p in this.m_PointerData.Values)
    16.         {
    17.             if (p.dragging)
    18.             {
    19.                 isDragging = true;
    20.                 break;
    21.             }
    22.         }
    23.  
    24.         if (!isDragging)
    25.             Cursor.lockState = this.CursorLockMode;
    26.     }
    27. }
     
    BjoUnity3d likes this.
  7. yangminxing

    yangminxing

    Joined:
    Aug 10, 2022
    Posts:
    1
    Thanks for your help, it's really a good way. I could write pointer click code in MyInputModule