127 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using UnityEditorInternal;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace UnityEditor.Timeline
 | |
| {
 | |
|     class TimelineClipUnion
 | |
|     {
 | |
|         List<TimelineClipGUI> m_Members = new List<TimelineClipGUI>();
 | |
|         Rect m_BoundingRect;
 | |
|         Rect m_Union;
 | |
|         double m_Start;
 | |
|         double m_Duration;
 | |
|         bool m_InitUnionRect = true;
 | |
| 
 | |
|         void Add(TimelineClipGUI clip)
 | |
|         {
 | |
|             m_Members.Add(clip);
 | |
|             if (m_Members.Count == 1)
 | |
|             {
 | |
|                 m_BoundingRect = clip.clippedRect;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 m_BoundingRect = Encompass(m_BoundingRect, clip.rect);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void Draw(Rect parentRect, WindowState state)
 | |
|         {
 | |
|             if (m_InitUnionRect)
 | |
|             {
 | |
|                 m_Start = m_Members.OrderBy(c => c.clip.start).First().clip.start;
 | |
|                 m_Duration = m_Members.Sum(c => c.clip.duration);
 | |
|                 m_InitUnionRect = false;
 | |
|             }
 | |
| 
 | |
|             m_Union = new Rect((float)(m_Start) * state.timeAreaScale.x, 0, (float)m_Duration * state.timeAreaScale.x, 0);
 | |
| 
 | |
|             // transform clipRect into pixel-space
 | |
|             m_Union.xMin += state.timeAreaTranslation.x + parentRect.x;
 | |
|             m_Union.xMax += state.timeAreaTranslation.x + parentRect.x;
 | |
|             m_Union.y = parentRect.y + 4.0f;
 | |
|             m_Union.height = parentRect.height - 8.0f;
 | |
| 
 | |
|             // calculate clipped rect
 | |
|             if (m_Union.x < parentRect.xMin)
 | |
|             {
 | |
|                 var overflow = parentRect.xMin - m_Union.x;
 | |
|                 m_Union.x = parentRect.xMin;
 | |
|                 m_Union.width -= overflow;
 | |
|             }
 | |
| 
 | |
|             // bail out if completely clipped
 | |
|             if (m_Union.xMax < parentRect.xMin)
 | |
|                 return;
 | |
|             if (m_Union.xMin > parentRect.xMax)
 | |
|                 return;
 | |
| 
 | |
|             EditorGUI.DrawRect(m_Union, DirectorStyles.Instance.customSkin.colorClipUnion);
 | |
|         }
 | |
| 
 | |
|         public static List<TimelineClipUnion> Build(List<TimelineClipGUI> clips)
 | |
|         {
 | |
|             var unions = new List<TimelineClipUnion>();
 | |
|             if (clips == null)
 | |
|                 return unions;
 | |
| 
 | |
|             TimelineClipUnion currentUnion = null;
 | |
|             foreach (var c in clips)
 | |
|             {
 | |
|                 if (currentUnion == null)
 | |
|                 {
 | |
|                     currentUnion = new TimelineClipUnion();
 | |
|                     currentUnion.Add(c);
 | |
|                     unions.Add(currentUnion);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     Rect result;
 | |
|                     if (Intersection(c.rect, currentUnion.m_BoundingRect, out result))
 | |
|                     {
 | |
|                         currentUnion.Add(c);
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         currentUnion = new TimelineClipUnion();
 | |
|                         currentUnion.Add(c);
 | |
|                         unions.Add(currentUnion);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return unions;
 | |
|         }
 | |
| 
 | |
|         public static Rect Encompass(Rect a, Rect b)
 | |
|         {
 | |
|             Rect newRect = a;
 | |
|             newRect.xMin = Mathf.Min(a.xMin, b.xMin);
 | |
|             newRect.yMin = Mathf.Min(a.yMin, b.yMin);
 | |
|             newRect.xMax = Mathf.Max(a.xMax, b.xMax);
 | |
|             newRect.yMax = Mathf.Max(a.yMax, b.yMax);
 | |
|             return newRect;
 | |
|         }
 | |
| 
 | |
|         public static bool Intersection(Rect r1, Rect r2, out Rect intersection)
 | |
|         {
 | |
|             if (!r1.Overlaps(r2) && !r2.Overlaps(r1))
 | |
|             {
 | |
|                 intersection = new Rect(0, 0, 0, 0);
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             float left = Mathf.Max(r1.xMin, r2.xMin);
 | |
|             float top = Mathf.Max(r1.yMin, r2.yMin);
 | |
| 
 | |
|             float right = Mathf.Min(r1.xMax, r2.xMax);
 | |
|             float bottom = Mathf.Min(r1.yMax, r2.yMax);
 | |
| 
 | |
|             intersection = new Rect(left, top, right - left, bottom - top);
 | |
|             return true;
 | |
|         }
 | |
|     }
 | |
| }
 |