No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TimelineGroupGUI.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.IMGUI.Controls;
  5. using UnityEngine;
  6. using UnityEngine.Timeline;
  7. namespace UnityEditor.Timeline
  8. {
  9. class TimelineGroupGUI : TimelineTrackBaseGUI
  10. {
  11. protected DirectorStyles m_Styles;
  12. protected Rect m_TreeViewRect = new Rect(0, 0, 0, 0);
  13. protected GUIContent m_ProblemIcon = new GUIContent();
  14. bool m_MustRecomputeUnions = true;
  15. int m_GroupDepth;
  16. readonly bool m_IsReferencedTrack;
  17. readonly List<TimelineClipUnion> m_Unions = new List<TimelineClipUnion>();
  18. public override Rect boundingRect
  19. {
  20. get { return ToWindowSpace(m_TreeViewRect); }
  21. }
  22. public Rect ToWindowSpace(Rect localRect)
  23. {
  24. localRect.position += treeViewToWindowTransformation;
  25. return localRect;
  26. }
  27. public override bool expandable
  28. {
  29. get { return !m_IsRoot; }
  30. }
  31. // The expanded rectangle (contains children) as calculated by the the tree gui
  32. public Rect expandedRect { get; set; }
  33. // The row rectangle (header only) as calculated by the tree gui
  34. public Rect rowRect { get; set; }
  35. // the drop rectangle as set by the tree gui when targetted by a drag and drop
  36. public Rect dropRect { get; set; }
  37. public TimelineGroupGUI(TreeViewController treeview, TimelineTreeViewGUI treeviewGUI, int id, int depth, TreeViewItem parent, string displayName, TrackAsset trackAsset, bool isRoot)
  38. : base(id, depth, parent, displayName, trackAsset, treeview, treeviewGUI)
  39. {
  40. m_Styles = DirectorStyles.Instance;
  41. m_IsRoot = isRoot;
  42. var trackPath = AssetDatabase.GetAssetPath(trackAsset);
  43. var sequencePath = AssetDatabase.GetAssetPath(treeviewGUI.TimelineWindow.state.editSequence.asset);
  44. if (trackPath != sequencePath)
  45. m_IsReferencedTrack = true;
  46. m_GroupDepth = CalculateGroupDepth(parent);
  47. }
  48. public virtual float GetHeight(WindowState state)
  49. {
  50. // group tracks don't scale in height
  51. return TrackEditor.DefaultTrackHeight;
  52. }
  53. public override void OnGraphRebuilt() { }
  54. static int CalculateGroupDepth(TreeViewItem parent)
  55. {
  56. int depth = 0;
  57. bool done = false;
  58. do
  59. {
  60. var gui = parent as TimelineGroupGUI;
  61. if (gui == null || gui.track == null)
  62. done = true;
  63. else
  64. {
  65. if (gui.track is GroupTrack)
  66. depth++;
  67. parent = parent.parent;
  68. }
  69. }
  70. while (!done);
  71. return depth;
  72. }
  73. void DrawTrackButtons(Rect headerRect, WindowState state)
  74. {
  75. const float buttonSize = WindowConstants.trackHeaderButtonSize;
  76. const float padding = WindowConstants.trackHeaderButtonPadding;
  77. var buttonRect = new Rect(headerRect.xMax - buttonSize - padding, headerRect.y + ((headerRect.height - buttonSize) / 2f), buttonSize, buttonSize);
  78. if (GUI.Button(buttonRect, EditorGUIUtility.IconContent("CreateAddNew"), m_Styles.trackGroupAddButton))
  79. {
  80. // the drop down will apply to all selected tracks
  81. if (!SelectionManager.Contains(track))
  82. {
  83. SelectionManager.Clear();
  84. SelectionManager.Add(track);
  85. }
  86. SequencerContextMenu.ShowNewTracksContextMenu(SelectionManager.SelectedTracks().ToArray(), TimelineWindow.state, buttonRect);
  87. }
  88. buttonRect.x -= buttonSize;
  89. var suitePadding = DrawButtonSuite(2, ref buttonRect);
  90. DrawMuteButton(buttonRect, state);
  91. buttonRect.x -= buttonSize + padding;
  92. DrawLockButton(buttonRect, state);
  93. buttonRect.x -= suitePadding;
  94. }
  95. public void SetExpanded(bool expanded)
  96. {
  97. var collapseChanged = expanded != isExpanded;
  98. isExpanded = expanded;
  99. if (collapseChanged)
  100. {
  101. track.SetCollapsed(!expanded);
  102. m_MustRecomputeUnions = true;
  103. }
  104. }
  105. public override void Draw(Rect headerRect, Rect contentRect, WindowState state)
  106. {
  107. if (track == null || m_IsRoot)
  108. return;
  109. if (m_MustRecomputeUnions)
  110. RecomputeRectUnions();
  111. if (depth == 1)
  112. Graphics.DrawBackgroundRect(state, headerRect);
  113. var background = headerRect;
  114. background.height = expandedRect.height;
  115. var groupColor = TrackResourceCache.GetTrackColor(track);
  116. m_TreeViewRect = contentRect;
  117. var col = groupColor;
  118. var isSelected = SelectionManager.Contains(track);
  119. if (isSelected)
  120. col = DirectorStyles.Instance.customSkin.colorSelection;
  121. else if (isDropTarget)
  122. col = DirectorStyles.Instance.customSkin.colorDropTarget;
  123. else
  124. {
  125. if (m_GroupDepth % 2 == 1)
  126. {
  127. float h, s, v;
  128. Color.RGBToHSV(col, out h, out s, out v);
  129. v += 0.06f;
  130. col = Color.HSVToRGB(h, s, v);
  131. }
  132. }
  133. if (background.width > 0)
  134. {
  135. using (new GUIColorOverride(col))
  136. GUI.Box(background, GUIContent.none, m_Styles.groupBackground);
  137. }
  138. var trackRectBackground = headerRect;
  139. trackRectBackground.xMin += background.width;
  140. trackRectBackground.width = contentRect.width;
  141. trackRectBackground.height = background.height;
  142. if (isSelected)
  143. {
  144. col = state.IsEditingASubTimeline()
  145. ? m_Styles.customSkin.colorTrackSubSequenceBackgroundSelected
  146. : m_Styles.customSkin.colorTrackBackgroundSelected;
  147. }
  148. else
  149. {
  150. col = m_Styles.customSkin.colorGroupTrackBackground;
  151. }
  152. EditorGUI.DrawRect(trackRectBackground, col);
  153. if (!isExpanded && children != null && children.Count > 0)
  154. {
  155. var collapsedTrackRect = contentRect;
  156. foreach (var u in m_Unions)
  157. u.Draw(collapsedTrackRect, state);
  158. }
  159. using (new GUIGroupScope(headerRect))
  160. {
  161. var groupRect = new Rect(0, 0, headerRect.width, headerRect.height);
  162. DrawName(groupRect, isSelected);
  163. DrawTrackButtons(groupRect, state);
  164. }
  165. if (IsTrackRecording(state))
  166. {
  167. using (new GUIColorOverride(DirectorStyles.Instance.customSkin.colorTrackBackgroundRecording))
  168. GUI.Label(background, GUIContent.none, m_Styles.displayBackground);
  169. }
  170. // is this a referenced track?
  171. if (m_IsReferencedTrack)
  172. {
  173. var refRect = contentRect;
  174. refRect.x = state.timeAreaRect.xMax - 20.0f;
  175. refRect.y += 5.0f;
  176. refRect.width = 30.0f;
  177. GUI.Label(refRect, DirectorStyles.referenceTrackLabel, EditorStyles.label);
  178. }
  179. var bgRect = contentRect;
  180. if (track as GroupTrack != null || AllChildrenMuted(this))
  181. bgRect.height = expandedRect.height;
  182. DrawTrackState(contentRect, bgRect, track);
  183. }
  184. void DrawName(Rect rect, bool isSelected)
  185. {
  186. var labelRect = rect;
  187. labelRect.xMin += 20;
  188. var actorName = track != null ? track.name : "missing";
  189. labelRect.width = m_Styles.groupFont.CalcSize(new GUIContent(actorName)).x;
  190. labelRect.width = Math.Max(labelRect.width, 50.0f);
  191. // if we aren't bound to anything, we show a text field that allows to rename the actor
  192. // otherwise we show a ObjectField to allow binding to a go
  193. if (track != null && track is GroupTrack)
  194. {
  195. var textColor = m_Styles.groupFont.normal.textColor;
  196. if (isSelected)
  197. textColor = Color.white;
  198. string newName;
  199. EditorGUI.BeginChangeCheck();
  200. using (new StyleNormalColorOverride(m_Styles.groupFont, textColor))
  201. {
  202. newName = EditorGUI.DelayedTextField(labelRect, GUIContent.none, track.GetInstanceID(), track.name, m_Styles.groupFont);
  203. }
  204. if (EditorGUI.EndChangeCheck() && !string.IsNullOrEmpty(newName))
  205. {
  206. track.SetNameWithUndo(newName);
  207. displayName = track.name;
  208. }
  209. }
  210. }
  211. protected bool IsSubTrack()
  212. {
  213. if (track == null)
  214. return false;
  215. var parentTrack = track.parent as TrackAsset;
  216. if (parentTrack == null)
  217. return false;
  218. return parentTrack.GetType() != typeof(GroupTrack);
  219. }
  220. protected TrackAsset ParentTrack()
  221. {
  222. if (IsSubTrack())
  223. return track.parent as TrackAsset;
  224. return null;
  225. }
  226. // is there currently a recording track
  227. bool IsTrackRecording(WindowState state)
  228. {
  229. if (!state.recording)
  230. return false;
  231. if (track.GetType() != typeof(GroupTrack))
  232. return false;
  233. return state.GetArmedTrack(track) != null;
  234. }
  235. void RecomputeRectUnions()
  236. {
  237. m_MustRecomputeUnions = false;
  238. m_Unions.Clear();
  239. if (children == null)
  240. return;
  241. foreach (var c in children.OfType<TimelineTrackGUI>())
  242. {
  243. c.RebuildGUICacheIfNecessary();
  244. m_Unions.AddRange(TimelineClipUnion.Build(c.clips));
  245. }
  246. }
  247. static bool AllChildrenMuted(TimelineGroupGUI groupGui)
  248. {
  249. if (!groupGui.track.muted)
  250. return false;
  251. if (groupGui.children == null)
  252. return true;
  253. return groupGui.children.OfType<TimelineGroupGUI>().All(AllChildrenMuted);
  254. }
  255. protected static float DrawButtonSuite(int numberOfButtons, ref Rect buttonRect)
  256. {
  257. var style = DirectorStyles.Instance.trackButtonSuite;
  258. var buttonWidth = WindowConstants.trackHeaderButtonSize * numberOfButtons + WindowConstants.trackHeaderButtonPadding * Math.Max(0, numberOfButtons - 1);
  259. var suiteWidth = buttonWidth + style.padding.right + style.padding.left;
  260. var rect = new Rect(buttonRect.xMax - style.margin.right - suiteWidth, buttonRect.y + style.margin.top, suiteWidth, buttonRect.height);
  261. if (Event.current.type == EventType.Repaint)
  262. style.Draw(rect, false, false, false, false);
  263. buttonRect.x -= style.margin.right + style.padding.right;
  264. return style.margin.left + style.padding.left;
  265. }
  266. }
  267. }