TimelineClipUnion.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEditorInternal;
  4. using UnityEngine;
  5. namespace UnityEditor.Timeline
  6. {
  7. class TimelineClipUnion
  8. {
  9. List<TimelineClipGUI> m_Members = new List<TimelineClipGUI>();
  10. Rect m_BoundingRect;
  11. Rect m_Union;
  12. double m_Start;
  13. double m_Duration;
  14. bool m_InitUnionRect = true;
  15. void Add(TimelineClipGUI clip)
  16. {
  17. m_Members.Add(clip);
  18. if (m_Members.Count == 1)
  19. {
  20. m_BoundingRect = clip.clippedRect;
  21. }
  22. else
  23. {
  24. m_BoundingRect = Encompass(m_BoundingRect, clip.rect);
  25. }
  26. }
  27. public void Draw(Rect parentRect, WindowState state)
  28. {
  29. if (m_InitUnionRect)
  30. {
  31. m_Start = m_Members.OrderBy(c => c.clip.start).First().clip.start;
  32. m_Duration = m_Members.Sum(c => c.clip.duration);
  33. m_InitUnionRect = false;
  34. }
  35. m_Union = new Rect((float)(m_Start) * state.timeAreaScale.x, 0, (float)m_Duration * state.timeAreaScale.x, 0);
  36. // transform clipRect into pixel-space
  37. m_Union.xMin += state.timeAreaTranslation.x + parentRect.x;
  38. m_Union.xMax += state.timeAreaTranslation.x + parentRect.x;
  39. m_Union.y = parentRect.y + 4.0f;
  40. m_Union.height = parentRect.height - 8.0f;
  41. // calculate clipped rect
  42. if (m_Union.x < parentRect.xMin)
  43. {
  44. var overflow = parentRect.xMin - m_Union.x;
  45. m_Union.x = parentRect.xMin;
  46. m_Union.width -= overflow;
  47. }
  48. // bail out if completely clipped
  49. if (m_Union.xMax < parentRect.xMin)
  50. return;
  51. if (m_Union.xMin > parentRect.xMax)
  52. return;
  53. EditorGUI.DrawRect(m_Union, DirectorStyles.Instance.customSkin.colorClipUnion);
  54. }
  55. public static List<TimelineClipUnion> Build(List<TimelineClipGUI> clips)
  56. {
  57. var unions = new List<TimelineClipUnion>();
  58. if (clips == null)
  59. return unions;
  60. TimelineClipUnion currentUnion = null;
  61. foreach (var c in clips)
  62. {
  63. if (currentUnion == null)
  64. {
  65. currentUnion = new TimelineClipUnion();
  66. currentUnion.Add(c);
  67. unions.Add(currentUnion);
  68. }
  69. else
  70. {
  71. Rect result;
  72. if (Intersection(c.rect, currentUnion.m_BoundingRect, out result))
  73. {
  74. currentUnion.Add(c);
  75. }
  76. else
  77. {
  78. currentUnion = new TimelineClipUnion();
  79. currentUnion.Add(c);
  80. unions.Add(currentUnion);
  81. }
  82. }
  83. }
  84. return unions;
  85. }
  86. public static Rect Encompass(Rect a, Rect b)
  87. {
  88. Rect newRect = a;
  89. newRect.xMin = Mathf.Min(a.xMin, b.xMin);
  90. newRect.yMin = Mathf.Min(a.yMin, b.yMin);
  91. newRect.xMax = Mathf.Max(a.xMax, b.xMax);
  92. newRect.yMax = Mathf.Max(a.yMax, b.yMax);
  93. return newRect;
  94. }
  95. public static bool Intersection(Rect r1, Rect r2, out Rect intersection)
  96. {
  97. if (!r1.Overlaps(r2) && !r2.Overlaps(r1))
  98. {
  99. intersection = new Rect(0, 0, 0, 0);
  100. return false;
  101. }
  102. float left = Mathf.Max(r1.xMin, r2.xMin);
  103. float top = Mathf.Max(r1.yMin, r2.yMin);
  104. float right = Mathf.Min(r1.xMax, r2.xMax);
  105. float bottom = Mathf.Min(r1.yMax, r2.yMax);
  106. intersection = new Rect(left, top, right - left, bottom - top);
  107. return true;
  108. }
  109. }
  110. }