You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
5.1 KiB
133 lines
5.1 KiB
#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
|
|
|