A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using UnityEditor.IMGUI.Controls;
5using UnityEngine;
6using UnityEngine.Playables;
7using UnityEngine.Timeline;
8
9namespace UnityEditor.Timeline
10{
11 class TimelineDataSource : TreeViewDataSource
12 {
13 readonly TimelineWindow m_TimelineWindow;
14 readonly TimelineTreeViewGUI m_ParentGUI;
15
16 public List<TimelineTrackBaseGUI> allTrackGuis { get; private set; }
17
18 TreeViewItem treeroot
19 {
20 get { return m_RootItem; }
21 }
22
23 public TimelineDataSource(TimelineTreeViewGUI parentGUI, TreeViewController treeView, TimelineWindow sequencerWindow)
24 : base(treeView)
25 {
26 m_TreeView.useExpansionAnimation = false;
27 m_TimelineWindow = sequencerWindow;
28 m_ParentGUI = parentGUI;
29 FetchData();
30 }
31
32 public override bool IsExpanded(TreeViewItem item)
33 {
34 if (!IsExpandable(item))
35 return true;
36
37 return IsExpanded(item.id);
38 }
39
40 public override bool IsExpandable(TreeViewItem item)
41 {
42 var expandable = false;
43
44 var track = item as TimelineTrackBaseGUI;
45
46 if (track != null)
47 expandable = track.expandable;
48
49 return expandable && item.hasChildren;
50 }
51
52 public sealed override void FetchData()
53 {
54 // create root item
55 m_RootItem = new TimelineGroupGUI(m_TreeView, m_ParentGUI, 1, 0, null, "root", null, true);
56
57 var tree = new Dictionary<TrackAsset, TimelineTrackBaseGUI>();
58
59 var filteredView = m_TimelineWindow.state.editSequence.asset.trackObjects;
60 allTrackGuis = new List<TimelineTrackBaseGUI>(filteredView.Count());
61
62 foreach (var t in filteredView)
63 {
64 CreateItem(t, ref tree, filteredView.OfType<TrackAsset>(), m_RootItem);
65 }
66
67 m_NeedRefreshRows = true;
68
69 SetExpanded(m_RootItem, true);
70 }
71
72 TimelineTrackBaseGUI CreateItem(ScriptableObject scriptableObject, ref Dictionary<TrackAsset, TimelineTrackBaseGUI> tree, IEnumerable<TrackAsset> selectedRows, TreeViewItem parentTreeViewItem)
73 {
74 // if a script doesn't load correctly, the trackAsset will be NULL, but the scriptableObject __should_ be intact (but == null will be true)
75 var trackAsset = scriptableObject as TrackAsset;
76
77 if (tree == null)
78 throw new ArgumentNullException("tree");
79
80 if (selectedRows == null)
81 throw new ArgumentNullException("selectedRows");
82
83 if (trackAsset != null && tree.ContainsKey(trackAsset))
84 return tree[trackAsset];
85
86 TimelineTrackBaseGUI parentItem = parentTreeViewItem as TimelineTrackBaseGUI;
87
88 // should we create the parent?
89 TrackAsset parentTrack = trackAsset != null ? (trackAsset.parent as TrackAsset) : null;
90 if (trackAsset != null && parentTrack != null && selectedRows.Contains(parentTrack))
91 {
92 parentItem = CreateItem(parentTrack, ref tree, selectedRows, parentTreeViewItem);
93 }
94
95 int theDepth = -1;
96 if (parentItem != null)
97 theDepth = parentItem.depth;
98 theDepth++;
99
100 TimelineTrackBaseGUI newItem;
101 if (trackAsset == null)
102 {
103 PlayableAsset parent = m_TimelineWindow.state.editSequence.asset;
104 if (parentItem != null && parentItem.track != null)
105 parent = parentItem.track;
106
107 newItem = new TimelineTrackErrorGUI(m_TreeView, m_ParentGUI, 0, theDepth, parentItem, "ERROR", scriptableObject, parent);
108 }
109 else if (trackAsset.GetType() != typeof(GroupTrack))
110 {
111 newItem = new TimelineTrackGUI(m_TreeView, m_ParentGUI, trackAsset.GetInstanceID(), theDepth, parentItem, trackAsset.name, trackAsset);
112 }
113 else
114 {
115 newItem = new TimelineGroupGUI(m_TreeView, m_ParentGUI, trackAsset.GetInstanceID(), theDepth, parentItem, trackAsset.name, trackAsset, false);
116 }
117
118 allTrackGuis.Add(newItem);
119
120 if (parentItem != null)
121 {
122 if (parentItem.children == null)
123 parentItem.children = new List<TreeViewItem>();
124 parentItem.children.Add(newItem);
125 SetExpanded(newItem, trackAsset.IsCollapsed());
126 }
127 else
128 {
129 m_RootItem = newItem;
130 SetExpanded(m_RootItem, true);
131 }
132
133 if (trackAsset != null)
134 tree[trackAsset] = newItem;
135
136 var actorAsAnimTrack = newItem.track as AnimationTrack;
137 bool isEditableInfiniteClip = actorAsAnimTrack != null && actorAsAnimTrack.ShouldShowInfiniteClipEditor();
138 if (isEditableInfiniteClip)
139 {
140 if (newItem.children == null)
141 newItem.children = new List<TreeViewItem>();
142 }
143 else if (trackAsset != null)
144 {
145 // check if clips on this track have animation, if so we inline a animationEditorTrack
146 bool clipHasAnimatableAnimationCurves = false;
147
148 for (var i = 0; i != newItem.track.clips.Length; ++i)
149 {
150 var curveClip = newItem.track.clips[i].curves;
151 var animationClip = newItem.track.clips[i].animationClip;
152
153 // prune out clip with zero curves
154 if (curveClip != null && curveClip.empty)
155 curveClip = null;
156
157 if (animationClip != null && animationClip.empty)
158 animationClip = null;
159
160 // prune out clips coming from FBX
161 if (animationClip != null && ((animationClip.hideFlags & HideFlags.NotEditable) != 0))
162 animationClip = null;
163
164 if (!newItem.track.clips[i].recordable)
165 animationClip = null;
166
167 clipHasAnimatableAnimationCurves = (curveClip != null) || (animationClip != null);
168 if (clipHasAnimatableAnimationCurves)
169 break;
170 }
171
172 if (clipHasAnimatableAnimationCurves)
173 {
174 if (newItem.children == null)
175 newItem.children = new List<TreeViewItem>();
176 }
177 }
178
179 if (trackAsset != null)
180 {
181 // Here we are using the internal subTrackObject so we can properly handle tracks whose script
182 // can't load (via ScriptableObject)
183 foreach (var subTrack in trackAsset.subTracksObjects)
184 {
185 CreateItem(subTrack, ref tree, selectedRows, newItem);
186 }
187 }
188 return newItem;
189 }
190
191 public override bool CanBeParent(TreeViewItem item)
192 {
193 // will prevent track becoming subtracks via dragging
194 TimelineTrackGUI track = item as TimelineTrackGUI;
195 if (track != null)
196 return false;
197
198 return true;
199 }
200
201 public void ExpandItems(TreeViewItem item)
202 {
203 if (treeroot == item)
204 {
205 SetExpanded(treeroot, true);
206 }
207
208 TimelineGroupGUI gui = item as TimelineGroupGUI;
209 if (gui != null && gui.track != null)
210 {
211 SetExpanded(item, !gui.track.IsCollapsed());
212 }
213
214 if (item.children != null)
215 {
216 for (int c = 0; c < item.children.Count; c++)
217 {
218 ExpandItems(item.children[c]);
219 }
220 }
221 }
222 }
223}