A game about forced loneliness, made by TACStudios
at master 155 lines 5.6 kB view raw
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using UnityEngine; 5using UnityEngine.Playables; 6using UnityEngine.Timeline; 7 8namespace UnityEditor.Timeline 9{ 10 class CustomTimelineEditorCache 11 { 12 static class SubClassCache<TEditorClass> where TEditorClass : class, new() 13 { 14 private static Type[] s_SubClasses = null; 15 private static readonly TEditorClass s_DefaultInstance = new TEditorClass(); 16 private static readonly Dictionary<System.Type, TEditorClass> s_TypeMap = new Dictionary<Type, TEditorClass>(); 17 18 public static TEditorClass DefaultInstance 19 { 20 get { return s_DefaultInstance; } 21 } 22 23 static Type[] SubClasses 24 { 25 get 26 { 27 // order the subclass array by built-ins then user defined so built-in classes are chosen first 28 return s_SubClasses ?? 29 (s_SubClasses = TypeCache.GetTypesDerivedFrom<TEditorClass>().OrderBy(t => t.Assembly == typeof(UnityEditor.Timeline.TimelineEditor).Assembly ? 1 : 0).ToArray()); 30 } 31 } 32 33 public static TEditorClass GetEditorForType(Type type) 34 { 35 TEditorClass editorClass = null; 36 if (!s_TypeMap.TryGetValue(type, out editorClass) || editorClass == null) 37 { 38 Type editorClassType = null; 39 Type searchType = type; 40 while (searchType != null) 41 { 42 // search our way up the runtime class hierarchy so we get the best match 43 editorClassType = GetExactEditorClassForType(searchType); 44 if (editorClassType != null) 45 break; 46 searchType = searchType.BaseType; 47 } 48 49 if (editorClassType == null) 50 { 51 editorClass = s_DefaultInstance; 52 } 53 else 54 { 55 try 56 { 57 editorClass = (TEditorClass)Activator.CreateInstance(editorClassType); 58 } 59 catch (Exception e) 60 { 61 Debug.LogWarningFormat("Could not create a Timeline editor class of type {0}: {1}", editorClassType, e.Message); 62 editorClass = s_DefaultInstance; 63 } 64 } 65 66 s_TypeMap[type] = editorClass; 67 } 68 69 return editorClass; 70 } 71 72 private static Type GetExactEditorClassForType(Type type) 73 { 74 foreach (var subClass in SubClasses) 75 { 76 // first check for exact match 77 var attr = (CustomTimelineEditorAttribute)Attribute.GetCustomAttribute(subClass, typeof(CustomTimelineEditorAttribute), false); 78 if (attr != null && attr.classToEdit == type) 79 { 80 return subClass; 81 } 82 } 83 84 return null; 85 } 86 87 public static void Clear() 88 { 89 s_TypeMap.Clear(); 90 s_SubClasses = null; 91 } 92 } 93 94 public static TEditorClass GetEditorForType<TEditorClass, TRuntimeClass>(Type type) where TEditorClass : class, new() 95 { 96 if (type == null) 97 throw new ArgumentNullException(nameof(type)); 98 99 if (!typeof(TRuntimeClass).IsAssignableFrom(type)) 100 throw new ArgumentException(type.FullName + " does not inherit from" + typeof(TRuntimeClass)); 101 102 return SubClassCache<TEditorClass>.GetEditorForType(type); 103 } 104 105 public static void ClearCache<TEditorClass>() where TEditorClass : class, new() 106 { 107 SubClassCache<TEditorClass>.Clear(); 108 } 109 110 public static ClipEditor GetClipEditor(TimelineClip clip) 111 { 112 if (clip == null) 113 throw new ArgumentNullException(nameof(clip)); 114 115 var type = typeof(IPlayableAsset); 116 if (clip.asset != null) 117 type = clip.asset.GetType(); 118 119 if (!typeof(IPlayableAsset).IsAssignableFrom(type)) 120 return GetDefaultClipEditor(); 121 122 return GetEditorForType<ClipEditor, IPlayableAsset>(type); 123 } 124 125 public static ClipEditor GetDefaultClipEditor() 126 { 127 return SubClassCache<ClipEditor>.DefaultInstance; 128 } 129 130 public static TrackEditor GetTrackEditor(TrackAsset track) 131 { 132 if (track == null) 133 throw new ArgumentNullException(nameof(track)); 134 135 return GetEditorForType<TrackEditor, TrackAsset>(track.GetType()); 136 } 137 138 public static TrackEditor GetDefaultTrackEditor() 139 { 140 return SubClassCache<TrackEditor>.DefaultInstance; 141 } 142 143 public static MarkerEditor GetMarkerEditor(IMarker marker) 144 { 145 if (marker == null) 146 throw new ArgumentNullException(nameof(marker)); 147 return GetEditorForType<MarkerEditor, IMarker>(marker.GetType()); 148 } 149 150 public static MarkerEditor GetDefaultMarkerEditor() 151 { 152 return SubClassCache<MarkerEditor>.DefaultInstance; 153 } 154 } 155}