Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

global pointer events?

Discussion in 'UGUI & TextMesh Pro' started by smootler, Dec 4, 2014.

  1. smootler

    smootler

    Joined:
    Aug 3, 2014
    Posts:
    19
    Is there an easy way to access global pointer events in the new UI eventsystem? Basically the items shown at runtime in the inspector for the EventSystem (pointer id, position, pointerEnter, pointerPress, lastPointerPress, pointerDrag).

    It seems like it should be easy since they are shown in the inspector but I can't find any way to access PointerEventData in a global way (only by implementing interfaces like IPointerClickHandler, etc. on a specific gameobject).

    Basically I'm trying to create a context menu that destroys itself if you click anywhere outside the context menu. This seemed like the best way to do it but if there is another way I should be approaching this I'm open to suggestions.
     
  2. smootler

    smootler

    Joined:
    Aug 3, 2014
    Posts:
    19
    I found a suitable function in PointerInputModule: GetLastPointerEventData which returns a PointerEventData. However, it is protected so I can't call it. Is there any way around this?
     
  3. holyjewsus

    holyjewsus

    Joined:
    Mar 7, 2011
    Posts:
    624
    reflection?
     
  4. smootler

    smootler

    Joined:
    Aug 3, 2014
    Posts:
    19
    If anyone else cares, I solved this by creating my own input module that inherits from StandaloneInputModule and has a public wrapper function for GetLastPointerEventData
     
  5. VMS_Lab

    VMS_Lab

    Joined:
    Dec 31, 2013
    Posts:
    3
    I am trying to do the same thing. I'm very interested in hearing more about your solution. Any chance you could go into further detail?
     
  6. smootler

    smootler

    Joined:
    Aug 3, 2014
    Posts:
    19
    Yeah, in case others need it, in a script on the object you need to have destroy itself:

    Code (CSharp):
    1.     public void Update()
    2.     {
    3.         if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
    4.         {
    5.             PointerEventData mouse1 = EventSystem.current.gameObject.GetComponent<StandaloneInputModuleCustom>().GetLastPointerEventDataPublic(-1);
    6.             //if pointerPress is null (it was either a mouse2 click or it was outside any gui), or if pointerPress doesn't have my context menu component.
    7.             if (mouse1.pointerPress == null || !mouse1.pointerPress.GetComponent<ContextMenuItemUI>())
    8.             {
    9.                 Destroy(this.gameObject);
    10.             }
    11.         }
    12.     }
    new StandaloneInputModuleCustom (make sure to attach this script to your EventSystem object in the scene, and remove the standard StandaloneInputModule):

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4. using UnityEngine.EventSystems;
    5.  
    6. public class StandaloneInputModuleCustom : StandaloneInputModule {
    7.  
    8.     public PointerEventData GetLastPointerEventDataPublic (int id)
    9.     {
    10.         return GetLastPointerEventData(id);
    11.     }
    12. }
    13.  
    And then on the button itself I have it destroy its context menu container when it's clicked so the context menu goes away when you select an option:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.EventSystems;
    4.  
    5. public class ContextMenuItemUI : MonoBehaviour, IPointerUpHandler {
    6.  
    7.     public ContextMenuUI parentMenu;
    8.  
    9.     public void OnPointerUp (PointerEventData eventData)
    10.     {
    11.         StartCoroutine(DestroyOnNextFrame());
    12.     }
    13.     public IEnumerator DestroyOnNextFrame()
    14.     {
    15.         yield return null;
    16.         Destroy(parentMenu.gameObject);
    17.         yield break;
    18.     }
    19. }
    20.  
     
    spamove, astracat111, dyupa and 2 others like this.
  7. rustofelees

    rustofelees

    Joined:
    Apr 22, 2013
    Posts:
    26
    Hello,

    I'm currently trying to take a left click mouse down event and disable it for a frame, and then reenable it the next (without the user having to click the mouse button again. It seems like this code may help with my cause, but I can't quite determine how I can make this happen. I tried your code, but PointerEventData mouse1 always ends up being null even though I click on another UI element. Is this to be expected?
     
  8. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    725
    @smootler WOW! This right here...I didn't know you could actually expose Unity protected methods like that!