示例#1
0
        static void SaveCloneToAsset(Object clone, Object newOwner)
        {
            var containerPath  = AssetDatabase.GetAssetPath(newOwner);
            var containerAsset = AssetDatabase.LoadAssetAtPath <Object>(containerPath);

            if (containerAsset != null)
            {
                TimelineCreateUtilities.SaveAssetIntoObject(clone, containerAsset);
                EditorUtility.SetDirty(containerAsset);
            }
        }
示例#2
0
        static void AddMarkerToParent(ScriptableObject marker, TrackAsset parent)
        {
            TimelineCreateUtilities.SaveAssetIntoObject(marker, parent);
            TimelineUndo.RegisterCreatedObjectUndo(marker, "Duplicate Marker");
            TimelineUndo.PushUndo(parent, "Duplicate Marker");

            if (parent != null)
            {
                parent.AddMarker(marker);
                ((IMarker)marker).Initialize(parent);
            }
        }
        internal static void RecursiveSubtrackClone(TrackAsset source, TrackAsset duplicate, PlayableDirector director)
        {
            List <TrackAsset> subTracks = source.subTracks;

            foreach (TrackAsset current in subTracks)
            {
                TrackAsset trackAsset = TimelineHelpers.Clone(duplicate, current, director);
                duplicate.AddChild(trackAsset);
                TrackExtensions.RecursiveSubtrackClone(current, trackAsset, director);
                Undo.RegisterCreatedObjectUndo(trackAsset, "Duplicate");
                TimelineCreateUtilities.SaveAssetIntoObject(trackAsset, source);
            }
        }
        internal static void RecursiveSubtrackClone(TrackAsset source, TrackAsset duplicate, PlayableDirector director, PlayableAsset assetOwner)
        {
            var subtracks = source.GetChildTracks();

            foreach (var sub in subtracks)
            {
                var newSub = TimelineHelpers.Clone(duplicate, sub, director, assetOwner);
                duplicate.AddChild(newSub);
                RecursiveSubtrackClone(sub, newSub, director, assetOwner);
                // registration has to happen AFTER recursion
                TimelineUndo.RegisterCreatedObjectUndo(newSub, "Duplicate");
                TimelineCreateUtilities.SaveAssetIntoObject(newSub, assetOwner);
            }
        }
        internal static bool Duplicate(this TrackAsset track, PlayableDirector director, TimelineAsset destinationTimeline = null)
        {
            bool result;

            if (track == null)
            {
                result = false;
            }
            else
            {
                if (destinationTimeline == track.timelineAsset)
                {
                    destinationTimeline = null;
                }
                TimelineAsset timelineAsset = track.parent as TimelineAsset;
                TrackAsset    trackAsset    = track.parent as TrackAsset;
                if (timelineAsset == null && trackAsset == null)
                {
                    Debug.LogWarning("Cannot duplicate track because it is not parented to known type");
                    result = false;
                }
                else
                {
                    PlayableAsset playableAsset = destinationTimeline ?? track.parent;
                    TrackAsset    trackAsset2   = TimelineHelpers.Clone(playableAsset, track, director);
                    TrackExtensions.RecursiveSubtrackClone(track, trackAsset2, director);
                    Undo.RegisterCreatedObjectUndo(trackAsset2, "Duplicate");
                    TimelineCreateUtilities.SaveAssetIntoObject(trackAsset2, playableAsset);
                    TimelineUndo.PushUndo(playableAsset, "Duplicate");
                    if (destinationTimeline != null)
                    {
                        destinationTimeline.AddTrackInternal(trackAsset2);
                    }
                    else if (timelineAsset != null)
                    {
                        TrackExtensions.ReparentTracks(new List <TrackAsset>
                        {
                            trackAsset2
                        }, timelineAsset, track, false);
                    }
                    else
                    {
                        trackAsset.AddChildAfter(trackAsset2, track);
                    }
                    result = true;
                }
            }
            return(result);
        }
示例#6
0
        internal static TimelineClip Clone(TimelineClip clip, PlayableDirector director, PlayableAsset newOwner)
        {
            var editorClip = EditorClipFactory.GetEditorClip(clip);
            // Workaround for Clips not being unity object, assign it to a editor clip wrapper, clone it, and pull the clip back out
            var newClip = Object.Instantiate(editorClip).clip;

            // perform fix ups for what Instantiate cannot properly detect
            SelectionManager.Remove(newClip);
            newClip.parentTrack = null;
            newClip.curves      = null; // instantiate might copy the reference, we need to clear it

            // curves are explicitly owned by the clip
            if (clip.curves != null)
            {
                newClip.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(newOwner, clip.curves.name));
                EditorUtility.CopySerialized(clip.curves, newClip.curves);
                TimelineCreateUtilities.SaveAssetIntoObject(newClip.curves, newOwner);
            }

            ScriptableObject playableAsset = newClip.asset as ScriptableObject;

            if (playableAsset != null && newClip.asset is IPlayableAsset)
            {
                var clone = CloneReferencedPlayableAsset(playableAsset, director);
                SaveCloneToAsset(clone, newOwner);

                newClip.asset = clone;

                // special case to make the name match the recordable clips, but only if they match on the original clip
                var originalRecordedAsset = clip.asset as AnimationPlayableAsset;
                if (clip.recordable && originalRecordedAsset != null && originalRecordedAsset.clip != null)
                {
                    AnimationPlayableAsset clonedAnimationAsset = clone as AnimationPlayableAsset;
                    if (clonedAnimationAsset != null && clonedAnimationAsset.clip != null)
                    {
                        clonedAnimationAsset.clip = CloneAnimationClip(originalRecordedAsset.clip, newOwner);
                        if (clip.displayName == originalRecordedAsset.clip.name && newClip.recordable)
                        {
                            clonedAnimationAsset.name = clonedAnimationAsset.clip.name;
                            newClip.displayName       = clonedAnimationAsset.name;
                        }
                    }
                }
            }

            return(newClip);
        }
        static void RecursiveSubtrackClone(TrackAsset source, TrackAsset duplicate, IExposedPropertyTable sourceTable, IExposedPropertyTable destTable, PlayableAsset assetOwner)
        {
            var subtracks = source.GetChildTracks();

            foreach (var sub in subtracks)
            {
                var newSub = TimelineHelpers.Clone(duplicate, sub, sourceTable, destTable, assetOwner);
                duplicate.AddChild(newSub);
                RecursiveSubtrackClone(sub, newSub, sourceTable, destTable, assetOwner);

                // Call the custom editor on Create
                var customEditor = CustomTimelineEditorCache.GetTrackEditor(newSub);
                customEditor.OnCreate_Safe(newSub, sub);

                // registration has to happen AFTER recursion
                TimelineCreateUtilities.SaveAssetIntoObject(newSub, assetOwner);
                TimelineUndo.RegisterCreatedObjectUndo(newSub, L10n.Tr("Duplicate"));
            }
        }
        static void SaveCloneToAsset(Object clone, Object newOwner)
        {
            if (newOwner == null)
            {
                return;
            }

            var containerPath  = AssetDatabase.GetAssetPath(newOwner);
            var containerAsset = AssetDatabase.LoadAssetAtPath <Object>(containerPath);

            if (containerAsset != null)
            {
                TimelineCreateUtilities.SaveAssetIntoObject(clone, containerAsset);
                EditorUtility.SetDirty(containerAsset);
            }
            else
            {
                clone.hideFlags |= newOwner.hideFlags & HideFlags.DontSave;
            }
        }
示例#9
0
        public static TimelineClip CreateClipOnTrack(Type playableAssetType, TrackAsset parentTrack, ITimelineState state, Vector2 mousePosition)
        {
            TimelineClip result;

            if (!typeof(IPlayableAsset).IsAssignableFrom(playableAssetType) || !typeof(ScriptableObject).IsAssignableFrom(playableAssetType))
            {
                result = null;
            }
            else
            {
                ScriptableObject scriptableObject = ScriptableObject.CreateInstance(playableAssetType);
                if (scriptableObject == null)
                {
                    throw new InvalidOperationException("Could not create an instance of the ScriptableObject type " + playableAssetType.Name);
                }
                scriptableObject.set_name(playableAssetType.Name);
                TimelineCreateUtilities.SaveAssetIntoObject(scriptableObject, parentTrack);
                result = TimelineHelpers.CreateClipOnTrack(scriptableObject, parentTrack, state, mousePosition);
            }
            return(result);
        }
示例#10
0
        public static TimelineClip AddRecordableClip(TrackAsset parentTrack, TimelineWindow.TimelineState state)
        {
            TimelineAsset timeline = state.timeline;
            TimelineClip  result;

            if (timeline == null)
            {
                Debug.LogError("Parent Track needs to be bound to an asset to add a recordable");
                result = null;
            }
            else
            {
                AnimationClip animationClip = new AnimationClip();
                animationClip.set_name(AnimationTrackRecorder.GetUniqueRecordedClipName(parentTrack, AnimationTrackRecorder.kRecordClipDefaultName));
                animationClip.set_frameRate(state.frameRate);
                AnimationUtility.SetGenerateMotionCurves(animationClip, true);
                Undo.RegisterCreatedObjectUndo(animationClip, "Create Clip");
                TimelineHelpers.SaveAnimClipIntoObject(animationClip, parentTrack);
                TimelineClip timelineClip = parentTrack.CreateClipFromAsset(animationClip);
                if (timelineClip != null)
                {
                    timelineClip.recordable            = true;
                    timelineClip.displayName           = animationClip.get_name();
                    timelineClip.timeScale             = 1.0;
                    timelineClip.start                 = 0.0;
                    timelineClip.duration              = 0.0;
                    timelineClip.mixInCurve            = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
                    timelineClip.mixOutCurve           = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f);
                    timelineClip.preExtrapolationMode  = TimelineClip.ClipExtrapolation.Hold;
                    timelineClip.postExtrapolationMode = TimelineClip.ClipExtrapolation.Hold;
                    TimelineCreateUtilities.SaveAssetIntoObject(timelineClip.asset, parentTrack);
                    state.Refresh();
                }
                result = timelineClip;
            }
            return(result);
        }
示例#11
0
        public DragAndDropVisualMode HandleObjectDrop(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, TreeViewDragging.DropPosition dropPos)
        {
            DragAndDropVisualMode result;

            if (!perform)
            {
                List <Object> list = new List <Object>();
                if (DragAndDrop.get_objectReferences().Any <Object>())
                {
                    list.AddRange(DragAndDrop.get_objectReferences());
                    using (List <Object> .Enumerator enumerator = list.GetEnumerator())
                    {
                        while (enumerator.MoveNext())
                        {
                            Object      o = enumerator.Current;
                            TrackType[] trackTypeHandle = TimelineHelpers.GetTrackTypeHandle(o.GetType());
                            if (!trackTypeHandle.Any <TrackType>() || trackTypeHandle.Any((TrackType t) => !TimelineDragging.ValidateObjectDrop(o)))
                            {
                                result = 0;
                                return(result);
                            }
                        }
                    }
                    result = 1;
                }
                else if (DragAndDrop.get_paths().Any <string>())
                {
                    TimelineGroupGUI timelineGroupGUI = targetItem as TimelineGroupGUI;
                    if (timelineGroupGUI == null)
                    {
                        result = 1;
                    }
                    else if (timelineGroupGUI.track == null)
                    {
                        result = 0;
                    }
                    else
                    {
                        TrackType tt    = TimelineHelpers.TrackTypeFromType(timelineGroupGUI.track.GetType());
                        string[]  paths = DragAndDrop.get_paths();
                        for (int i = 0; i < paths.Length; i++)
                        {
                            string text = paths[i];
                            list.AddRange(AssetDatabase.LoadAllAssetsAtPath(text));
                        }
                        bool flag = (from o in list
                                     where o != null
                                     select o).Any((Object o) => TimelineHelpers.IsTypeSupportedByTrack(tt, o.GetType()));
                        result = ((!flag) ? 0 : 1);
                    }
                }
                else
                {
                    result = 0;
                }
            }
            else
            {
                List <Object> list2 = new List <Object>();
                list2.AddRange(DragAndDrop.get_objectReferences());
                TrackAsset       trackAsset        = null;
                TimelineGroupGUI timelineGroupGUI2 = (TimelineGroupGUI)targetItem;
                if (targetItem != null && timelineGroupGUI2.track != null)
                {
                    trackAsset = timelineGroupGUI2.track;
                }
                Vector2 mousePosition = Event.get_current().get_mousePosition();
                foreach (Object current in list2)
                {
                    if (!(current == null))
                    {
                        if (current is TimelineAsset)
                        {
                            if (TimelineHelpers.IsCircularRef(this.m_Timeline, current as TimelineAsset))
                            {
                                Debug.LogError("Cannot add " + current.get_name() + " to the sequence because it would cause a circular reference");
                                continue;
                            }
                            TimelineAsset timelineAsset = current as TimelineAsset;
                            foreach (TrackAsset current2 in timelineAsset.tracks)
                            {
                                if (current2.mediaType == TimelineAsset.MediaType.Group)
                                {
                                    this.m_Timeline.AddTrackInternal(current2);
                                }
                            }
                            this.m_Window.state.Refresh();
                            EditorUtility.SetDirty(this.m_Timeline);
                        }
                        else if (current is TrackAsset)
                        {
                            this.m_Timeline.AddTrackInternal((TrackAsset)current);
                        }
                        else
                        {
                            TrackType   trackType        = null;
                            TrackAsset  trackAsset2      = null;
                            TrackType[] trackTypeHandle2 = TimelineHelpers.GetTrackTypeHandle(current.GetType());
                            if (trackAsset != null)
                            {
                                TrackType[] array = trackTypeHandle2;
                                for (int j = 0; j < array.Length; j++)
                                {
                                    TrackType trackType2 = array[j];
                                    if (trackAsset.GetType() == trackType2.trackType)
                                    {
                                        trackType = trackType2;
                                        break;
                                    }
                                }
                            }
                            if (trackType == null)
                            {
                                if (trackTypeHandle2.Length == 1)
                                {
                                    trackType = trackTypeHandle2[0];
                                }
                                else if (trackTypeHandle2.Length > 1)
                                {
                                    trackType = this.ResolveTypeAmbiguity(trackTypeHandle2);
                                }
                            }
                            if (trackType == null)
                            {
                                continue;
                            }
                            if (!TimelineDragging.ValidateObjectDrop(current))
                            {
                                continue;
                            }
                            if (trackAsset != null && trackAsset.GetType() == trackType.trackType)
                            {
                                trackAsset2 = trackAsset;
                            }
                            if (trackAsset2 == null)
                            {
                                trackAsset2 = this.m_Window.AddTrack(trackType.trackType, null, string.Empty);
                            }
                            if (trackAsset2 == null)
                            {
                                result = 0;
                                return(result);
                            }
                            Object @object = TimelineDragging.TransformObjectBeingDroppedAccordingToTrackRules(trackAsset2, current);
                            if (@object == null)
                            {
                                continue;
                            }
                            TimelineUndo.PushUndo(trackAsset2, "Create Clip");
                            AnimationTrack animationTrack = trackAsset2 as AnimationTrack;
                            if (animationTrack != null)
                            {
                                animationTrack.ConvertToClipMode();
                            }
                            TimelineClip timelineClip = TimelineHelpers.CreateClipOnTrack(@object, trackAsset2, this.m_Window.state, mousePosition);
                            if (timelineClip != null)
                            {
                                float num = this.m_Window.state.TimeToPixel(1.0) - this.m_Window.state.TimeToPixel(0.0);
                                mousePosition.x += (float)timelineClip.duration * num;
                                if (timelineClip.asset is ScriptableObject)
                                {
                                    string assetPath = AssetDatabase.GetAssetPath(timelineClip.asset);
                                    if (assetPath.Length == 0)
                                    {
                                        TimelineCreateUtilities.SaveAssetIntoObject(timelineClip.asset, trackAsset2);
                                    }
                                }
                                TimelineDragging.FrameClips(this.m_Window.state);
                                trackAsset2.SetCollapsed(false);
                            }
                        }
                        this.m_Window.state.Refresh();
                        EditorUtility.SetDirty(this.m_Timeline);
                    }
                }
                result = 1;
            }
            return(result);
        }
        public DragAndDropVisualMode HandleTrackDrop(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos)
        {
            ((TimelineTreeView)m_Window.treeView.gui).showInsertionMarker = false;
            var trackDragData = (TimelineDragData)DragAndDrop.GetGenericData(k_GenericDragId);
            bool validDrag = ValidDrag(targetItem, trackDragData.draggedItems);
            if (!validDrag)
                return DragAndDropVisualMode.None;


            var draggedTracks = trackDragData.draggedItems.OfType<TimelineGroupGUI>().Select(x => x.track).ToList();
            if (draggedTracks.Count == 0)
                return DragAndDropVisualMode.None;

            if (parentItem != null)
            {
                var parentActor = parentItem as TimelineGroupGUI;
                if (parentActor != null && parentActor.track != null)
                {
                    if (parentActor.track.lockedInHierarchy)
                        return DragAndDropVisualMode.Rejected;

                    if (draggedTracks.Any(x => !TimelineCreateUtilities.ValidateParentTrack(parentActor.track, x.GetType())))
                        return DragAndDropVisualMode.Rejected;
                }
            }

            var insertAfterItem = targetItem as TimelineGroupGUI;
            if (insertAfterItem != null && insertAfterItem.track != null)
            {
                ((TimelineTreeView)m_Window.treeView.gui).showInsertionMarker = true;
            }

            if (dropPos == DropPosition.Upon)
            {
                var groupGUI = targetItem as TimelineGroupGUI;
                if (groupGUI != null)
                    groupGUI.isDropTarget = true;
            }

            if (perform)
            {
                PlayableAsset targetParent = m_Timeline;
                var parentActor = parentItem as TimelineGroupGUI;

                if (parentActor != null && parentActor.track != null)
                    targetParent = parentActor.track;

                TrackAsset siblingTrack = insertAfterItem != null ? insertAfterItem.track : null;

                // where the user drops after the last track, make sure to place it after all the tracks
                if (targetParent == m_Timeline && dropPos == DropPosition.Below && siblingTrack == null)
                {
                    siblingTrack = m_Timeline.GetRootTracks().LastOrDefault(x => !draggedTracks.Contains(x));
                }

                if (TrackExtensions.ReparentTracks(TrackExtensions.FilterTracks(draggedTracks).ToList(), targetParent, siblingTrack, dropPos == DropPosition.Above))
                {
                    m_Window.state.Refresh();
                }
            }

            return DragAndDropVisualMode.Move;
        }
示例#13
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)
            {
                TimelineUndo.PushUndo(p, "Reparent");
            }
            foreach (var t in validTracks)
            {
                TimelineUndo.PushUndo(t, "Reparent");
            }
            TimelineUndo.PushUndo(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);
        }
示例#14
0
        internal static TrackAsset Duplicate(this TrackAsset track, PlayableDirector director,
                                             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, director, finalParent);

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

            RecursiveSubtrackClone(track, newTrack, director, finalParent);
            TimelineUndo.RegisterCreatedObjectUndo(newTrack, "Duplicate");
            TimelineCreateUtilities.SaveAssetIntoObject(newTrack, finalParent);
            TimelineUndo.PushUndo(finalParent, "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);
                try
                {
                    customEditor.OnCreate(newTrack, track);
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }

            return(newTrack);
        }