Search Unity

how to get mouse click position when got ContextualMenuPopulateEvent.

Discussion in 'UI Toolkit' started by wang37921, Jan 17, 2019.

  1. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    ContextualMenuPopulateEvent.localMousePosition is zero.
    any other method?
     
  2. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    o_O i access it in menu.AppendAction's callback. its information is clear before be pooled?
     
    Last edited: Jan 17, 2019
  3. etienne_phil_unity

    etienne_phil_unity

    Unity Technologies

    Joined:
    Jan 15, 2019
    Posts:
    16
  4. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    863
    ContextualMenuPopulateEvent.localMousePosition still seems to return zero. Is there a workaround for this?
     
  5. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    863
    Bump ...

    originalMousePosition and mousePosition is also zero. Basically, I am creating a node from context menu and I need to place it where I opened context menu. Unity 2019.3.0b1.
     
  6. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    (not tested, just an idea) Maybe try using a MouseDownEvent in addition to the ContextualMenu event. You can register for both and save the mouse position from the MouseDownEvent for future use by your Context.. event handler.
     
  7. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    863
    Thanks @uDamian that's a functioning work-around while I wait for a fix.
     
  8. calpolican

    calpolican

    Joined:
    Feb 2, 2015
    Posts:
    425
    I was kind of bother by this 2-year-old-bug. I wonder how many people had the same issue over this 2 years. Appreciate all the work you guys do, but you should fix this.
    I'm still a bit confuse on how to get the actual position, I'm trying to use Rect(event.mousePosition, mySize), but it gives a placement that is not accurate. Maybe a raycast to the screen position?
     
    Last edited: Jan 14, 2021
    nehvaleem likes this.
  9. FelipeWagner_WildLife

    FelipeWagner_WildLife

    Joined:
    Sep 14, 2018
    Posts:
    2
    Add a
    Vector2 localMousePosition;
    variable in your
    GraphView
    and add a
    MouseDownEvent
    callback in the constructor.

    Sample code:
    Code (CSharp):
    1.  
    2. public class MyGraphView : GraphView
    3. {
    4.     Vector2 localMousePosition;
    5.     public MyGraphView()
    6.     {
    7.         RegisterCallback<MouseDownEvent>(evt => { localMousePosition = evt.localMousePosition; });
    8.  
    9.         this.AddManipulator(new ContextualMenuManipulator(evt =>
    10.         {
    11.             evt.menu.AppendAction("Do Something",
    12.                 a => DoSomething(localMousePosition)),
    13.                 a => DropdownMenuAction.Status.Normal);
    14.         }));
    15.     }
    16. }
    17.  

    UPDATE
    If you can Drag & Zoom your GraphView use the following callback to take those in consideration:
    Code (CSharp):
    1.  
    2. RegisterCallback<MouseDownEvent>(evt =>
    3.         {
    4.             localMousePosition = (evt.localMousePosition - new Vector2(viewTransform.position.x, viewTransform.position.y)) / scale;
    5.         });
    6.  
    This solved the issue for me.
     
    Last edited: Apr 27, 2021
    romi-fauzi likes this.
  10. nehvaleem

    nehvaleem

    Joined:
    Dec 13, 2012
    Posts:
    437
    I've just encountered this. its really annoying to find something broken as this after this time.
     
  11. Kekito

    Kekito

    Joined:
    Nov 24, 2016
    Posts:
    14
    How does this issue STILL exist, not like its some trivial one
     
  12. TenaciousDan

    TenaciousDan

    Joined:
    Jul 11, 2019
    Posts:
    31
    Code (CSharp):
    1. Vector2 graphViewMousePosition = viewTransform.matrix.inverse.MultiplyPoint(evt.localMousePosition);
    This works for me. It basically takes the local position from the top left of the visible box of the graphView element, then applies the reverse translation operations that were applied to the graphView's "draggable work area". Which gives you the correct position within that area. You can use this position to place created nodes.
     
    flashframe likes this.
  13. RA_Prion_exe

    RA_Prion_exe

    Joined:
    Aug 2, 2021
    Posts:
    5
    Code (CSharp):
    1.  public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
    2.         {
    3.             {
    4.                 evt.menu.AppendAction("New Node", (a) => Debug.Log(evt.mousePosition));
    5.             }      
    6.         }
    The one above asks for the mouse position inside the lambda function executed by the menu and returns zero. But this one:

    Code (CSharp):
    1. public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
    2.         {
    3.             var pos = evt.mousePosition;
    4.             {
    5.                 evt.menu.AppendAction("New Node", (a) => Debug.Log(pos));
    6.             }      
    7.         }
    asks for the mouse position outside the lambda and returns the correct mouse position. :)

    My best guess is that inside the lambda either returns the default value or takes the menu as context for the mouse position.
     
  14. HIMMELMAX

    HIMMELMAX

    Joined:
    Aug 7, 2015
    Posts:
    1
    Here is the cleanest solution I've found. This is a 100% accurate position to place the search window as well as the node to be created.

    Code (csharp):
    1. public class MyGraphView : GraphView
    2. {
    3.     private Vector2 _mousePosition;
    4.     private MySearchWindow _searchWindow;
    5.  
    6.     public MyGraphView()
    7.     {
    8.         RegisterCallback<ContextualMenuPopulateEvent>( _ =>
    9.             // Cache the event's mouse position when right-clicking.
    10.             _mousePosition = Event.current.mousePosition
    11.         );
    12.      
    13.         if (_searchWindow == null )
    14.         {
    15.             _searchWindow = ScriptableObject.CreateInstance<MySearchWindow>();
    16.         }
    17.      
    18.         nodeCreationRequest = context =>
    19.         {
    20.             if ( Event.current != null )
    21.             {
    22.                 // Cache the mouse position if the search window was opened by right-clicking.
    23.                 // Definitely check if the Event.current is null because this can be opened by pressing the space key.
    24.                 _mousePosition = Event.current.mousePosition;
    25.             }
    26.  
    27.             SearchWindow.Open(
    28.                 // Still use the context's mouse position.
    29.                 new SearchWindowContext( context.screenMousePosition ),
    30.                 _searchWindow
    31.             );
    32.         };
    33.     }
    34.  
    35.     private Node CreateNode()
    36.     {      
    37.         Node newNode = new Node();
    38.      
    39.         // Use the Graph's contentViewContainer to convert the cached mouse event's position into local space.
    40.         var position = contentViewContainer.WorldToLocal( _mousePosition );
    41.         newNode.SetPosition( new Rect( position, Vector2.zero ) );
    42.      
    43.         AddElement( newNode );
    44.      
    45.         return newNode;
    46.     }
    47. }