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