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

Removing unreferencable manipulators

Discussion in 'UI Toolkit' started by MorZUB, Dec 24, 2020.

  1. MorZUB

    MorZUB

    Joined:
    Dec 21, 2020
    Posts:
    2
    So I've been running into a really frustrating problem.
    I'm working with some custom types that inherit some built-in UI Toolkit types, specifically the Edge class from the GraphViewEditor (https://github.com/Unity-Technologi...1761/Modules/GraphViewEditor/Elements/Edge.cs)

    I want to extend the basic edge to add extra functionality that I need, but I also want to disable the ability to drag it out of a port.
    The port dragging functionality is provided by the EdgeManipulator that is added to the Edge in its constructor with
    Code (CSharp):
    1. this.AddManipulator(new EdgeManipulator());
    The problem is that this doesn't keep a reference to the created manipulator, and there doesn't seem to be a way to remove a manipulator without a direct reference to it.

    Is there a way to strip all manipulators of a specific type from an element? Or alternatively, just strip ALL manipulators from an element altogether?
    Looking at the base Manipulator class (https://github.com/Unity-Technologi...Sources/com.unity.ui/Core/Manipulators.cs#L19) It seems like there wouldn't be any way to do something as simple as this, and that just seems like a huge oversight.
     
    Ghat-Smith likes this.
  2. MorZUB

    MorZUB

    Joined:
    Dec 21, 2020
    Posts:
    2
    Not exactly the solution I wanted, but I managed to find a hack that works.

    Intercepting the mouse movement event and disabling its further propagation will prevent it from reaching the EdgeManipulator, and thus disable the port dragging.
    The caveat is that any other functionality that relies on the mouse move event is also disabled unless explicitly forwarded from this hack. Which is not pretty.

    The code for anyone interested:
    Code (CSharp):
    1.  
    2.     public override void HandleEvent(EventBase evt)
    3.     {
    4.         if (evt is MouseMoveEvent)
    5.         {
    6.             evt.StopImmediatePropagation();
    7.         }
    8.         else
    9.         {
    10.             base.HandleEvent(evt);
    11.         }
    12.     }
     
    Ghat-Smith likes this.
  3. Ghat-Smith

    Ghat-Smith

    Joined:
    Aug 16, 2016
    Posts:
    48
    Up.

    I too think this is an important basic feature that is missing.
    In my case I wanted to remove a manipulator automatically added to GraphView by Unity, but it seems impossible as I don't have any reference to this manipulator.
    We really need a way to get all manipulators associated to a given VisualElement.
     
    FizzFab likes this.
  4. jakob-leitner

    jakob-leitner

    Joined:
    Nov 11, 2020
    Posts:
    16
  5. steve_ioconic

    steve_ioconic

    Joined:
    Feb 17, 2023
    Posts:
    2
  6. unity_D4A6C01F3EBB83613B4D

    unity_D4A6C01F3EBB83613B4D

    Joined:
    Oct 19, 2022
    Posts:
    9
  7. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,112
    +1

    My current "solution" for my own manipulators.

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine;
    5. using UnityEngine.UIElements;
    6.  
    7. namespace YourNamespace
    8. {
    9.     public abstract class ManipulatorBase<T> : Manipulator
    10.         where T : ManipulatorBase<T>
    11.     {
    12.         /// <summary>
    13.         /// All manipulators that are linked to an element AND whose 'target' element is currently attached to a panel.
    14.         /// </summary>
    15.         public static List<T> ActiveManipulators = new List<T>();
    16.  
    17.         public event Action<T> OnRegisterCallbacksOnTarget;
    18.         public event Action<T> OnUnregisterCallbacksOnTarget;
    19.  
    20.         public event Action<T, AttachToPanelEvent> OnElementAttachToPanel;
    21.         public event Action<T, DetachFromPanelEvent> OnElementDetachFromPanel;
    22.  
    23.         protected override void RegisterCallbacksOnTarget()
    24.         {
    25.             addToManipulators();
    26.  
    27.             target.UnregisterCallback<AttachToPanelEvent>(onAttach);
    28.             target.RegisterCallback<AttachToPanelEvent>(onAttach);
    29.  
    30.             target.UnregisterCallback<DetachFromPanelEvent>(onDetached);
    31.             target.RegisterCallback<DetachFromPanelEvent>(onDetached);
    32.  
    33.             OnRegisterCallbacksOnTarget?.Invoke((T)this);
    34.         }
    35.  
    36.         protected virtual void onAttach(AttachToPanelEvent evt)
    37.         {
    38.             addToManipulators();
    39.             OnElementAttachToPanel?.Invoke((T)this, evt);
    40.         }
    41.  
    42.         protected virtual void onDetached(DetachFromPanelEvent evt)
    43.         {
    44.             removeFromManipulators();
    45.             OnElementDetachFromPanel?.Invoke((T)this, evt);
    46.         }
    47.  
    48.         protected override void UnregisterCallbacksFromTarget()
    49.         {
    50.             target.UnregisterCallback<AttachToPanelEvent>(onAttach);
    51.             target.UnregisterCallback<DetachFromPanelEvent>(onDetached);
    52.  
    53.             removeFromManipulators();
    54.  
    55.             OnUnregisterCallbacksOnTarget?.Invoke((T)this);
    56.         }
    57.  
    58.         protected void addToManipulators()
    59.         {
    60.             if (!ActiveManipulators.Contains((T)this))
    61.             {
    62.                 ActiveManipulators.Add((T)this);
    63.             }
    64.         }
    65.  
    66.         protected void removeFromManipulators()
    67.         {
    68.             if (ActiveManipulators.Contains((T)this))
    69.             {
    70.                 ActiveManipulators.Remove((T)this);
    71.             }
    72.         }
    73.  
    74.         public static T GetManipulatorOnElement(VisualElement element)
    75.         {
    76.             foreach (var m in ActiveManipulators)
    77.             {
    78.                 if (m != null && m.target != null && m.target == element)
    79.                     return m;
    80.             }
    81.  
    82.             return null;
    83.         }
    84.     }
    85. }
     
    Last edited: Sep 22, 2023