Maze / Library /PackageCache /com.unity.timeline@1.6.5 /Editor /Manipulators /Sequence /SelectAndMoveItem.cs
| using System; | |
| using System.Linq; | |
| using UnityEngine; | |
| using UnityEngine.Timeline; | |
| namespace UnityEditor.Timeline | |
| { | |
| class ClearSelection : Manipulator | |
| { | |
| protected override bool MouseDown(Event evt, WindowState state) | |
| { | |
| // If we hit this point this means no one used the mouse down events. We can safely clear the selection if needed | |
| if (evt.button != 0) | |
| return false; | |
| var window = state.GetWindow(); | |
| if (!window.sequenceRect.Contains(evt.mousePosition)) | |
| return false; | |
| if (ItemSelection.CanClearSelection(evt)) | |
| { | |
| SelectionManager.Clear(); | |
| return true; | |
| } | |
| return false; | |
| } | |
| } | |
| static class ItemSelection | |
| { | |
| public static bool CanClearSelection(Event evt) | |
| { | |
| return !evt.control && !evt.command && !evt.shift; | |
| } | |
| public static void RangeSelectItems(ITimelineItem lastItemToSelect) | |
| { | |
| var selectSorted = SelectionManager.SelectedItems().ToList(); | |
| var firstSelect = selectSorted.FirstOrDefault(); | |
| if (firstSelect == null) | |
| { | |
| SelectionManager.Add(lastItemToSelect); | |
| return; | |
| } | |
| var allTracks = TimelineEditor.inspectedAsset.flattenedTracks; | |
| var allItems = allTracks.SelectMany(ItemsUtils.GetItems).ToList(); | |
| TimelineHelpers.RangeSelect(allItems, selectSorted, lastItemToSelect, SelectionManager.Add, SelectionManager.Remove); | |
| } | |
| public static ISelectable HandleSingleSelection(Event evt) | |
| { | |
| var item = PickerUtils.TopmostPickedItemOfType<ISelectable>(i => i.CanSelect(evt)); | |
| if (item != null) | |
| { | |
| var selected = item.IsSelected(); | |
| if (!selected && CanClearSelection(evt)) | |
| SelectionManager.Clear(); | |
| if (evt.modifiers == EventModifiers.Shift) | |
| { | |
| if (!selected) | |
| RangeSelectItems((item as TimelineItemGUI)?.item); | |
| } | |
| else | |
| { | |
| HandleItemSelection(evt, item); | |
| } | |
| } | |
| return item; | |
| } | |
| public static void HandleItemSelection(Event evt, ISelectable item) | |
| { | |
| if (evt.modifiers == ManipulatorsUtils.actionModifier) | |
| { | |
| if (item.IsSelected()) | |
| item.Deselect(); | |
| else | |
| item.Select(); | |
| } | |
| else | |
| { | |
| if (!item.IsSelected()) | |
| item.Select(); | |
| } | |
| } | |
| } | |
| class SelectAndMoveItem : Manipulator | |
| { | |
| bool m_Dragged; | |
| SnapEngine m_SnapEngine; | |
| TimeAreaAutoPanner m_TimeAreaAutoPanner; | |
| Vector2 m_MouseDownPosition; | |
| bool m_HorizontalMovementDone; | |
| bool m_VerticalMovementDone; | |
| MoveItemHandler m_MoveItemHandler; | |
| bool m_CycleMarkersPending; | |
| protected override bool MouseDown(Event evt, WindowState state) | |
| { | |
| if (evt.alt || evt.button != 0) | |
| return false; | |
| m_Dragged = false; | |
| // Cycling markers and selection are mutually exclusive operations | |
| if (!HandleMarkerCycle() && !HandleSingleSelection(evt)) | |
| return false; | |
| m_MouseDownPosition = evt.mousePosition; | |
| m_VerticalMovementDone = false; | |
| m_HorizontalMovementDone = false; | |
| return true; | |
| } | |
| protected override bool MouseUp(Event evt, WindowState state) | |
| { | |
| if (!m_Dragged) | |
| { | |
| var item = PickerUtils.TopmostPickedItem() as ISelectable; | |
| if (item == null) | |
| return false; | |
| if (!item.IsSelected()) | |
| return false; | |
| // Re-selecting an item part of a multi-selection should only keep this item selected. | |
| if (SelectionManager.Count() > 1 && ItemSelection.CanClearSelection(evt)) | |
| { | |
| SelectionManager.Clear(); | |
| item.Select(); | |
| return true; | |
| } | |
| if (m_CycleMarkersPending) | |
| { | |
| m_CycleMarkersPending = false; | |
| TimelineMarkerClusterGUI.CycleMarkers(); | |
| return true; | |
| } | |
| return false; | |
| } | |
| m_TimeAreaAutoPanner = null; | |
| DropItems(); | |
| m_SnapEngine = null; | |
| m_MoveItemHandler = null; | |
| state.Evaluate(); | |
| state.RemoveCaptured(this); | |
| m_Dragged = false; | |
| TimelineCursors.ClearCursor(); | |
| return true; | |
| } | |
| protected override bool DoubleClick(Event evt, WindowState state) | |
| { | |
| return MouseDown(evt, state) && MouseUp(evt, state); | |
| } | |
| protected override bool MouseDrag(Event evt, WindowState state) | |
| { | |
| if (state.editSequence.isReadOnly) | |
| return false; | |
| // case 1099285 - ctrl-click can cause no clips to be selected | |
| var selectedItemsGUI = SelectionManager.SelectedItems(); | |
| if (!selectedItemsGUI.Any()) | |
| { | |
| m_Dragged = false; | |
| return false; | |
| } | |
| const float hDeadZone = 5.0f; | |
| const float vDeadZone = 5.0f; | |
| bool vDone = m_VerticalMovementDone || Math.Abs(evt.mousePosition.y - m_MouseDownPosition.y) > vDeadZone; | |
| bool hDone = m_HorizontalMovementDone || Math.Abs(evt.mousePosition.x - m_MouseDownPosition.x) > hDeadZone; | |
| m_CycleMarkersPending = false; | |
| if (!m_Dragged) | |
| { | |
| var canStartMove = vDone || hDone; | |
| if (canStartMove) | |
| { | |
| state.AddCaptured(this); | |
| m_Dragged = true; | |
| var referenceTrack = GetTrackDropTargetAt(state, m_MouseDownPosition); | |
| foreach (var item in selectedItemsGUI) | |
| item.gui.StartDrag(); | |
| m_MoveItemHandler = new MoveItemHandler(state); | |
| m_MoveItemHandler.Grab(selectedItemsGUI, referenceTrack, m_MouseDownPosition); | |
| m_SnapEngine = new SnapEngine(m_MoveItemHandler, m_MoveItemHandler, ManipulateEdges.Both, | |
| state, m_MouseDownPosition); | |
| m_TimeAreaAutoPanner = new TimeAreaAutoPanner(state); | |
| } | |
| } | |
| if (!m_VerticalMovementDone) | |
| { | |
| m_VerticalMovementDone = vDone; | |
| if (m_VerticalMovementDone) | |
| m_MoveItemHandler.OnTrackDetach(); | |
| } | |
| if (!m_HorizontalMovementDone) | |
| { | |
| m_HorizontalMovementDone = hDone; | |
| } | |
| if (m_Dragged) | |
| { | |
| if (m_HorizontalMovementDone) | |
| m_SnapEngine.Snap(evt.mousePosition, evt.modifiers); | |
| if (m_VerticalMovementDone) | |
| { | |
| var track = GetTrackDropTargetAt(state, evt.mousePosition); | |
| m_MoveItemHandler.UpdateTrackTarget(track); | |
| } | |
| state.Evaluate(); | |
| } | |
| return true; | |
| } | |
| public override void Overlay(Event evt, WindowState state) | |
| { | |
| if (!m_Dragged) | |
| return; | |
| if (m_TimeAreaAutoPanner != null) | |
| m_TimeAreaAutoPanner.OnGUI(evt); | |
| m_MoveItemHandler.OnGUI(evt); | |
| if (!m_MoveItemHandler.allowTrackSwitch || m_MoveItemHandler.targetTrack != null) | |
| { | |
| TimeIndicator.Draw(state, m_MoveItemHandler.start, m_MoveItemHandler.end); | |
| m_SnapEngine.OnGUI(); | |
| } | |
| } | |
| bool HandleMarkerCycle() | |
| { | |
| m_CycleMarkersPending = TimelineMarkerClusterGUI.CanCycleMarkers(); | |
| return m_CycleMarkersPending; | |
| } | |
| static bool HandleSingleSelection(Event evt) | |
| { | |
| return ItemSelection.HandleSingleSelection(evt) != null; | |
| } | |
| void DropItems() | |
| { | |
| // Order matters here: m_MoveItemHandler.movingItems is destroyed during call to Drop() | |
| foreach (var movingItem in m_MoveItemHandler.movingItems) | |
| { | |
| foreach (var item in movingItem.items) | |
| item.gui.StopDrag(); | |
| } | |
| m_MoveItemHandler.Drop(); | |
| } | |
| static TrackAsset GetTrackDropTargetAt(WindowState state, Vector2 point) | |
| { | |
| var track = state.spacePartitioner.GetItemsAtPosition<IRowGUI>(point).FirstOrDefault(); | |
| return track != null ? track.asset : null; | |
| } | |
| } | |
| } | |