UIWindowBase.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /// Credit GXMark, alexzzzz, CaoMengde777, TroyDavis
  2. /// Original Sourced from (GXMark) - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-1834806 (with corrections)
  3. /// Scaling fixed for non overlay canvases (alexzzzz) - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/#post-1780612
  4. /// Canvas border fix (CaoMengde777) - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/#post-1781658
  5. /// Canvas reset position fix (TroyDavis)- http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/#post-1782214
  6. using System;
  7. using UnityEngine.EventSystems;
  8. namespace UnityEngine.UI.Extensions
  9. {
  10. /// <summary>
  11. /// Includes a few fixes of my own, mainly to tidy up duplicates, remove unneeded stuff and testing. (nothing major, all the crew above did the hard work!)
  12. /// </summary>
  13. [RequireComponent(typeof(RectTransform))]
  14. [AddComponentMenu("UI/Extensions/UI Window Base")]
  15. public class UIWindowBase : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
  16. {
  17. private bool _isDragging = false;
  18. public static bool ResetCoords = false;
  19. private Vector3 m_originalCoods = Vector3.zero;
  20. private Canvas m_canvas;
  21. private RectTransform m_canvasRectTransform;
  22. [Tooltip("Number of pixels of the window that must stay inside the canvas view.")]
  23. public int KeepWindowInCanvas = 5;
  24. [Tooltip("The transform that is moved when dragging, can be left empty in which case its own transform is used.")]
  25. public RectTransform RootTransform = null;
  26. // Use this for initialization
  27. void Start()
  28. {
  29. if (RootTransform == null)
  30. {
  31. RootTransform = GetComponent<RectTransform>();
  32. }
  33. m_originalCoods = RootTransform.position;
  34. m_canvas = GetComponentInParent<Canvas>();
  35. m_canvasRectTransform = m_canvas.GetComponent<RectTransform>();
  36. }
  37. void Update()
  38. {
  39. if (ResetCoords)
  40. resetCoordinatePosition();
  41. }
  42. public void OnDrag(PointerEventData eventData) {
  43. if (eventData.button != PointerEventData.InputButton.Left) return;
  44. if (_isDragging) {
  45. var delta = ScreenToCanvas(eventData.position) - ScreenToCanvas(eventData.position - eventData.delta);
  46. RootTransform.localPosition += delta;
  47. }
  48. }
  49. public void OnBeginDrag(PointerEventData eventData) {
  50. if (eventData.button != PointerEventData.InputButton.Left) return;
  51. _isDragging = true;
  52. /*
  53. * 不知道为啥,这个事件有延迟的,如果你鼠标动太快移动出去了,原本的修复会导致你拖不动
  54. //Note, the begin drag and end drag aren't actually needed to control the drag. However, I'd recommend keeping it in case you want to do something else when dragging starts and stops
  55. Debug.Log(eventData.pointerCurrentRaycast.gameObject == null ? "null" : eventData.pointerCurrentRaycast.gameObject.name);
  56. if (eventData.pointerCurrentRaycast.gameObject == null) return;
  57. if (eventData.pointerCurrentRaycast.gameObject.name == name) _isDragging = true;
  58. */
  59. }
  60. public void OnEndDrag(PointerEventData eventData) {
  61. if (eventData.button != PointerEventData.InputButton.Left) return;
  62. _isDragging = false;
  63. }
  64. void resetCoordinatePosition()
  65. {
  66. RootTransform.position = m_originalCoods;
  67. ResetCoords = false;
  68. }
  69. private Vector3 ScreenToCanvas(Vector3 screenPosition)
  70. {
  71. Vector3 localPosition;
  72. Vector2 min;
  73. Vector2 max;
  74. var canvasSize = m_canvasRectTransform.sizeDelta;
  75. if (m_canvas.renderMode == RenderMode.ScreenSpaceOverlay || (m_canvas.renderMode == RenderMode.ScreenSpaceCamera && m_canvas.worldCamera == null))
  76. {
  77. localPosition = screenPosition;
  78. min = Vector2.zero;
  79. max = canvasSize;
  80. }
  81. else
  82. {
  83. var ray = m_canvas.worldCamera.ScreenPointToRay(screenPosition);
  84. var plane = new Plane(m_canvasRectTransform.forward, m_canvasRectTransform.position);
  85. float distance;
  86. if (plane.Raycast(ray, out distance) == false)
  87. {
  88. throw new Exception("Is it practically possible?");
  89. };
  90. var worldPosition = ray.origin + ray.direction * distance;
  91. localPosition = m_canvasRectTransform.InverseTransformPoint(worldPosition);
  92. min = -Vector2.Scale(canvasSize, m_canvasRectTransform.pivot);
  93. max = Vector2.Scale(canvasSize, Vector2.one - m_canvasRectTransform.pivot);
  94. }
  95. // keep window inside canvas
  96. localPosition.x = Mathf.Clamp(localPosition.x, min.x + KeepWindowInCanvas, max.x - KeepWindowInCanvas);
  97. localPosition.y = Mathf.Clamp(localPosition.y, min.y + KeepWindowInCanvas, max.y - KeepWindowInCanvas);
  98. return localPosition;
  99. }
  100. }
  101. }