using System.Collections; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; [RequireComponent(typeof(CanvasGroup))] public class UIElementDragger : MonoBehaviour, IDragHandler, IEndDragHandler, IPointerDownHandler, IPointerUpHandler { public bool LockSize; [ShowIf("LockSize", false)] public Vector2 SizeMin = new Vector2(100, 100), SizeMax = new Vector2(1920, 1080); //Prevent the element for being attached or detached from a toolbar public bool LockProxyState; public string ProxyName; public UIDraggableProxy Proxy; public UIToolbar.ElementType ElementType; public GameObject HandlePosition, HandleSize; private Vector2 mouseOffset; private float currentScale = 1; private float sizeWhenClicked; private Vector2 savedMousePos; private bool _awake; private CanvasGroup _canvasGroup; public DragAction LastDragAction; public enum DragAction { None, Position, Scale, Size } private void Awake() { if (_awake) return; _awake = true; _canvasGroup = GetComponent(); if (LockSize) { HandleSize.SetActive(false); } } private void Start() { if (Proxy == null) { transform.position = RecalculatePosition(transform.position); } } public void SetProxyMode(UIDraggableProxy proxy) { Awake(); OnEndDrag(null); Proxy = proxy; if (proxy != null) { transform.position = proxy.GetComponent().position; HandlePosition.gameObject.SetActive(false); } else { gameObject.SetActive(true); HandlePosition.gameObject.SetActive(true); } } public void ProxySetVisible(bool visible) { if (!visible) { gameObject.SetActive(false); } else { var canvas = ModelViewerInterface.GetInstance().MainCanvas; var proxyRect = Proxy.transform as RectTransform; var handleRect = HandlePosition.transform as RectTransform; var handleOffset = handleRect.sizeDelta.y * canvas.scaleFactor * Vector3.up; if (Proxy.GetComponentInParent().Layout == UIToolbar.LayoutMode.Vertical) { //anchor to top-right of button transform.position = proxyRect.position + proxyRect.sizeDelta.x * canvas.scaleFactor * Vector3.right + handleOffset; } else { //anchor to bottom-left of button transform.position = proxyRect.position + proxyRect.sizeDelta.y * canvas.scaleFactor * Vector3.up - handleOffset; } gameObject.SetActive(true); } } public void OnDrag(PointerEventData eventData) { var rectTsf = transform as RectTransform; var canvas = ModelViewerInterface.GetInstance().MainCanvas; switch (LastDragAction) { case DragAction.Scale: { currentScale = Mathf.Clamp((Input.mousePosition.x - savedMousePos.x) / Screen.width + sizeWhenClicked, 0.5f, 1); transform.localScale = Vector3.one * currentScale; break; } case DragAction.Size: { var mousePos = (Vector2)Input.mousePosition; mousePos.y = -(Screen.height - mousePos.y); //convert anchor from bottom-left to top-left var sizeDelta = mousePos / canvas.scaleFactor - (Vector2)rectTsf.anchoredPosition; sizeDelta.x = Mathf.Clamp(sizeDelta.x, SizeMin.x, Mathf.Min(Screen.width / canvas.scaleFactor, SizeMax.x)); sizeDelta.y = Mathf.Clamp(-sizeDelta.y, SizeMin.y, Mathf.Min(Screen.height / canvas.scaleFactor, SizeMax.y)); if (currentScale > 0) { sizeDelta *= currentScale; } rectTsf.sizeDelta = sizeDelta; break; } case DragAction.Position: { transform.position = RecalculatePosition((Vector2)Input.mousePosition + mouseOffset); break; } } } public void OnEndDrag(PointerEventData eventData) { _canvasGroup.blocksRaycasts = true; } private void OnDestroy() { if(Proxy != null) { Destroy(Proxy.gameObject); } } public void OnPointerDown(PointerEventData eventData) { eventData.pointerDrag = this.gameObject; _canvasGroup.blocksRaycasts = false; if (eventData.button == PointerEventData.InputButton.Right) { LastDragAction = DragAction.Scale; ModelViewerMain.GetInstance().GetCamera().LightLock = true; savedMousePos = Input.mousePosition; sizeWhenClicked = currentScale; transform.SetAsLastSibling(); } else if (eventData.hovered.Contains(HandlePosition)) { LastDragAction = DragAction.Position; mouseOffset = transform.position - Input.mousePosition; transform.SetAsLastSibling(); } else if (eventData.hovered.Contains(HandleSize)) { LastDragAction = DragAction.Size; mouseOffset = transform.position - Input.mousePosition; } else { LastDragAction = DragAction.None; _canvasGroup.blocksRaycasts = true; eventData.pointerDrag = null; } } public void OnPointerUp(PointerEventData eventData) { OnEndDrag(null); } public Vector2 RecalculatePosition(Vector2 pos) { var handle = HandlePosition.transform as RectTransform; var tsf = transform as RectTransform; var canvas = ModelViewerInterface.GetInstance().MainCanvas; var xPos = Mathf.Clamp(pos.x, 0, Screen.width - tsf.sizeDelta.x * canvas.scaleFactor); var yPos = Mathf.Clamp(pos.y, handle.sizeDelta.y * canvas.scaleFactor, Screen.height); return new Vector2 (xPos, yPos); } }