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