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.

TimelineAsset_CreateRemove.cs 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Timeline;
  5. using UnityEngine.Playables;
  6. using UnityEngineInternal; // for metro type extensions
  7. namespace UnityEngine.Timeline
  8. {
  9. public partial class TimelineAsset
  10. {
  11. /// <summary>
  12. /// Allows you to create a track and add it to the Timeline.
  13. /// </summary>
  14. /// <param name="type">The type of track to create. Must derive from TrackAsset.</param>
  15. /// <param name="parent">Track to parent to. This can be null.</param>
  16. /// <param name="name">Name to give the track.</param>
  17. /// <returns>The created track.</returns>
  18. /// <remarks>
  19. /// This method will throw an InvalidOperationException if the parent is not valid. The parent can be any GroupTrack, or a supported parent type of track. For example, this can be used to create override tracks in AnimationTracks.
  20. /// </remarks>
  21. public TrackAsset CreateTrack(Type type, TrackAsset parent, string name)
  22. {
  23. if (parent != null && parent.timelineAsset != this)
  24. throw new InvalidOperationException("Addtrack cannot parent to a track not in the Timeline");
  25. if (!typeof(TrackAsset).IsAssignableFrom(type))
  26. throw new InvalidOperationException("Supplied type must be a track asset");
  27. if (parent != null)
  28. {
  29. if (!TimelineCreateUtilities.ValidateParentTrack(parent, type))
  30. throw new InvalidOperationException("Cannot assign a child of type " + type.Name + " to a parent of type " + parent.GetType().Name);
  31. }
  32. var baseName = name;
  33. if (string.IsNullOrEmpty(baseName))
  34. {
  35. baseName = type.Name;
  36. #if UNITY_EDITOR
  37. baseName = UnityEditor.ObjectNames.NicifyVariableName(baseName);
  38. #endif
  39. }
  40. var trackName = baseName;
  41. if (parent != null)
  42. trackName = TimelineCreateUtilities.GenerateUniqueActorName(parent.subTracksObjects, baseName);
  43. else
  44. trackName = TimelineCreateUtilities.GenerateUniqueActorName(trackObjects, baseName);
  45. TrackAsset newTrack = AllocateTrack(parent, trackName, type);
  46. return newTrack;
  47. }
  48. /// <summary>
  49. /// Creates a track and adds it to the Timeline Asset.
  50. /// </summary>
  51. /// <param name="parent">Track to parent to. This can be null.</param>
  52. /// <param name="trackName">The name of the track being created.</param>
  53. /// <typeparam name="T">The type of track being created. The track type must be derived from TrackAsset.</typeparam>
  54. /// <returns>Returns the created track.</returns>
  55. /// <remarks>
  56. /// This method will throw an InvalidOperationException if the parent is not valid. The parent can be any GroupTrack, or a supported parent type of track. For example, this can be used to create override tracks in AnimationTracks.
  57. /// </remarks>
  58. public T CreateTrack<T>(TrackAsset parent, string trackName) where T : TrackAsset, new()
  59. {
  60. return (T)CreateTrack(typeof(T), parent, trackName);
  61. }
  62. /// <summary>
  63. /// Creates a track and adds it to the Timeline Asset.
  64. /// </summary>
  65. /// <param name="trackName">The name of the track being created.</param>
  66. /// <typeparam name="T">The type of track being created. The track type must be derived from TrackAsset.</typeparam>
  67. /// <returns>Returns the created track.</returns>
  68. public T CreateTrack<T>(string trackName) where T : TrackAsset, new()
  69. {
  70. return (T)CreateTrack(typeof(T), null, trackName);
  71. }
  72. /// <summary>
  73. /// Creates a track and adds it to the Timeline Asset.
  74. /// </summary>
  75. /// <typeparam name="T">The type of track being created. The track type must be derived from TrackAsset.</typeparam>
  76. /// <returns>Returns the created track.</returns>
  77. public T CreateTrack<T>() where T : TrackAsset, new()
  78. {
  79. return (T)CreateTrack(typeof(T), null, null);
  80. }
  81. /// <summary>
  82. /// Delete a clip from this timeline.
  83. /// </summary>
  84. /// <param name="clip">The clip to delete.</param>
  85. /// <returns>Returns true if the removal was successful</returns>
  86. /// <remarks>
  87. /// This method will delete a clip and any assets owned by the clip.
  88. /// </remarks>
  89. public bool DeleteClip(TimelineClip clip)
  90. {
  91. if (clip == null || clip.GetParentTrack() == null)
  92. {
  93. return false;
  94. }
  95. if (this != clip.GetParentTrack().timelineAsset)
  96. {
  97. Debug.LogError("Cannot delete a clip from this timeline");
  98. return false;
  99. }
  100. TimelineUndo.PushUndo(clip.GetParentTrack(), "Delete Clip");
  101. if (clip.curves != null)
  102. {
  103. TimelineUndo.PushDestroyUndo(this, clip.GetParentTrack(), clip.curves);
  104. }
  105. // handle wrapped assets
  106. if (clip.asset != null)
  107. {
  108. DeleteRecordedAnimation(clip);
  109. // TODO -- we should flag assets and owned, instead of this check...
  110. #if UNITY_EDITOR
  111. string path = UnityEditor.AssetDatabase.GetAssetPath(clip.asset);
  112. if (path == UnityEditor.AssetDatabase.GetAssetPath(this))
  113. #endif
  114. {
  115. TimelineUndo.PushDestroyUndo(this, clip.GetParentTrack(), clip.asset);
  116. }
  117. }
  118. var clipParentTrack = clip.GetParentTrack();
  119. clipParentTrack.RemoveClip(clip);
  120. clipParentTrack.CalculateExtrapolationTimes();
  121. return true;
  122. }
  123. /// <summary>
  124. /// Deletes a track from a timeline, including all clips and subtracks.
  125. /// </summary>
  126. /// <param name="track">The track to delete. It must be owned by this Timeline.</param>
  127. /// <returns>True if the track was deleted successfully.</returns>
  128. public bool DeleteTrack(TrackAsset track)
  129. {
  130. if (track.timelineAsset != this)
  131. return false;
  132. // push before we modify properties
  133. TimelineUndo.PushUndo(track, "Delete Track");
  134. TimelineUndo.PushUndo(this, "Delete Track");
  135. TrackAsset parent = track.parent as TrackAsset;
  136. if (parent != null)
  137. TimelineUndo.PushUndo(parent, "Delete Track");
  138. var children = track.GetChildTracks();
  139. foreach (var child in children)
  140. {
  141. DeleteTrack(child);
  142. }
  143. DeleteRecordedAnimation(track);
  144. var clipsToDelete = new List<TimelineClip>(track.clips);
  145. foreach (var clip in clipsToDelete)
  146. {
  147. DeleteClip(clip);
  148. }
  149. RemoveTrack(track);
  150. TimelineUndo.PushDestroyUndo(this, this, track);
  151. return true;
  152. }
  153. internal void MoveLastTrackBefore(TrackAsset asset)
  154. {
  155. if (m_Tracks == null || m_Tracks.Count < 2 || asset == null)
  156. return;
  157. var lastTrack = m_Tracks[m_Tracks.Count - 1];
  158. if (lastTrack == asset)
  159. return;
  160. for (int i = 0; i < m_Tracks.Count - 1; i++)
  161. {
  162. if (m_Tracks[i] == asset)
  163. {
  164. for (int j = m_Tracks.Count - 1; j > i; j--)
  165. m_Tracks[j] = m_Tracks[j - 1];
  166. m_Tracks[i] = lastTrack;
  167. Invalidate();
  168. break;
  169. }
  170. }
  171. }
  172. TrackAsset AllocateTrack(TrackAsset trackAssetParent, string trackName, Type trackType)
  173. {
  174. if (trackAssetParent != null && trackAssetParent.timelineAsset != this)
  175. throw new InvalidOperationException("Addtrack cannot parent to a track not in the Timeline");
  176. if (!typeof(TrackAsset).IsAssignableFrom(trackType))
  177. throw new InvalidOperationException("Supplied type must be a track asset");
  178. var asset = (TrackAsset)CreateInstance(trackType);
  179. asset.name = trackName;
  180. const string createTrackUndoName = "Create Track";
  181. PlayableAsset parent = trackAssetParent != null ? trackAssetParent as PlayableAsset : this;
  182. TimelineCreateUtilities.SaveAssetIntoObject(asset, parent);
  183. TimelineUndo.RegisterCreatedObjectUndo(asset, createTrackUndoName);
  184. TimelineUndo.PushUndo(parent, createTrackUndoName);
  185. if (trackAssetParent != null)
  186. trackAssetParent.AddChild(asset);
  187. else //TimelineAsset is the parent
  188. AddTrackInternal(asset);
  189. return asset;
  190. }
  191. void DeleteRecordedAnimation(TrackAsset track)
  192. {
  193. var animTrack = track as AnimationTrack;
  194. if (animTrack != null && animTrack.infiniteClip != null)
  195. TimelineUndo.PushDestroyUndo(this, track, animTrack.infiniteClip);
  196. if (track.curves != null)
  197. TimelineUndo.PushDestroyUndo(this, track, track.curves);
  198. }
  199. void DeleteRecordedAnimation(TimelineClip clip)
  200. {
  201. if (clip == null)
  202. return;
  203. if (clip.curves != null)
  204. TimelineUndo.PushDestroyUndo(this, clip.GetParentTrack(), clip.curves);
  205. if (!clip.recordable)
  206. return;
  207. AnimationPlayableAsset asset = clip.asset as AnimationPlayableAsset;
  208. if (asset == null || asset.clip == null)
  209. return;
  210. TimelineUndo.PushDestroyUndo(this, asset, asset.clip);
  211. }
  212. }
  213. }