231 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			231 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | using System.Linq; | ||
|  | using UnityEngine; | ||
|  | using UnityEngine.Playables; | ||
|  | using UnityEngine.Timeline; | ||
|  | 
 | ||
|  | #if UNITY_6000_2_OR_NEWER | ||
|  | using TreeViewController = UnityEditor.IMGUI.Controls.TreeViewController<int>; | ||
|  | using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>; | ||
|  | using TreeViewDataSource = UnityEditor.IMGUI.Controls.TreeViewDataSource<int>; | ||
|  | #else | ||
|  | using UnityEditor.IMGUI.Controls; | ||
|  | #endif | ||
|  | 
 | ||
|  | namespace UnityEditor.Timeline | ||
|  | { | ||
|  |     class TimelineDataSource : TreeViewDataSource | ||
|  |     { | ||
|  |         readonly TimelineWindow m_TimelineWindow; | ||
|  |         readonly TimelineTreeViewGUI m_ParentGUI; | ||
|  | 
 | ||
|  |         public List<TimelineTrackBaseGUI> allTrackGuis { get; private set; } | ||
|  | 
 | ||
|  |         TreeViewItem treeroot | ||
|  |         { | ||
|  |             get { return m_RootItem; } | ||
|  |         } | ||
|  | 
 | ||
|  |         public TimelineDataSource(TimelineTreeViewGUI parentGUI, TreeViewController treeView, TimelineWindow sequencerWindow) | ||
|  |             : base(treeView) | ||
|  |         { | ||
|  |             m_TreeView.useExpansionAnimation = false; | ||
|  |             m_TimelineWindow = sequencerWindow; | ||
|  |             m_ParentGUI = parentGUI; | ||
|  |             FetchData(); | ||
|  |         } | ||
|  | 
 | ||
|  |         public override bool IsExpanded(TreeViewItem item) | ||
|  |         { | ||
|  |             if (!IsExpandable(item)) | ||
|  |                 return true; | ||
|  | 
 | ||
|  |             return IsExpanded(item.id); | ||
|  |         } | ||
|  | 
 | ||
|  |         public override bool IsExpandable(TreeViewItem item) | ||
|  |         { | ||
|  |             var expandable = false; | ||
|  | 
 | ||
|  |             var track = item as TimelineTrackBaseGUI; | ||
|  | 
 | ||
|  |             if (track != null) | ||
|  |                 expandable = track.expandable; | ||
|  | 
 | ||
|  |             return expandable && item.hasChildren; | ||
|  |         } | ||
|  | 
 | ||
|  |         public sealed override void FetchData() | ||
|  |         { | ||
|  |             // create root item | ||
|  |             m_RootItem = new TimelineGroupGUI(m_TreeView, m_ParentGUI, 1, 0, null, "root", null, true); | ||
|  | 
 | ||
|  |             var tree = new Dictionary<TrackAsset, TimelineTrackBaseGUI>(); | ||
|  | 
 | ||
|  |             var filteredView = m_TimelineWindow.state.editSequence.asset.trackObjects; | ||
|  |             allTrackGuis = new List<TimelineTrackBaseGUI>(filteredView.Count()); | ||
|  | 
 | ||
|  |             foreach (var t in filteredView) | ||
|  |             { | ||
|  |                 CreateItem(t, ref tree, filteredView.OfType<TrackAsset>(), m_RootItem); | ||
|  |             } | ||
|  | 
 | ||
|  |             m_NeedRefreshRows = true; | ||
|  | 
 | ||
|  |             SetExpanded(m_RootItem, true); | ||
|  |         } | ||
|  | 
 | ||
|  |         TimelineTrackBaseGUI CreateItem(ScriptableObject scriptableObject, ref Dictionary<TrackAsset, TimelineTrackBaseGUI> tree, IEnumerable<TrackAsset> selectedRows, TreeViewItem parentTreeViewItem) | ||
|  |         { | ||
|  |             // if a script doesn't load correctly, the trackAsset will be NULL, but the scriptableObject __should_ be intact (but == null will be true) | ||
|  |             var trackAsset = scriptableObject as TrackAsset; | ||
|  | 
 | ||
|  |             if (tree == null) | ||
|  |                 throw new ArgumentNullException("tree"); | ||
|  | 
 | ||
|  |             if (selectedRows == null) | ||
|  |                 throw new ArgumentNullException("selectedRows"); | ||
|  | 
 | ||
|  |             if (trackAsset != null && tree.ContainsKey(trackAsset)) | ||
|  |                 return tree[trackAsset]; | ||
|  | 
 | ||
|  |             TimelineTrackBaseGUI parentItem = parentTreeViewItem as TimelineTrackBaseGUI; | ||
|  | 
 | ||
|  |             // should we create the parent? | ||
|  |             TrackAsset parentTrack = trackAsset != null ? (trackAsset.parent as TrackAsset) : null; | ||
|  |             if (trackAsset != null && parentTrack != null && selectedRows.Contains(parentTrack)) | ||
|  |             { | ||
|  |                 parentItem = CreateItem(parentTrack, ref tree, selectedRows, parentTreeViewItem); | ||
|  |             } | ||
|  | 
 | ||
|  |             int theDepth = -1; | ||
|  |             if (parentItem != null) | ||
|  |                 theDepth = parentItem.depth; | ||
|  |             theDepth++; | ||
|  | 
 | ||
|  |             TimelineTrackBaseGUI newItem; | ||
|  |             if (trackAsset == null) | ||
|  |             { | ||
|  |                 PlayableAsset parent = m_TimelineWindow.state.editSequence.asset; | ||
|  |                 if (parentItem != null && parentItem.track != null) | ||
|  |                     parent = parentItem.track; | ||
|  | 
 | ||
|  |                 newItem = new TimelineTrackErrorGUI(m_TreeView, m_ParentGUI, 0, theDepth, parentItem, "ERROR", scriptableObject, parent); | ||
|  |             } | ||
|  |             else if (trackAsset.GetType() != typeof(GroupTrack)) | ||
|  |             { | ||
|  |                 newItem = new TimelineTrackGUI(m_TreeView, m_ParentGUI, trackAsset.GetInstanceID(), theDepth, parentItem, trackAsset.name, trackAsset); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 newItem = new TimelineGroupGUI(m_TreeView, m_ParentGUI, trackAsset.GetInstanceID(), theDepth, parentItem, trackAsset.name, trackAsset, false); | ||
|  |             } | ||
|  | 
 | ||
|  |             allTrackGuis.Add(newItem); | ||
|  | 
 | ||
|  |             if (parentItem != null) | ||
|  |             { | ||
|  |                 if (parentItem.children == null) | ||
|  |                     parentItem.children = new List<TreeViewItem>(); | ||
|  |                 parentItem.children.Add(newItem); | ||
|  |                 SetExpanded(newItem, trackAsset.IsCollapsed()); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 m_RootItem = newItem; | ||
|  |                 SetExpanded(m_RootItem, true); | ||
|  |             } | ||
|  | 
 | ||
|  |             if (trackAsset != null) | ||
|  |                 tree[trackAsset] = newItem; | ||
|  | 
 | ||
|  |             var actorAsAnimTrack = newItem.track as AnimationTrack; | ||
|  |             bool isEditableInfiniteClip = actorAsAnimTrack != null && actorAsAnimTrack.ShouldShowInfiniteClipEditor(); | ||
|  |             if (isEditableInfiniteClip) | ||
|  |             { | ||
|  |                 if (newItem.children == null) | ||
|  |                     newItem.children = new List<TreeViewItem>(); | ||
|  |             } | ||
|  |             else if (trackAsset != null) | ||
|  |             { | ||
|  |                 // check if clips on this track have animation, if so we inline a animationEditorTrack | ||
|  |                 bool clipHasAnimatableAnimationCurves = false; | ||
|  | 
 | ||
|  |                 for (var i = 0; i != newItem.track.clips.Length; ++i) | ||
|  |                 { | ||
|  |                     var curveClip = newItem.track.clips[i].curves; | ||
|  |                     var animationClip = newItem.track.clips[i].animationClip; | ||
|  | 
 | ||
|  |                     // prune out clip with zero curves | ||
|  |                     if (curveClip != null && curveClip.empty) | ||
|  |                         curveClip = null; | ||
|  | 
 | ||
|  |                     if (animationClip != null && animationClip.empty) | ||
|  |                         animationClip = null; | ||
|  | 
 | ||
|  |                     // prune out clips coming from FBX | ||
|  |                     if (animationClip != null && ((animationClip.hideFlags & HideFlags.NotEditable) != 0)) | ||
|  |                         animationClip = null; | ||
|  | 
 | ||
|  |                     if (!newItem.track.clips[i].recordable) | ||
|  |                         animationClip = null; | ||
|  | 
 | ||
|  |                     clipHasAnimatableAnimationCurves = (curveClip != null) || (animationClip != null); | ||
|  |                     if (clipHasAnimatableAnimationCurves) | ||
|  |                         break; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (clipHasAnimatableAnimationCurves) | ||
|  |                 { | ||
|  |                     if (newItem.children == null) | ||
|  |                         newItem.children = new List<TreeViewItem>(); | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             if (trackAsset != null) | ||
|  |             { | ||
|  |                 // Here we are using the internal subTrackObject so we can properly handle tracks whose script | ||
|  |                 //  can't load (via ScriptableObject) | ||
|  |                 foreach (var subTrack in trackAsset.subTracksObjects) | ||
|  |                 { | ||
|  |                     CreateItem(subTrack, ref tree, selectedRows, newItem); | ||
|  |                 } | ||
|  |             } | ||
|  |             return newItem; | ||
|  |         } | ||
|  | 
 | ||
|  |         public override bool CanBeParent(TreeViewItem item) | ||
|  |         { | ||
|  |             // will prevent track becoming subtracks via dragging | ||
|  |             TimelineTrackGUI track = item as TimelineTrackGUI; | ||
|  |             if (track != null) | ||
|  |                 return false; | ||
|  | 
 | ||
|  |             return true; | ||
|  |         } | ||
|  | 
 | ||
|  |         public void ExpandItems(TreeViewItem item) | ||
|  |         { | ||
|  |             if (treeroot == item) | ||
|  |             { | ||
|  |                 SetExpanded(treeroot, true); | ||
|  |             } | ||
|  | 
 | ||
|  |             TimelineGroupGUI gui = item as TimelineGroupGUI; | ||
|  |             if (gui != null && gui.track != null) | ||
|  |             { | ||
|  |                 SetExpanded(item, !gui.track.IsCollapsed()); | ||
|  |             } | ||
|  | 
 | ||
|  |             if (item.children != null) | ||
|  |             { | ||
|  |                 for (int c = 0; c < item.children.Count; c++) | ||
|  |                 { | ||
|  |                     ExpandItems(item.children[c]); | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } |