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;
        }
Exemplo n.º 2
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);
        }