123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- using System;
- using UnityEngine;
- using UnityEditor.Experimental.GraphView;
- using UnityEngine.UIElements;
- using UnityEngine.UIElements.StyleSheets;
- namespace UnityEditor.ShaderGraph.Drawing
- {
- class WindowDraggable : MouseManipulator
- {
- bool m_Active;
- WindowDockingLayout m_WindowDockingLayout;
- Vector2 m_LocalMosueOffset;
- VisualElement m_Handle;
- GraphView m_GraphView;
- public Action OnDragFinished;
- public WindowDraggable(VisualElement handle = null, VisualElement container = null)
- {
- m_Handle = handle;
- m_Active = false;
- m_WindowDockingLayout = new WindowDockingLayout();
- if (container != null)
- container.RegisterCallback<GeometryChangedEvent>(OnParentGeometryChanged);
- }
- protected override void RegisterCallbacksOnTarget()
- {
- if (m_Handle == null)
- m_Handle = target;
- m_Handle.RegisterCallback(new EventCallback<MouseDownEvent>(OnMouseDown), TrickleDownEnum.NoTrickleDown);
- m_Handle.RegisterCallback(new EventCallback<MouseMoveEvent>(OnMouseMove), TrickleDownEnum.NoTrickleDown);
- m_Handle.RegisterCallback(new EventCallback<MouseUpEvent>(OnMouseUp), TrickleDownEnum.NoTrickleDown);
- target.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
- }
- protected override void UnregisterCallbacksFromTarget()
- {
- m_Handle.UnregisterCallback(new EventCallback<MouseDownEvent>(OnMouseDown), TrickleDownEnum.NoTrickleDown);
- m_Handle.UnregisterCallback(new EventCallback<MouseMoveEvent>(OnMouseMove), TrickleDownEnum.NoTrickleDown);
- m_Handle.UnregisterCallback(new EventCallback<MouseUpEvent>(OnMouseUp), TrickleDownEnum.NoTrickleDown);
- target.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
- if (m_GraphView != null)
- m_GraphView.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
- }
- void OnMouseDown(MouseDownEvent evt)
- {
- m_Active = true;
- VisualElement parent = target.parent;
- while (parent != null && !(parent is GraphView))
- parent = parent.parent;
- m_GraphView = parent as GraphView;
- if (m_GraphView != null)
- m_GraphView.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
- // m_LocalMouseOffset is offset from the target element's (0, 0) to the
- // to the mouse position.
- m_LocalMosueOffset = m_Handle.WorldToLocal(evt.mousePosition);
- m_Handle.CaptureMouse();
- evt.StopImmediatePropagation();
- }
- void OnMouseMove(MouseMoveEvent evt)
- {
- if (m_Active)
- {
- // The mouse position of is corrected according to the offset within the target
- // element (m_LocalWorldOffset) to set the position relative to the mouse position
- // when the dragging started.
- Vector2 position = target.parent.WorldToLocal(evt.mousePosition) - m_LocalMosueOffset;
- // Make sure that the object remains in the parent window
- position.x = Mathf.Clamp(position.x, 0f, target.parent.layout.width - target.layout.width);
- position.y = Mathf.Clamp(position.y, 0f, target.parent.layout.height - target.layout.height);
- // While moving, use only the left and top position properties,
- // while keeping the others NaN to not affect layout.
- target.style.left = position.x;
- target.style.top = position.y;
- target.style.right = float.NaN;
- target.style.bottom = float.NaN;
- }
- }
- void OnMouseUp(MouseUpEvent evt)
- {
- bool emitDragFinishedEvent = m_Active;
- m_Active = false;
- if (m_Handle.HasMouseCapture())
- {
- m_Handle.ReleaseMouse();
- }
- evt.StopImmediatePropagation();
- // Recalculate which corner to dock to
- m_WindowDockingLayout.CalculateDockingCornerAndOffset(target.layout, target.parent.layout);
- m_WindowDockingLayout.ClampToParentWindow();
- // Use the docking results to figure which of left/right and top/bottom needs to be set.
- m_WindowDockingLayout.ApplyPosition(target);
- // Signal that the dragging has finished.
- if (emitDragFinishedEvent && OnDragFinished != null)
- OnDragFinished();
- }
- void OnGeometryChanged(GeometryChangedEvent geometryChangedEvent)
- {
- // Make the target clamp to the border of the window if the
- // parent window becomes too small to contain it.
- if (target.parent.layout.width < target.layout.width)
- {
- if (m_WindowDockingLayout.dockingLeft)
- {
- target.style.left = 0f;
- target.style.right = float.NaN;
- }
- else
- {
- target.style.left = float.NaN;
- target.style.right = 0f;
- }
- }
- if (target.parent.layout.height < target.layout.height)
- {
- if (m_WindowDockingLayout.dockingTop)
- {
- target.style.top = 0f;
- target.style.bottom = float.NaN;
- }
- else
- {
- target.style.top = float.NaN;
- target.style.bottom = 0f;
- }
- }
- }
- void OnParentGeometryChanged(GeometryChangedEvent geometryChangedEvent)
- {
- // Check if the parent window can no longer contain the target window.
- // If the window is out of bounds, make one edge clamp to the border of the
- // parent window.
- if (target.layout.xMin < 0f)
- {
- target.style.left = 0f;
- target.style.right = float.NaN;
- }
- if (target.layout.xMax > geometryChangedEvent.newRect.width)
- {
- target.style.left = float.NaN;
- target.style.right = 0f;
- }
- if (target.layout.yMax > geometryChangedEvent.newRect.height)
- {
- target.style.top = float.NaN;
- target.style.bottom = 0f;
- }
- if (target.layout.yMin < 0f)
- {
- target.style.top = 0f;
- target.style.bottom = float.NaN;
- }
- }
- }
- }
|