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

Resolved Drag Drop Visual Element and Keep initial mouse position Offset

Discussion in 'UI Toolkit' started by toomasio, Jun 21, 2022.

  1. toomasio

    toomasio

    Joined:
    Nov 19, 2013
    Posts:
    198
    Hello,

    I am having a tough time figuring out the math for this.
    This is what I have testing so far thanks to @Yecats.

    Code (CSharp):
    1. private void StartDrag(PointerDownEvent evt)
    2.     {
    3.         dragging = true;
    4.  
    5.         //Set the new position
    6.         background.style.top = evt.position.y - background.layout.height / 2;
    7.         background.style.left = evt.position.x - background.layout.width / 2;
    8.         Debug.Log(evt.position);
    9.     }
    10.  
    11.     private void MoveDrag(PointerMoveEvent evt)
    12.     {
    13.         if (!dragging) return;
    14.  
    15.         //Set the new position
    16.         background.style.top = evt.position.y - background.layout.height / 2;
    17.         background.style.left = evt.position.x - background.layout.width / 2;
    18.     }
    19.  
    20.     private void StopDrag(PointerUpEvent evt)
    21.     {
    22.         dragging = false;
    23.     }
    The issue is, my elements always snap to the center of the mouse position. How do I keep the initial offset on the start of the drag?

    Thanks,

    EDIT:

    Solved. You can grab the world positions of the visual elements to get the offsets. ez pz

    Code (CSharp):
    1. private void StartDrag(PointerDownEvent evt)
    2.     {
    3.         dragging = true;
    4.  
    5.         //Set the new position
    6.         offset = background.worldTransform.GetPosition() - evt.position;
    7.     }
    8.  
    9.     private void MoveDrag(PointerMoveEvent evt)
    10.     {
    11.         if (!dragging) return;
    12.  
    13.         //Set the new position
    14.         background.style.top = evt.position.y + offset.y;
    15.         background.style.left = evt.position.x + offset.x;
    16.     }
    17.  
    18.     private void StopDrag(PointerUpEvent evt)
    19.     {
    20.         dragging = false;
    21.     }
    EDIT 2 : This is another way of handling the mouse positions and offsets...dumping here for future use. I plan on using this for DOTS so I do not want to use event handlers.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UIElements;
    3.  
    4. public class DragTest : MonoBehaviour
    5. {
    6.     [SerializeField] private UIDocument doc;
    7.     [SerializeField] private string visualElementToPick;
    8.     [SerializeField] private string visualElementToDrag;
    9.  
    10.     private VisualElement pickingElement;
    11.     private VisualElement draggingElement;
    12.     private VisualElement root;
    13.  
    14.     private bool dragging;
    15.     private Vector3 offset;
    16.  
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.         root = doc.rootVisualElement;
    21.         pickingElement = root.Q<VisualElement>(visualElementToPick);
    22.         draggingElement = root.Q<VisualElement>(visualElementToDrag);
    23.         pickingElement.RegisterCallback<PointerDownEvent>(StartDrag);
    24.     }
    25.  
    26.     private void OnDestroy()
    27.     {
    28.         draggingElement.UnregisterCallback<PointerDownEvent>(StartDrag);
    29.     }
    30.  
    31.     private void LateUpdate()
    32.     {
    33.         var mousePos = Input.mousePosition;
    34.         var mousePosScreen = new Vector3(mousePos.x, Screen.height - mousePos.y, 0);
    35.  
    36.         // can possibly use this for basic picking to bypass event handlers
    37.         if (pickingElement.worldBound.Contains(mousePosScreen))
    38.         {
    39.             Debug.Log("hit");
    40.         }
    41.  
    42.         if (!dragging) return;
    43.         // set position
    44.         draggingElement.style.left = mousePosScreen.x + offset.x;
    45.         draggingElement.style.top = mousePosScreen.y + offset.y;
    46.      
    47.      
    48.         if (Input.GetMouseButtonUp(0))
    49.             dragging = false;
    50.     }
    51.  
    52.     private void StartDrag(PointerDownEvent evt)
    53.     {
    54.         dragging = true;
    55.  
    56.         // get offset
    57.         offset = draggingElement.worldTransform.GetPosition() - evt.position;
    58.     }
    59.  
    60. }
     
    Last edited: Jun 22, 2022
    Xelnath likes this.