RectangleTool.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System;
  2. using UnityEngine;
  3. namespace UnityEditor.Timeline
  4. {
  5. abstract class RectangleTool
  6. {
  7. struct TimelinePoint
  8. {
  9. readonly double m_Time;
  10. readonly float m_YPos;
  11. readonly float m_YScrollPos;
  12. readonly WindowState m_State;
  13. readonly TimelineTreeViewGUI m_TreeViewGUI;
  14. public TimelinePoint(WindowState state, Vector2 mousePosition)
  15. {
  16. m_State = state;
  17. m_TreeViewGUI = state.GetWindow().treeView;
  18. m_Time = m_State.PixelToTime(mousePosition.x);
  19. m_YPos = mousePosition.y;
  20. m_YScrollPos = m_TreeViewGUI.scrollPosition.y;
  21. }
  22. public Vector2 ToPixel()
  23. {
  24. return new Vector2(m_State.TimeToPixel(m_Time), m_YPos - (m_TreeViewGUI.scrollPosition.y - m_YScrollPos));
  25. }
  26. }
  27. TimeAreaAutoPanner m_TimeAreaAutoPanner;
  28. TimelinePoint m_StartPoint;
  29. Vector2 m_EndPixel = Vector2.zero;
  30. Rect m_ActiveRect;
  31. protected abstract bool enableAutoPan { get; }
  32. protected abstract bool CanStartRectangle(Event evt, Vector2 mousePosition, WindowState state);
  33. protected abstract bool OnFinish(Event evt, WindowState state, Rect rect);
  34. int m_Id;
  35. public void OnGUI(WindowState state, EventType rawType, Vector2 mousePosition)
  36. {
  37. if (m_Id == 0)
  38. m_Id = GUIUtility.GetPermanentControlID();
  39. if (state == null || state.GetWindow().treeView == null)
  40. return;
  41. var evt = Event.current;
  42. if (rawType == EventType.MouseDown || evt.type == EventType.MouseDown)
  43. {
  44. if (state.IsCurrentEditingASequencerTextField())
  45. return;
  46. m_ActiveRect = TimelineWindow.instance.sequenceContentRect;
  47. if (!m_ActiveRect.Contains(mousePosition))
  48. return;
  49. if (!CanStartRectangle(evt, mousePosition, state))
  50. return;
  51. if (enableAutoPan)
  52. m_TimeAreaAutoPanner = new TimeAreaAutoPanner(state);
  53. m_StartPoint = new TimelinePoint(state, mousePosition);
  54. m_EndPixel = mousePosition;
  55. GUIUtility.hotControl = m_Id; //HACK: Because the treeView eats all the events, steal the hotControl if necessary...
  56. evt.Use();
  57. return;
  58. }
  59. switch (evt.GetTypeForControl(m_Id))
  60. {
  61. case EventType.KeyDown:
  62. {
  63. if (GUIUtility.hotControl == m_Id)
  64. {
  65. if (evt.keyCode == KeyCode.Escape)
  66. {
  67. m_TimeAreaAutoPanner = null;
  68. GUIUtility.hotControl = 0;
  69. evt.Use();
  70. }
  71. }
  72. return;
  73. }
  74. case EventType.MouseDrag:
  75. {
  76. if (GUIUtility.hotControl != m_Id)
  77. return;
  78. m_EndPixel = mousePosition;
  79. evt.Use();
  80. return;
  81. }
  82. case EventType.MouseUp:
  83. {
  84. if (GUIUtility.hotControl != m_Id)
  85. return;
  86. m_TimeAreaAutoPanner = null;
  87. var rect = CurrentRectangle();
  88. if (IsValidRect(rect))
  89. OnFinish(evt, state, rect);
  90. GUIUtility.hotControl = 0;
  91. evt.Use();
  92. return;
  93. }
  94. }
  95. if (GUIUtility.hotControl == m_Id)
  96. {
  97. if (evt.type == EventType.Repaint)
  98. {
  99. var r = CurrentRectangle();
  100. if (IsValidRect(r))
  101. {
  102. using (new GUIViewportScope(m_ActiveRect))
  103. {
  104. DrawRectangle(r);
  105. }
  106. }
  107. }
  108. if (m_TimeAreaAutoPanner != null)
  109. m_TimeAreaAutoPanner.OnGUI(evt);
  110. }
  111. }
  112. protected virtual void DrawRectangle(Rect rect)
  113. {
  114. EditorStyles.selectionRect.Draw(rect, GUIContent.none, false, false, false, false);
  115. }
  116. static bool IsValidRect(Rect rect)
  117. {
  118. return rect.width >= 1.0f && rect.height >= 1.0f;
  119. }
  120. Rect CurrentRectangle()
  121. {
  122. var startPixel = m_StartPoint.ToPixel();
  123. return Rect.MinMaxRect(
  124. Math.Min(startPixel.x, m_EndPixel.x),
  125. Math.Min(startPixel.y, m_EndPixel.y),
  126. Math.Max(startPixel.x, m_EndPixel.x),
  127. Math.Max(startPixel.y, m_EndPixel.y));
  128. }
  129. }
  130. }