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.
254 lines
9.7 KiB
254 lines
9.7 KiB
using System; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
using UnityEngine.Timeline; |
|
using UnityEngine.Playables; |
|
using UnityEngineInternal; // for metro type extensions |
|
|
|
namespace UnityEngine.Timeline |
|
{ |
|
public partial class TimelineAsset |
|
{ |
|
/// <summary> |
|
/// Allows you to create a track and add it to the Timeline. |
|
/// </summary> |
|
/// <param name="type">The type of track to create. Must derive from TrackAsset.</param> |
|
/// <param name="parent">Track to parent to. This can be null.</param> |
|
/// <param name="name">Name to give the track.</param> |
|
/// <returns>The created track.</returns> |
|
/// <remarks> |
|
/// 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. |
|
/// </remarks> |
|
public TrackAsset CreateTrack(Type type, TrackAsset parent, string name) |
|
{ |
|
if (parent != null && parent.timelineAsset != this) |
|
throw new InvalidOperationException("Addtrack cannot parent to a track not in the Timeline"); |
|
|
|
if (!typeof(TrackAsset).IsAssignableFrom(type)) |
|
throw new InvalidOperationException("Supplied type must be a track asset"); |
|
|
|
if (parent != null) |
|
{ |
|
if (!TimelineCreateUtilities.ValidateParentTrack(parent, type)) |
|
throw new InvalidOperationException("Cannot assign a child of type " + type.Name + " to a parent of type " + parent.GetType().Name); |
|
} |
|
|
|
var baseName = name; |
|
if (string.IsNullOrEmpty(baseName)) |
|
{ |
|
baseName = type.Name; |
|
#if UNITY_EDITOR |
|
baseName = UnityEditor.ObjectNames.NicifyVariableName(baseName); |
|
#endif |
|
} |
|
|
|
var trackName = baseName; |
|
if (parent != null) |
|
trackName = TimelineCreateUtilities.GenerateUniqueActorName(parent.subTracksObjects, baseName); |
|
else |
|
trackName = TimelineCreateUtilities.GenerateUniqueActorName(trackObjects, baseName); |
|
|
|
TrackAsset newTrack = AllocateTrack(parent, trackName, type); |
|
|
|
return newTrack; |
|
} |
|
|
|
/// <summary> |
|
/// Creates a track and adds it to the Timeline Asset. |
|
/// </summary> |
|
/// <param name="parent">Track to parent to. This can be null.</param> |
|
/// <param name="trackName">The name of the track being created.</param> |
|
/// <typeparam name="T">The type of track being created. The track type must be derived from TrackAsset.</typeparam> |
|
/// <returns>Returns the created track.</returns> |
|
/// <remarks> |
|
/// 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. |
|
/// </remarks> |
|
public T CreateTrack<T>(TrackAsset parent, string trackName) where T : TrackAsset, new() |
|
{ |
|
return (T)CreateTrack(typeof(T), parent, trackName); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a track and adds it to the Timeline Asset. |
|
/// </summary> |
|
/// <param name="trackName">The name of the track being created.</param> |
|
/// <typeparam name="T">The type of track being created. The track type must be derived from TrackAsset.</typeparam> |
|
/// <returns>Returns the created track.</returns> |
|
public T CreateTrack<T>(string trackName) where T : TrackAsset, new() |
|
{ |
|
return (T)CreateTrack(typeof(T), null, trackName); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a track and adds it to the Timeline Asset. |
|
/// </summary> |
|
/// <typeparam name="T">The type of track being created. The track type must be derived from TrackAsset.</typeparam> |
|
/// <returns>Returns the created track.</returns> |
|
public T CreateTrack<T>() where T : TrackAsset, new() |
|
{ |
|
return (T)CreateTrack(typeof(T), null, null); |
|
} |
|
|
|
/// <summary> |
|
/// Delete a clip from this timeline. |
|
/// </summary> |
|
/// <param name="clip">The clip to delete.</param> |
|
/// <returns>Returns true if the removal was successful</returns> |
|
/// <remarks> |
|
/// This method will delete a clip and any assets owned by the clip. |
|
/// </remarks> |
|
public bool DeleteClip(TimelineClip clip) |
|
{ |
|
if (clip == null || clip.GetParentTrack() == null) |
|
{ |
|
return false; |
|
} |
|
if (this != clip.GetParentTrack().timelineAsset) |
|
{ |
|
Debug.LogError("Cannot delete a clip from this timeline"); |
|
return false; |
|
} |
|
|
|
TimelineUndo.PushUndo(clip.GetParentTrack(), "Delete Clip"); |
|
if (clip.curves != null) |
|
{ |
|
TimelineUndo.PushDestroyUndo(this, clip.GetParentTrack(), clip.curves); |
|
} |
|
|
|
// handle wrapped assets |
|
if (clip.asset != null) |
|
{ |
|
DeleteRecordedAnimation(clip); |
|
|
|
// TODO -- we should flag assets and owned, instead of this check... |
|
#if UNITY_EDITOR |
|
string path = UnityEditor.AssetDatabase.GetAssetPath(clip.asset); |
|
if (path == UnityEditor.AssetDatabase.GetAssetPath(this)) |
|
#endif |
|
{ |
|
TimelineUndo.PushDestroyUndo(this, clip.GetParentTrack(), clip.asset); |
|
} |
|
} |
|
|
|
var clipParentTrack = clip.GetParentTrack(); |
|
clipParentTrack.RemoveClip(clip); |
|
clipParentTrack.CalculateExtrapolationTimes(); |
|
|
|
return true; |
|
} |
|
|
|
/// <summary> |
|
/// Deletes a track from a timeline, including all clips and subtracks. |
|
/// </summary> |
|
/// <param name="track">The track to delete. It must be owned by this Timeline.</param> |
|
/// <returns>True if the track was deleted successfully.</returns> |
|
public bool DeleteTrack(TrackAsset track) |
|
{ |
|
if (track.timelineAsset != this) |
|
return false; |
|
|
|
// push before we modify properties |
|
TimelineUndo.PushUndo(track, "Delete Track"); |
|
TimelineUndo.PushUndo(this, "Delete Track"); |
|
|
|
TrackAsset parent = track.parent as TrackAsset; |
|
if (parent != null) |
|
TimelineUndo.PushUndo(parent, "Delete Track"); |
|
|
|
var children = track.GetChildTracks(); |
|
foreach (var child in children) |
|
{ |
|
DeleteTrack(child); |
|
} |
|
|
|
DeleteRecordedAnimation(track); |
|
|
|
var clipsToDelete = new List<TimelineClip>(track.clips); |
|
foreach (var clip in clipsToDelete) |
|
{ |
|
DeleteClip(clip); |
|
} |
|
RemoveTrack(track); |
|
|
|
TimelineUndo.PushDestroyUndo(this, this, track); |
|
|
|
return true; |
|
} |
|
|
|
internal void MoveLastTrackBefore(TrackAsset asset) |
|
{ |
|
if (m_Tracks == null || m_Tracks.Count < 2 || asset == null) |
|
return; |
|
|
|
var lastTrack = m_Tracks[m_Tracks.Count - 1]; |
|
if (lastTrack == asset) |
|
return; |
|
|
|
for (int i = 0; i < m_Tracks.Count - 1; i++) |
|
{ |
|
if (m_Tracks[i] == asset) |
|
{ |
|
for (int j = m_Tracks.Count - 1; j > i; j--) |
|
m_Tracks[j] = m_Tracks[j - 1]; |
|
m_Tracks[i] = lastTrack; |
|
Invalidate(); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
TrackAsset AllocateTrack(TrackAsset trackAssetParent, string trackName, Type trackType) |
|
{ |
|
if (trackAssetParent != null && trackAssetParent.timelineAsset != this) |
|
throw new InvalidOperationException("Addtrack cannot parent to a track not in the Timeline"); |
|
|
|
if (!typeof(TrackAsset).IsAssignableFrom(trackType)) |
|
throw new InvalidOperationException("Supplied type must be a track asset"); |
|
|
|
var asset = (TrackAsset)CreateInstance(trackType); |
|
asset.name = trackName; |
|
|
|
const string createTrackUndoName = "Create Track"; |
|
|
|
PlayableAsset parent = trackAssetParent != null ? trackAssetParent as PlayableAsset : this; |
|
TimelineCreateUtilities.SaveAssetIntoObject(asset, parent); |
|
TimelineUndo.RegisterCreatedObjectUndo(asset, createTrackUndoName); |
|
TimelineUndo.PushUndo(parent, createTrackUndoName); |
|
|
|
if (trackAssetParent != null) |
|
trackAssetParent.AddChild(asset); |
|
else //TimelineAsset is the parent |
|
AddTrackInternal(asset); |
|
|
|
return asset; |
|
} |
|
|
|
void DeleteRecordedAnimation(TrackAsset track) |
|
{ |
|
var animTrack = track as AnimationTrack; |
|
if (animTrack != null && animTrack.infiniteClip != null) |
|
TimelineUndo.PushDestroyUndo(this, track, animTrack.infiniteClip); |
|
|
|
if (track.curves != null) |
|
TimelineUndo.PushDestroyUndo(this, track, track.curves); |
|
} |
|
|
|
void DeleteRecordedAnimation(TimelineClip clip) |
|
{ |
|
if (clip == null) |
|
return; |
|
|
|
if (clip.curves != null) |
|
TimelineUndo.PushDestroyUndo(this, clip.GetParentTrack(), clip.curves); |
|
|
|
if (!clip.recordable) |
|
return; |
|
|
|
AnimationPlayableAsset asset = clip.asset as AnimationPlayableAsset; |
|
if (asset == null || asset.clip == null) |
|
return; |
|
|
|
TimelineUndo.PushDestroyUndo(this, asset, asset.clip); |
|
} |
|
} |
|
}
|
|
|