345 lines
11 KiB
C#
345 lines
11 KiB
C#
![]() |
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Timeline;
|
||
|
|
||
|
namespace UnityEditor.Timeline
|
||
|
{
|
||
|
static class EditMode
|
||
|
{
|
||
|
public enum EditType
|
||
|
{
|
||
|
None = -1,
|
||
|
Mix = 0,
|
||
|
Ripple = 1,
|
||
|
Replace = 2
|
||
|
}
|
||
|
|
||
|
interface ISubEditMode
|
||
|
{
|
||
|
IMoveItemMode moveItemMode { get; }
|
||
|
IMoveItemDrawer moveItemDrawer { get; }
|
||
|
ITrimItemMode trimItemMode { get; }
|
||
|
ITrimItemDrawer trimItemDrawer { get; }
|
||
|
IAddDeleteItemMode addDeleteItemMode { get; }
|
||
|
|
||
|
Color color { get; }
|
||
|
KeyCode clutchKey { get; }
|
||
|
|
||
|
void Reset();
|
||
|
}
|
||
|
|
||
|
class SubEditMode<TMoveMode, TTrimMode, TAddDeleteMode>: ISubEditMode
|
||
|
where TMoveMode : class, IMoveItemMode, IMoveItemDrawer, new()
|
||
|
where TTrimMode : class, ITrimItemMode, ITrimItemDrawer, new()
|
||
|
where TAddDeleteMode : class, IAddDeleteItemMode, new()
|
||
|
{
|
||
|
public SubEditMode(Color guiColor, KeyCode key)
|
||
|
{
|
||
|
color = guiColor;
|
||
|
clutchKey = key;
|
||
|
Reset();
|
||
|
}
|
||
|
|
||
|
public void Reset()
|
||
|
{
|
||
|
m_MoveItemMode = new TMoveMode();
|
||
|
m_TrimItemMode = new TTrimMode();
|
||
|
m_AddDeleteItemMode = new TAddDeleteMode();
|
||
|
}
|
||
|
|
||
|
TMoveMode m_MoveItemMode;
|
||
|
TTrimMode m_TrimItemMode;
|
||
|
TAddDeleteMode m_AddDeleteItemMode;
|
||
|
|
||
|
public IMoveItemMode moveItemMode { get { return m_MoveItemMode; } }
|
||
|
public IMoveItemDrawer moveItemDrawer { get { return m_MoveItemMode; } }
|
||
|
public ITrimItemMode trimItemMode { get { return m_TrimItemMode; } }
|
||
|
public ITrimItemDrawer trimItemDrawer { get { return m_TrimItemMode; } }
|
||
|
public IAddDeleteItemMode addDeleteItemMode { get { return m_AddDeleteItemMode; } }
|
||
|
public Color color { get; }
|
||
|
public KeyCode clutchKey { get; }
|
||
|
}
|
||
|
|
||
|
static readonly Dictionary<EditType, ISubEditMode> k_EditModes = new Dictionary<EditType, ISubEditMode>
|
||
|
{
|
||
|
{ EditType.Mix, new SubEditMode<MoveItemModeMix, TrimItemModeMix, AddDeleteItemModeMix>(DirectorStyles.kMixToolColor, KeyCode.Alpha1) },
|
||
|
{ EditType.Ripple, new SubEditMode<MoveItemModeRipple, TrimItemModeRipple, AddDeleteItemModeRipple>(DirectorStyles.kRippleToolColor, KeyCode.Alpha2) },
|
||
|
{ EditType.Replace, new SubEditMode<MoveItemModeReplace, TrimItemModeReplace, AddDeleteItemModeReplace>(DirectorStyles.kReplaceToolColor, KeyCode.Alpha3) }
|
||
|
};
|
||
|
|
||
|
static EditType s_CurrentEditType = EditType.Mix;
|
||
|
static EditType s_OverrideEditType = EditType.None;
|
||
|
|
||
|
static ITrimmable s_CurrentTrimItem;
|
||
|
static TrimEdge s_CurrentTrimDirection;
|
||
|
static MoveItemHandler s_CurrentMoveItemHandler;
|
||
|
static EditModeInputHandler s_InputHandler = new EditModeInputHandler();
|
||
|
|
||
|
static ITrimItemMode trimMode
|
||
|
{
|
||
|
get { return GetSubEditMode(editType).trimItemMode; }
|
||
|
}
|
||
|
|
||
|
static ITrimItemDrawer trimDrawer
|
||
|
{
|
||
|
get { return GetSubEditMode(editType).trimItemDrawer; }
|
||
|
}
|
||
|
|
||
|
static IMoveItemMode moveMode
|
||
|
{
|
||
|
get { return GetSubEditMode(editType).moveItemMode; }
|
||
|
}
|
||
|
|
||
|
static IMoveItemDrawer moveDrawer
|
||
|
{
|
||
|
get { return GetSubEditMode(editType).moveItemDrawer; }
|
||
|
}
|
||
|
|
||
|
static IAddDeleteItemMode addDeleteMode
|
||
|
{
|
||
|
get { return GetSubEditMode(editType).addDeleteItemMode; }
|
||
|
}
|
||
|
|
||
|
public static EditModeInputHandler inputHandler
|
||
|
{
|
||
|
get { return s_InputHandler; }
|
||
|
}
|
||
|
|
||
|
static Color modeColor
|
||
|
{
|
||
|
get { return GetSubEditMode(editType).color; }
|
||
|
}
|
||
|
|
||
|
public static EditType editType
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (s_OverrideEditType != EditType.None)
|
||
|
return s_OverrideEditType;
|
||
|
|
||
|
var window = TimelineWindow.instance;
|
||
|
if (window != null)
|
||
|
s_CurrentEditType = window.state.editType;
|
||
|
|
||
|
return s_CurrentEditType;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
s_CurrentEditType = value;
|
||
|
|
||
|
var window = TimelineWindow.instance;
|
||
|
if (window != null)
|
||
|
window.state.editType = value;
|
||
|
|
||
|
s_OverrideEditType = EditType.None;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static ISubEditMode GetSubEditMode(EditType type)
|
||
|
{
|
||
|
var subEditMode = k_EditModes[type];
|
||
|
if (subEditMode != null)
|
||
|
return subEditMode;
|
||
|
|
||
|
Debug.LogError("Unsupported editmode type");
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
static EditType GetSubEditType(KeyCode key)
|
||
|
{
|
||
|
foreach (var subEditMode in k_EditModes)
|
||
|
{
|
||
|
if (subEditMode.Value.clutchKey == key)
|
||
|
return subEditMode.Key;
|
||
|
}
|
||
|
return EditType.None;
|
||
|
}
|
||
|
|
||
|
public static void ClearEditMode()
|
||
|
{
|
||
|
k_EditModes[editType].Reset();
|
||
|
}
|
||
|
|
||
|
public static void BeginTrim(ITimelineItem item, TrimEdge trimDirection)
|
||
|
{
|
||
|
var itemToTrim = item as ITrimmable;
|
||
|
if (itemToTrim == null) return;
|
||
|
|
||
|
s_CurrentTrimItem = itemToTrim;
|
||
|
s_CurrentTrimDirection = trimDirection;
|
||
|
trimMode.OnBeforeTrim(itemToTrim, trimDirection);
|
||
|
UndoExtensions.RegisterTrack(itemToTrim.parentTrack, L10n.Tr("Trim Clip"));
|
||
|
}
|
||
|
|
||
|
public static void TrimStart(ITimelineItem item, double time, bool affectTimeScale)
|
||
|
{
|
||
|
var itemToTrim = item as ITrimmable;
|
||
|
if (itemToTrim == null) return;
|
||
|
|
||
|
trimMode.TrimStart(itemToTrim, time, affectTimeScale);
|
||
|
}
|
||
|
|
||
|
public static void TrimEnd(ITimelineItem item, double time, bool affectTimeScale)
|
||
|
{
|
||
|
var itemToTrim = item as ITrimmable;
|
||
|
if (itemToTrim == null) return;
|
||
|
|
||
|
trimMode.TrimEnd(itemToTrim, time, affectTimeScale);
|
||
|
}
|
||
|
|
||
|
public static void DrawTrimGUI(WindowState state, TimelineItemGUI item, TrimEdge edge)
|
||
|
{
|
||
|
trimDrawer.DrawGUI(state, item.rect, modeColor, edge);
|
||
|
}
|
||
|
|
||
|
public static void FinishTrim()
|
||
|
{
|
||
|
s_CurrentTrimItem = null;
|
||
|
|
||
|
TimelineCursors.ClearCursor();
|
||
|
ClearEditMode();
|
||
|
|
||
|
TimelineEditor.Refresh(RefreshReason.ContentsModified);
|
||
|
}
|
||
|
|
||
|
public static void BeginMove(MoveItemHandler moveItemHandler)
|
||
|
{
|
||
|
s_CurrentMoveItemHandler = moveItemHandler;
|
||
|
moveMode.BeginMove(s_CurrentMoveItemHandler.movingItems);
|
||
|
}
|
||
|
|
||
|
public static void UpdateMove()
|
||
|
{
|
||
|
moveMode.UpdateMove(s_CurrentMoveItemHandler.movingItems);
|
||
|
}
|
||
|
|
||
|
public static void OnTrackDetach(IEnumerable<ItemsPerTrack> grabbedTrackItems)
|
||
|
{
|
||
|
moveMode.OnTrackDetach(grabbedTrackItems);
|
||
|
}
|
||
|
|
||
|
public static void HandleTrackSwitch(IEnumerable<ItemsPerTrack> grabbedTrackItems)
|
||
|
{
|
||
|
moveMode.HandleTrackSwitch(grabbedTrackItems);
|
||
|
}
|
||
|
|
||
|
public static bool AllowTrackSwitch()
|
||
|
{
|
||
|
return moveMode.AllowTrackSwitch();
|
||
|
}
|
||
|
|
||
|
public static double AdjustStartTime(WindowState state, ItemsPerTrack itemsGroup, double time)
|
||
|
{
|
||
|
return moveMode.AdjustStartTime(state, itemsGroup, time);
|
||
|
}
|
||
|
|
||
|
public static bool ValidateDrag(ItemsPerTrack itemsGroup)
|
||
|
{
|
||
|
return moveMode.ValidateMove(itemsGroup);
|
||
|
}
|
||
|
|
||
|
public static void DrawMoveGUI(WindowState state, IEnumerable<MovingItems> movingItems)
|
||
|
{
|
||
|
moveDrawer.DrawGUI(state, movingItems, modeColor);
|
||
|
}
|
||
|
|
||
|
public static void FinishMove()
|
||
|
{
|
||
|
var manipulatedItemsList = s_CurrentMoveItemHandler.movingItems;
|
||
|
moveMode.FinishMove(manipulatedItemsList);
|
||
|
|
||
|
foreach (var itemsGroup in manipulatedItemsList)
|
||
|
foreach (var item in itemsGroup.items)
|
||
|
item.parentTrack = itemsGroup.targetTrack;
|
||
|
|
||
|
s_CurrentMoveItemHandler = null;
|
||
|
|
||
|
TimelineCursors.ClearCursor();
|
||
|
ClearEditMode();
|
||
|
|
||
|
TimelineEditor.Refresh(RefreshReason.ContentsModified);
|
||
|
}
|
||
|
|
||
|
public static void FinalizeInsertItemsAtTime(IEnumerable<ItemsPerTrack> newItems, double requestedTime)
|
||
|
{
|
||
|
addDeleteMode.InsertItemsAtTime(newItems, requestedTime);
|
||
|
}
|
||
|
|
||
|
public static void PrepareItemsDelete(IEnumerable<ItemsPerTrack> newItems)
|
||
|
{
|
||
|
addDeleteMode.RemoveItems(newItems);
|
||
|
}
|
||
|
|
||
|
public static void HandleModeClutch()
|
||
|
{
|
||
|
if (Event.current.type == EventType.KeyDown && EditorGUI.IsEditingTextField())
|
||
|
return;
|
||
|
|
||
|
var prevType = editType;
|
||
|
|
||
|
if (Event.current.type == EventType.KeyDown)
|
||
|
{
|
||
|
var clutchEditType = GetSubEditType(Event.current.keyCode);
|
||
|
if (clutchEditType != EditType.None)
|
||
|
{
|
||
|
s_OverrideEditType = clutchEditType;
|
||
|
Event.current.Use();
|
||
|
}
|
||
|
}
|
||
|
else if (Event.current.type == EventType.KeyUp)
|
||
|
{
|
||
|
var clutchEditType = GetSubEditType(Event.current.keyCode);
|
||
|
if (clutchEditType == s_OverrideEditType)
|
||
|
{
|
||
|
s_OverrideEditType = EditType.None;
|
||
|
Event.current.Use();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (prevType != editType)
|
||
|
{
|
||
|
if (s_CurrentTrimItem != null)
|
||
|
{
|
||
|
trimMode.OnBeforeTrim(s_CurrentTrimItem, s_CurrentTrimDirection);
|
||
|
}
|
||
|
else if (s_CurrentMoveItemHandler != null)
|
||
|
{
|
||
|
if (s_CurrentMoveItemHandler.movingItems == null)
|
||
|
{
|
||
|
s_CurrentMoveItemHandler = null;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
foreach (var movingItems in s_CurrentMoveItemHandler.movingItems)
|
||
|
{
|
||
|
if (movingItems != null && movingItems.HasAnyDetachedParents())
|
||
|
{
|
||
|
foreach (var items in movingItems.items)
|
||
|
{
|
||
|
items.parentTrack = movingItems.originalTrack;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var movingSelection = s_CurrentMoveItemHandler.movingItems;
|
||
|
|
||
|
// Handle clutch key transition if needed
|
||
|
GetSubEditMode(prevType).moveItemMode.OnModeClutchExit(movingSelection);
|
||
|
moveMode.OnModeClutchEnter(movingSelection);
|
||
|
|
||
|
moveMode.BeginMove(movingSelection);
|
||
|
moveMode.HandleTrackSwitch(movingSelection);
|
||
|
|
||
|
UpdateMove();
|
||
|
s_CurrentMoveItemHandler.RefreshPreviewItems();
|
||
|
|
||
|
TimelineWindow.instance.state.rebuildGraph = true; // TODO Rebuild only if parent changed
|
||
|
}
|
||
|
|
||
|
TimelineWindow.instance.Repaint(); // TODO Refresh the toolbar without doing a full repaint?
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|