A game about forced loneliness, made by TACStudios
1#if UNITY_EDITOR
2using System.Collections.Generic;
3using UnityEngine;
4using UnityEngine.Playables;
5using UnityEngine.Timeline;
6using UnityEditor;
7
8namespace UnityEngine.Timeline
9{
10 /// <summary>
11 /// Animator to Editor Curve Binding cache. Used to prevent frequent calls to GetAnimatorBindings which can be costly
12 /// </summary>
13 class AnimatorBindingCache
14 {
15 public const string TRPlaceHolder = "TransformTR";
16 public const string ScalePlaceholder = "TransformScale";
17
18 struct AnimatorEntry
19 {
20 public int animatorID;
21 public bool applyRootMotion;
22 public bool humanoid;
23 }
24
25 class AnimatorEntryComparer : IEqualityComparer<AnimatorEntry>
26 {
27 public bool Equals(AnimatorEntry x, AnimatorEntry y) { return x.animatorID == y.animatorID && x.applyRootMotion == y.applyRootMotion && x.humanoid == y.humanoid; }
28 public int GetHashCode(AnimatorEntry obj) { return HashUtility.CombineHash(obj.animatorID, obj.applyRootMotion.GetHashCode(), obj.humanoid.GetHashCode()); }
29 public static readonly AnimatorEntryComparer Instance = new AnimatorEntryComparer();
30 }
31
32 readonly Dictionary<AnimatorEntry, EditorCurveBinding[]> m_AnimatorCache = new Dictionary<AnimatorEntry, EditorCurveBinding[]>(AnimatorEntryComparer.Instance);
33 readonly Dictionary<AnimationClip, EditorCurveBinding[]> m_ClipCache = new Dictionary<AnimationClip, EditorCurveBinding[]>();
34
35 private static readonly EditorCurveBinding[] kEmptyArray = new EditorCurveBinding[0];
36 private static readonly List<EditorCurveBinding> s_BindingScratchPad = new List<EditorCurveBinding>(1000);
37
38 public AnimatorBindingCache()
39 {
40 AnimationUtility.onCurveWasModified += OnCurveWasModified;
41 }
42
43 public EditorCurveBinding[] GetAnimatorBindings(GameObject gameObject)
44 {
45 if (gameObject == null)
46 return kEmptyArray;
47
48 Animator animator = gameObject.GetComponent<Animator>();
49 if (animator == null)
50 return kEmptyArray;
51
52 AnimatorEntry entry = new AnimatorEntry()
53 {
54 animatorID = animator.GetInstanceID(),
55 applyRootMotion = animator.applyRootMotion,
56 humanoid = animator.isHuman
57 };
58
59 EditorCurveBinding[] result = null;
60 if (m_AnimatorCache.TryGetValue(entry, out result))
61 return result;
62
63 s_BindingScratchPad.Clear();
64
65 // Replacement for AnimationMode.GetAnimatorBinding - this is faster and allocates kB instead of MB
66 var transforms = animator.GetComponentsInChildren<Transform>();
67 foreach (var t in transforms)
68 {
69 if (animator.IsBoneTransform(t))
70 s_BindingScratchPad.Add(EditorCurveBinding.FloatCurve(AnimationUtility.CalculateTransformPath(t, animator.transform), typeof(Transform), TRPlaceHolder));
71 }
72
73 var streamBindings = AnimationUtility.GetAnimationStreamBindings(animator.gameObject);
74 UpdateTransformBindings(streamBindings);
75 s_BindingScratchPad.AddRange(streamBindings);
76
77 result = new EditorCurveBinding[s_BindingScratchPad.Count];
78 s_BindingScratchPad.CopyTo(result);
79 m_AnimatorCache[entry] = result;
80 return result;
81 }
82
83 public EditorCurveBinding[] GetCurveBindings(AnimationClip clip)
84 {
85 if (clip == null)
86 return kEmptyArray;
87
88 EditorCurveBinding[] result;
89 if (!m_ClipCache.TryGetValue(clip, out result))
90 {
91 result = AnimationMode.GetCurveBindings(clip);
92 UpdateTransformBindings(result);
93 m_ClipCache[clip] = result;
94 }
95
96 return result;
97 }
98
99 private static void UpdateTransformBindings(EditorCurveBinding[] bindings)
100 {
101 for (int i = 0; i < bindings.Length; i++)
102 {
103 var binding = bindings[i];
104 if (AnimationPreviewUtilities.IsRootMotion(binding))
105 {
106 binding.type = typeof(Transform);
107 binding.propertyName = TRPlaceHolder;
108 }
109 else if (typeof(Transform).IsAssignableFrom(binding.type) && (binding.propertyName.StartsWith("m_LocalRotation.") || binding.propertyName.StartsWith("m_LocalPosition.")))
110 {
111 binding.propertyName = TRPlaceHolder;
112 }
113 else if (typeof(Transform).IsAssignableFrom(binding.type) && binding.propertyName.StartsWith("m_LocalScale."))
114 {
115 binding.propertyName = ScalePlaceholder;
116 }
117 bindings[i] = binding;
118 }
119 }
120
121 public void Clear()
122 {
123 m_AnimatorCache.Clear();
124 m_ClipCache.Clear();
125 }
126
127 void OnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType modification)
128 {
129 m_ClipCache.Remove(clip);
130 }
131 }
132}
133#endif