A game about forced loneliness, made by TACStudios
at master 427 lines 14 kB view raw
1using System.Collections.Generic; 2using System.Linq; 3using UnityEngine; 4using UnityEditor; 5using UnityEditorInternal; 6 7namespace UnityEditor.Timeline 8{ 9 struct CurveBindingPair 10 { 11 public EditorCurveBinding binding; 12 public AnimationCurve curve; 13 public ObjectReferenceKeyframe[] objectCurve; 14 } 15 16 class CurveBindingGroup 17 { 18 public CurveBindingPair[] curveBindingPairs { get; set; } 19 public Vector2 timeRange { get; set; } 20 public Vector2 valueRange { get; set; } 21 22 public bool isFloatCurve 23 { 24 get 25 { 26 return curveBindingPairs != null && curveBindingPairs.Length > 0 && 27 curveBindingPairs[0].curve != null; 28 } 29 } 30 31 public bool isObjectCurve 32 { 33 get 34 { 35 return curveBindingPairs != null && curveBindingPairs.Length > 0 && 36 curveBindingPairs[0].objectCurve != null; 37 } 38 } 39 40 public int count 41 { 42 get 43 { 44 if (curveBindingPairs == null) 45 return 0; 46 return curveBindingPairs.Length; 47 } 48 } 49 } 50 51 class AnimationClipCurveInfo 52 { 53 bool m_CurveDirty = true; 54 bool m_KeysDirty = true; 55 56 public bool dirty 57 { 58 get { return m_CurveDirty; } 59 set 60 { 61 m_CurveDirty = value; 62 if (m_CurveDirty) 63 { 64 m_KeysDirty = true; 65 if (m_groupings != null) 66 m_groupings.Clear(); 67 } 68 } 69 } 70 71 public AnimationCurve[] curves; 72 public EditorCurveBinding[] bindings; 73 74 public EditorCurveBinding[] objectBindings; 75 public List<ObjectReferenceKeyframe[]> objectCurves; 76 77 Dictionary<string, CurveBindingGroup> m_groupings; 78 79 // to tell whether the cache has changed 80 public int version { get; private set; } 81 82 float[] m_KeyTimes; 83 84 Dictionary<EditorCurveBinding, float[]> m_individualBindinsKey; 85 86 public float[] keyTimes 87 { 88 get 89 { 90 if (m_KeysDirty || m_KeyTimes == null) 91 { 92 RebuildKeyCache(); 93 } 94 return m_KeyTimes; 95 } 96 } 97 98 public float[] GetCurveTimes(EditorCurveBinding curve) 99 { 100 return GetCurveTimes(new[] { curve }); 101 } 102 103 public float[] GetCurveTimes(EditorCurveBinding[] curves) 104 { 105 if (m_KeysDirty || m_KeyTimes == null) 106 { 107 RebuildKeyCache(); 108 } 109 110 var keyTimes = new List<float>(); 111 for (int i = 0; i < curves.Length; i++) 112 { 113 var c = curves[i]; 114 if (m_individualBindinsKey.ContainsKey(c)) 115 { 116 keyTimes.AddRange(m_individualBindinsKey[c]); 117 } 118 } 119 return keyTimes.ToArray(); 120 } 121 122 void RebuildKeyCache() 123 { 124 m_individualBindinsKey = new Dictionary<EditorCurveBinding, float[]>(); 125 126 List<float> keys = curves.SelectMany(y => y.keys).Select(z => z.time).ToList(); 127 for (int i = 0; i < objectCurves.Count; i++) 128 { 129 var kf = objectCurves[i]; 130 keys.AddRange(kf.Select(x => x.time)); 131 } 132 133 for (int b = 0; b < bindings.Count(); b++) 134 { 135 m_individualBindinsKey.Add(bindings[b], curves[b].keys.Select(k => k.time).Distinct().ToArray()); 136 } 137 138 m_KeyTimes = keys.OrderBy(x => x).Distinct().ToArray(); 139 m_KeysDirty = false; 140 } 141 142 public void Update(AnimationClip clip) 143 { 144 List<EditorCurveBinding> postfilter = new List<EditorCurveBinding>(); 145 var clipBindings = AnimationUtility.GetCurveBindings(clip); 146 for (int i = 0; i < clipBindings.Length; i++) 147 { 148 var bind = clipBindings[i]; 149 if (!bind.propertyName.Contains("LocalRotation.w")) 150 postfilter.Add(RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(bind, clip)); 151 } 152 bindings = postfilter.ToArray(); 153 154 curves = new AnimationCurve[bindings.Length]; 155 for (int i = 0; i < bindings.Length; i++) 156 { 157 curves[i] = AnimationUtility.GetEditorCurve(clip, bindings[i]); 158 } 159 160 objectBindings = AnimationUtility.GetObjectReferenceCurveBindings(clip); 161 objectCurves = new List<ObjectReferenceKeyframe[]>(objectBindings.Length); 162 for (int i = 0; i < objectBindings.Length; i++) 163 { 164 objectCurves.Add(AnimationUtility.GetObjectReferenceCurve(clip, objectBindings[i])); 165 } 166 167 m_CurveDirty = false; 168 m_KeysDirty = true; 169 170 version = version + 1; 171 } 172 173 public bool GetBindingForCurve(AnimationCurve curve, ref EditorCurveBinding binding) 174 { 175 for (int i = 0; i < curves.Length; i++) 176 { 177 if (curve == curves[i]) 178 { 179 binding = bindings[i]; 180 return true; 181 } 182 } 183 return false; 184 } 185 186 public AnimationCurve GetCurveForBinding(EditorCurveBinding binding) 187 { 188 for (int i = 0; i < curves.Length; i++) 189 { 190 if (binding.Equals(bindings[i])) 191 { 192 return curves[i]; 193 } 194 } 195 return null; 196 } 197 198 public ObjectReferenceKeyframe[] GetObjectCurveForBinding(EditorCurveBinding binding) 199 { 200 if (objectCurves == null) 201 return null; 202 203 for (int i = 0; i < objectCurves.Count; i++) 204 { 205 if (binding.Equals(objectBindings[i])) 206 { 207 return objectCurves[i]; 208 } 209 } 210 return null; 211 } 212 213 // given a groupID, get the list of curve bindings 214 public CurveBindingGroup GetGroupBinding(string groupID) 215 { 216 if (m_groupings == null) 217 m_groupings = new Dictionary<string, CurveBindingGroup>(); 218 219 CurveBindingGroup result = null; 220 if (!m_groupings.TryGetValue(groupID, out result)) 221 { 222 result = new CurveBindingGroup(); 223 result.timeRange = new Vector2(float.MaxValue, float.MinValue); 224 result.valueRange = new Vector2(float.MaxValue, float.MinValue); 225 List<CurveBindingPair> found = new List<CurveBindingPair>(); 226 for (int i = 0; i < bindings.Length; i++) 227 { 228 if (bindings[i].GetGroupID() == groupID) 229 { 230 CurveBindingPair pair = new CurveBindingPair(); 231 pair.binding = bindings[i]; 232 pair.curve = curves[i]; 233 found.Add(pair); 234 235 for (int k = 0; k < curves[i].keys.Length; k++) 236 { 237 var key = curves[i].keys[k]; 238 result.timeRange = new Vector2(Mathf.Min(key.time, result.timeRange.x), Mathf.Max(key.time, result.timeRange.y)); 239 result.valueRange = new Vector2(Mathf.Min(key.value, result.valueRange.x), Mathf.Max(key.value, result.valueRange.y)); 240 } 241 } 242 } 243 for (int i = 0; i < objectBindings.Length; i++) 244 { 245 if (objectBindings[i].GetGroupID() == groupID) 246 { 247 CurveBindingPair pair = new CurveBindingPair(); 248 pair.binding = objectBindings[i]; 249 pair.objectCurve = objectCurves[i]; 250 found.Add(pair); 251 252 for (int k = 0; k < objectCurves[i].Length; k++) 253 { 254 var key = objectCurves[i][k]; 255 result.timeRange = new Vector2(Mathf.Min(key.time, result.timeRange.x), Mathf.Max(key.time, result.timeRange.y)); 256 } 257 } 258 } 259 260 result.curveBindingPairs = found.OrderBy(x => AnimationWindowUtility.GetComponentIndex(x.binding.propertyName)).ToArray(); 261 262 m_groupings.Add(groupID, result); 263 } 264 return result; 265 } 266 } 267 268 // Cache for storing the animation clip data 269 class AnimationClipCurveCache 270 { 271 static AnimationClipCurveCache s_Instance; 272 Dictionary<AnimationClip, AnimationClipCurveInfo> m_ClipCache = new Dictionary<AnimationClip, AnimationClipCurveInfo>(); 273 bool m_IsEnabled; 274 275 276 public static AnimationClipCurveCache Instance 277 { 278 get 279 { 280 if (s_Instance == null) 281 { 282 s_Instance = new AnimationClipCurveCache(); 283 } 284 285 return s_Instance; 286 } 287 } 288 289 public void OnEnable() 290 { 291 if (!m_IsEnabled) 292 { 293 AnimationUtility.onCurveWasModified += OnCurveWasModified; 294 m_IsEnabled = true; 295 } 296 } 297 298 public void OnDisable() 299 { 300 if (m_IsEnabled) 301 { 302 AnimationUtility.onCurveWasModified -= OnCurveWasModified; 303 m_IsEnabled = false; 304 } 305 } 306 307 // callback when a curve is edited. Force the cache to update next time it's accessed 308 void OnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType modification) 309 { 310 AnimationClipCurveInfo data; 311 if (m_ClipCache.TryGetValue(clip, out data)) 312 { 313 data.dirty = true; 314 } 315 } 316 317 public AnimationClipCurveInfo GetCurveInfo(AnimationClip clip) 318 { 319 AnimationClipCurveInfo data; 320 if (clip == null) 321 return null; 322 if (!m_ClipCache.TryGetValue(clip, out data)) 323 { 324 data = new AnimationClipCurveInfo(); 325 data.dirty = true; 326 m_ClipCache[clip] = data; 327 } 328 if (data.dirty) 329 { 330 data.Update(clip); 331 } 332 return data; 333 } 334 335 public void ClearCachedProxyClips() 336 { 337 var toRemove = new List<AnimationClip>(); 338 foreach (var entry in m_ClipCache) 339 { 340 var clip = entry.Key; 341 if (clip != null && (clip.hideFlags & HideFlags.HideAndDontSave) == HideFlags.HideAndDontSave) 342 toRemove.Add(clip); 343 } 344 345 foreach (var clip in toRemove) 346 { 347 m_ClipCache.Remove(clip); 348 Object.DestroyImmediate(clip, true); 349 } 350 } 351 352 public void Clear() 353 { 354 ClearCachedProxyClips(); 355 m_ClipCache.Clear(); 356 } 357 } 358 359 static class EditorCurveBindingExtension 360 { 361 // identifier to generate an id thats the same for all curves in the same group 362 public static string GetGroupID(this EditorCurveBinding binding) 363 { 364 return binding.type + AnimationWindowUtility.GetPropertyGroupName(binding.propertyName); 365 } 366 } 367 368 369 static class CurveBindingGroupExtensions 370 { 371 // Extentions to determine curve types 372 public static bool IsEnableGroup(this CurveBindingGroup curves) 373 { 374 return curves.isFloatCurve && curves.count == 1 && curves.curveBindingPairs[0].binding.propertyName == "m_Enabled"; 375 } 376 377 public static bool IsVectorGroup(this CurveBindingGroup curves) 378 { 379 if (!curves.isFloatCurve) 380 return false; 381 if (curves.count <= 1 || curves.count > 4) 382 return false; 383 char l = curves.curveBindingPairs[0].binding.propertyName.Last(); 384 return l == 'x' || l == 'y' || l == 'z' || l == 'w'; 385 } 386 387 public static bool IsColorGroup(this CurveBindingGroup curves) 388 { 389 if (!curves.isFloatCurve) 390 return false; 391 if (curves.count != 3 && curves.count != 4) 392 return false; 393 char l = curves.curveBindingPairs[0].binding.propertyName.Last(); 394 return l == 'r' || l == 'g' || l == 'b' || l == 'a'; 395 } 396 397 public static string GetDescription(this CurveBindingGroup group, float t) 398 { 399 string result = string.Empty; 400 if (group.isFloatCurve) 401 { 402 if (group.count > 1) 403 { 404 result += "(" + group.curveBindingPairs[0].curve.Evaluate(t).ToString("0.##"); 405 for (int j = 1; j < group.curveBindingPairs.Length; j++) 406 { 407 result += "," + group.curveBindingPairs[j].curve.Evaluate(t).ToString("0.##"); 408 } 409 result += ")"; 410 } 411 else 412 { 413 result = group.curveBindingPairs[0].curve.Evaluate(t).ToString("0.##"); 414 } 415 } 416 else if (group.isObjectCurve) 417 { 418 Object obj = null; 419 if (group.curveBindingPairs[0].objectCurve.Length > 0) 420 obj = CurveEditUtility.Evaluate(group.curveBindingPairs[0].objectCurve, t); 421 result = (obj == null ? "None" : obj.name); 422 } 423 424 return result; 425 } 426 } 427}