using System; namespace UnityEngine.Timeline { /// /// Extension methods for TimelineClip /// public static class TimelineClipExtensions { static readonly string k_UndoSetParentTrackText = "Move Clip"; /// /// Tries to move a TimelineClip to a different track. Validates that the destination track can accept the clip before performing the move. /// Fails if the clip's PlayableAsset is null, the current and destination tracks are the same or the destination track cannot accept the clip. /// /// Clip that is being moved /// Desired destination track /// Thrown if or are null /// Thrown if the PlayableAsset in the TimelineClip is null /// Thrown if the current parent track and destination track are the same /// Thrown if the destination track cannot hold tracks of the given type public static void MoveToTrack(this TimelineClip clip, TrackAsset destinationTrack) { if (clip == null) { throw new ArgumentNullException($"'this' argument for {nameof(MoveToTrack)} cannot be null."); } if (destinationTrack == null) { throw new ArgumentNullException("Cannot move TimelineClip to a null track."); } TrackAsset parentTrack = clip.GetParentTrack(); Object asset = clip.asset; // If the asset is null we cannot validate its type against the destination track if (asset == null) { throw new InvalidOperationException("Cannot move a TimelineClip to a different track if the TimelineClip's PlayableAsset is null."); } if (parentTrack == destinationTrack) { throw new InvalidOperationException($"TimelineClip is already on {destinationTrack.name}."); } if (!destinationTrack.ValidateClipType(asset.GetType())) { throw new InvalidOperationException($"Track {destinationTrack.name} cannot contain clips of type {clip.GetType().Name}."); } MoveToTrack_Impl(clip, destinationTrack, asset, parentTrack); } /// /// Tries to move a TimelineClip to a different track. Validates that the destination track can accept the clip before performing the move. /// Fails if the clip's PlayableAsset is null, the current and destination tracks are the same or the destination track cannot accept the clip. /// /// Clip that is being moved /// Desired destination track /// Returns true if the clip was successfully moved to the destination track, false otherwise. Also returns false if either argument is null /// Thrown if or are null public static bool TryMoveToTrack(this TimelineClip clip, TrackAsset destinationTrack) { if (clip == null) { throw new ArgumentNullException($"'this' argument for {nameof(TryMoveToTrack)} cannot be null."); } if (destinationTrack == null) { throw new ArgumentNullException("Cannot move TimelineClip to a null parent."); } TrackAsset parentTrack = clip.GetParentTrack(); Object asset = clip.asset; // If the asset is null we cannot validate its type against the destination track if (asset == null) { return false; } if (parentTrack != destinationTrack) { if (!destinationTrack.ValidateClipType(asset.GetType())) { return false; } MoveToTrack_Impl(clip, destinationTrack, asset, parentTrack); return true; } return false; } static void MoveToTrack_Impl(TimelineClip clip, TrackAsset destinationTrack, Object asset, TrackAsset parentTrack) { TimelineUndo.PushUndo(asset, k_UndoSetParentTrackText); if (parentTrack != null) { TimelineUndo.PushUndo(parentTrack, k_UndoSetParentTrackText); } TimelineUndo.PushUndo(destinationTrack, k_UndoSetParentTrackText); clip.SetParentTrack_Internal(destinationTrack); if (parentTrack == null) { TimelineCreateUtilities.SaveAssetIntoObject(asset, destinationTrack); } else if (parentTrack.timelineAsset != destinationTrack.timelineAsset) { TimelineCreateUtilities.RemoveAssetFromObject(asset, parentTrack); TimelineCreateUtilities.SaveAssetIntoObject(asset, destinationTrack); } } } }