コード例 #1
0
        // Special method to remove a track that is in a broken state. i.e. the script won't load
        internal static bool RemoveBrokenTrack(PlayableAsset parent, ScriptableObject track)
        {
            var parentTrack    = parent as TrackAsset;
            var parentTimeline = parent as TimelineAsset;

            if (parentTrack == null && parentTimeline == null)
            {
                throw new ArgumentException("parent is not a valid parent type", "parent");
            }

            // this object must be a Unity null, but not actually null;
            object trackAsObject = track;

            if (trackAsObject == null || track as TrackAsset != null) // yes, this is correct
            {
                throw new ArgumentException("track is not in a broken state");
            }

            // this belongs to a parent track
            if (parentTrack != null)
            {
                int index = parentTrack.subTracksObjects.FindIndex(t => t.GetInstanceID() == track.GetInstanceID());
                if (index >= 0)
                {
                    UndoExtensions.RegisterTrack(parentTrack, L10n.Tr("Remove Track"));
                    parentTrack.subTracksObjects.RemoveAt(index);
                    parentTrack.Invalidate();
                    Undo.DestroyObjectImmediate(track);
                    return(true);
                }
            }
            else if (parentTimeline != null)
            {
                int index = parentTimeline.trackObjects.FindIndex(t => t.GetInstanceID() == track.GetInstanceID());
                if (index >= 0)
                {
                    UndoExtensions.RegisterPlayableAsset(parentTimeline, L10n.Tr("Remove Track"));
                    parentTimeline.trackObjects.RemoveAt(index);
                    parentTimeline.Invalidate();
                    Undo.DestroyObjectImmediate(track);
                    return(true);
                }
            }

            return(false);
        }
        void DoManipulators()
        {
            if (m_EditorClip == null || m_EditorClip.clip == null)
            {
                return;
            }

            AnimationPlayableAsset animationPlayable = m_EditorClip.clip.asset as AnimationPlayableAsset;
            AnimationTrack         track             = m_EditorClip.clip.parentTrack as AnimationTrack;
            Transform transform = GetTransform();

            if (transform != null && animationPlayable != null && m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None && track != null)
            {
                UndoExtensions.RegisterPlayableAsset(animationPlayable, "Inspector");
                Vector3    position = transform.position;
                Quaternion rotation = transform.rotation;

                EditorGUI.BeginChangeCheck();
                if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Translation)
                {
                    position = Handles.PositionHandle(position, Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : rotation);
                }
                else if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Rotation)
                {
                    rotation = Handles.RotationHandle(rotation, position);
                }

                if (EditorGUI.EndChangeCheck())
                {
                    var res = TimelineAnimationUtilities.UpdateClipOffsets(animationPlayable, track, transform, position, rotation);
                    animationPlayable.position    = res.position;
                    animationPlayable.eulerAngles = AnimationUtility.GetClosestEuler(res.rotation, animationPlayable.eulerAngles, RotationOrder.OrderZXY);
                    Reevaluate();
                    Repaint();
                }
            }
        }
コード例 #3
0
        // Reparents a list of tracks to a new parent
        //  the new parent cannot be null (has to be track asset or sequence)
        //  the insertAfter can be null (will not reorder)
        internal static bool ReparentTracks(List <TrackAsset> tracksToMove, PlayableAsset targetParent,
                                            TrackAsset insertMarker = null, bool insertBefore = false)
        {
            var targetParentTrack   = targetParent as TrackAsset;
            var targetSequenceTrack = targetParent as TimelineAsset;

            if (tracksToMove == null || tracksToMove.Count == 0 || (targetParentTrack == null && targetSequenceTrack == null))
            {
                return(false);
            }

            // invalid parent type on a track
            if (targetParentTrack != null && tracksToMove.Any(x => !TimelineCreateUtilities.ValidateParentTrack(targetParentTrack, x.GetType())))
            {
                return(false);
            }

            // no valid tracks means this is simply a rearrangement
            var validTracks = tracksToMove.Where(x => x.parent != targetParent).ToList();

            if (insertMarker == null && !validTracks.Any())
            {
                return(false);
            }

            var parents = validTracks.Select(x => x.parent).Where(x => x != null).Distinct().ToList();

            // push the current state of the tracks that will change
            foreach (var p in parents)
            {
                UndoExtensions.RegisterPlayableAsset(p, "Reparent");
            }
            UndoExtensions.RegisterTracks(validTracks, "Reparent");
            UndoExtensions.RegisterPlayableAsset(targetParent, "Reparent");

            // need to reparent tracks first, before moving them.
            foreach (var t in validTracks)
            {
                if (t.parent != targetParent)
                {
                    TrackAsset    toMoveParent   = t.parent as TrackAsset;
                    TimelineAsset toMoveTimeline = t.parent as TimelineAsset;
                    if (toMoveTimeline != null)
                    {
                        toMoveTimeline.RemoveTrack(t);
                    }
                    else if (toMoveParent != null)
                    {
                        toMoveParent.RemoveSubTrack(t);
                    }

                    if (targetParentTrack != null)
                    {
                        targetParentTrack.AddChild(t);
                        targetParentTrack.SetCollapsed(false);
                    }
                    else
                    {
                        targetSequenceTrack.AddTrackInternal(t);
                    }
                }
            }


            if (insertMarker != null)
            {
                // re-ordering track. This is using internal APIs, so invalidation of the tracks must be done manually to avoid
                //  cache mismatches
                var children = targetParentTrack != null ? targetParentTrack.subTracksObjects : targetSequenceTrack.trackObjects;
                TimelineUtility.ReorderTracks(children, tracksToMove, insertMarker, insertBefore);
                if (targetParentTrack != null)
                {
                    targetParentTrack.Invalidate();
                }
                if (insertMarker.timelineAsset != null)
                {
                    insertMarker.timelineAsset.Invalidate();
                }
            }

            return(true);
        }
コード例 #4
0
        internal static TrackAsset Duplicate(this TrackAsset track, IExposedPropertyTable sourceTable, IExposedPropertyTable destTable,
                                             TimelineAsset destinationTimeline = null)
        {
            if (track == null)
            {
                return(null);
            }

            // if the destination is us, clear to avoid bad parenting (case 919421)
            if (destinationTimeline == track.timelineAsset)
            {
                destinationTimeline = null;
            }

            var timelineParent = track.parent as TimelineAsset;
            var trackParent    = track.parent as TrackAsset;

            if (timelineParent == null && trackParent == null)
            {
                Debug.LogWarning("Cannot duplicate track because it is not parented to known type");
                return(null);
            }

            // Determine who the final parent is. If we are pasting into another track, it's always the timeline.
            //  Otherwise it's the original parent
            PlayableAsset finalParent = destinationTimeline != null ? destinationTimeline : track.parent;

            // grab the list of tracks to generate a name from (923360) to get the list of names
            // no need to do this part recursively
            var finalTrackParent   = finalParent as TrackAsset;
            var finalTimelineAsset = finalParent as TimelineAsset;
            var otherTracks        = (finalTimelineAsset != null) ? finalTimelineAsset.trackObjects : finalTrackParent.subTracksObjects;

            // Important to create the new objects before pushing the original undo, or redo breaks the
            //  sequence
            var newTrack = TimelineHelpers.Clone(finalParent, track, sourceTable, destTable, finalParent);

            newTrack.name = TimelineCreateUtilities.GenerateUniqueActorName(otherTracks, newTrack.name);

            RecursiveSubtrackClone(track, newTrack, sourceTable, destTable, finalParent);
            TimelineCreateUtilities.SaveAssetIntoObject(newTrack, finalParent);
            TimelineUndo.RegisterCreatedObjectUndo(newTrack, L10n.Tr("Duplicate"));
            UndoExtensions.RegisterPlayableAsset(finalParent, L10n.Tr("Duplicate"));

            if (destinationTimeline != null) // other timeline
            {
                destinationTimeline.AddTrackInternal(newTrack);
            }
            else if (timelineParent != null) // this timeline, no parent
            {
                ReparentTracks(new List <TrackAsset> {
                    newTrack
                }, timelineParent, timelineParent.GetRootTracks().Last(), false);
            }
            else // this timeline, with parent
            {
                trackParent.AddChild(newTrack);
            }

            // Call the custom editor. this check prevents the call when copying to the clipboard
            if (destinationTimeline == null || destinationTimeline == TimelineEditor.inspectedAsset)
            {
                var customEditor = CustomTimelineEditorCache.GetTrackEditor(newTrack);
                customEditor.OnCreate_Safe(newTrack, track);
            }

            return(newTrack);
        }