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; }
// 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); }