You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
5.3 KiB
C#

1 year ago
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Timeline;
namespace UnityEditor.Timeline
{
class Clipboard
{
class ExposedReferenceTable : IExposedPropertyTable
{
Dictionary<PropertyName, Object> m_ReferenceTable = new Dictionary<PropertyName, Object>();
public void SetReferenceValue(PropertyName id, Object value)
{
m_ReferenceTable[id] = value;
}
public Object GetReferenceValue(PropertyName id, out bool idValid)
{
Object reference;
idValid = m_ReferenceTable.TryGetValue(id, out reference);
return reference;
}
public void ClearReferenceValue(PropertyName id)
{
m_ReferenceTable.Remove(id);
}
public void Clear()
{
m_ReferenceTable.Clear();
}
}
public struct ClipboardTrackEntry
{
public TrackAsset item;
public TrackAsset parent;
public List<Object> bindings;
}
static readonly int kListInitialSize = 10;
readonly List<ItemsPerTrack> m_ItemsData = new List<ItemsPerTrack>(kListInitialSize);
readonly List<ClipboardTrackEntry> m_trackData = new List<ClipboardTrackEntry>(kListInitialSize);
TimelineAsset rootTimeline;
public readonly IExposedPropertyTable exposedPropertyTable = new ExposedReferenceTable();
public Clipboard()
{
rootTimeline = CreateTimeline();
EditorApplication.playModeStateChanged += OnPlayModeChanged;
}
public void CopyItems(IEnumerable<ITimelineItem> items)
{
using (new TimelineUndo.DisableUndoGuard(true))
{
var itemsByParent = items.ToLookup(i => i.parentTrack);
foreach (var itemsGroup in itemsByParent)
{
var parent = itemsGroup.Key;
var itemsList = new List<ITimelineItem>();
foreach (var item in itemsGroup)
{
if (item is ClipItem)
itemsList.Add(CopyItem((ClipItem)item));
else if (item is MarkerItem)
itemsList.Add(CopyItem((MarkerItem)item));
}
m_ItemsData.Add(new ItemsPerTrack(parent, itemsList));
}
}
}
ClipItem CopyItem(ClipItem clipItem)
{
var newClip = TimelineHelpers.Clone(clipItem.clip, TimelineWindow.instance.state.editSequence.director, exposedPropertyTable, rootTimeline);
return new ClipItem(newClip);
}
static MarkerItem CopyItem(MarkerItem markerItem)
{
var markerObject = markerItem.marker as Object;
if (markerObject != null)
{
var newMarker = Object.Instantiate(markerObject);
newMarker.name = markerObject.name;
return new MarkerItem((IMarker)newMarker);
}
return null;
}
public void CopyTracks(IEnumerable<TrackAsset> tracks)
{
using (new TimelineUndo.DisableUndoGuard(true))
{
foreach (var track in TrackExtensions.FilterTracks(tracks))
{
var newTrack = track.Duplicate(TimelineEditor.inspectedDirector, TimelineEditor.clipboard.exposedPropertyTable, rootTimeline);
var originalTracks = track.GetFlattenedChildTracks().Append(track);
var newTracks = newTrack.GetFlattenedChildTracks().Append(newTrack);
var toBind = new List<Object>();
// Collect all track bindings to duplicate
var originalIt = originalTracks.GetEnumerator();
var newIt = newTracks.GetEnumerator();
while (originalIt.MoveNext() && newIt.MoveNext())
{
toBind.Add(TimelineEditor.inspectedDirector != null ? TimelineEditor.inspectedDirector.GetGenericBinding(originalIt.Current) : null);
}
m_trackData.Add(new ClipboardTrackEntry { item = newTrack, parent = track.parent as TrackAsset, bindings = toBind });
}
}
}
public IEnumerable<ClipboardTrackEntry> GetTracks()
{
return m_trackData;
}
public IEnumerable<ItemsPerTrack> GetCopiedItems()
{
return m_ItemsData;
}
public void Clear()
{
m_ItemsData.Clear();
m_trackData.Clear();
rootTimeline = CreateTimeline();
((ExposedReferenceTable)exposedPropertyTable).Clear();
}
private void OnPlayModeChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.EnteredPlayMode)
Clear();
}
static TimelineAsset CreateTimeline()
{
var timeline = ScriptableObject.CreateInstance<TimelineAsset>();
timeline.hideFlags |= HideFlags.DontSave;
timeline.name = "Clipboard";
return timeline;
}
}
}