diff options
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs')
| -rw-r--r-- | Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs new file mode 100644 index 0000000..8570a73 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs @@ -0,0 +1,436 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEditor; +using UnityEditorInternal; + +namespace UnityEditor.Timeline +{ + struct CurveBindingPair + { + public EditorCurveBinding binding; + public AnimationCurve curve; + public ObjectReferenceKeyframe[] objectCurve; + } + + class CurveBindingGroup + { + public CurveBindingPair[] curveBindingPairs { get; set; } + public Vector2 timeRange { get; set; } + public Vector2 valueRange { get; set; } + + public bool isFloatCurve + { + get + { + return curveBindingPairs != null && curveBindingPairs.Length > 0 && + curveBindingPairs[0].curve != null; + } + } + + public bool isObjectCurve + { + get + { + return curveBindingPairs != null && curveBindingPairs.Length > 0 && + curveBindingPairs[0].objectCurve != null; + } + } + + public int count + { + get + { + if (curveBindingPairs == null) + return 0; + return curveBindingPairs.Length; + } + } + } + + class AnimationClipCurveInfo + { + bool m_CurveDirty = true; + bool m_KeysDirty = true; + + public bool dirty + { + get { return m_CurveDirty; } + set + { + m_CurveDirty = value; + if (m_CurveDirty) + { + m_KeysDirty = true; + if (m_groupings != null) + m_groupings.Clear(); + } + } + } + + public AnimationCurve[] curves; + public EditorCurveBinding[] bindings; + + public EditorCurveBinding[] objectBindings; + public List<ObjectReferenceKeyframe[]> objectCurves; + + Dictionary<string, CurveBindingGroup> m_groupings; + + // to tell whether the cache has changed + public int version { get; private set; } + + float[] m_KeyTimes; + + Dictionary<EditorCurveBinding, float[]> m_individualBindinsKey; + + public float[] keyTimes + { + get + { + if (m_KeysDirty || m_KeyTimes == null) + { + RebuildKeyCache(); + } + return m_KeyTimes; + } + } + + public float[] GetCurveTimes(EditorCurveBinding curve) + { + return GetCurveTimes(new[] { curve }); + } + + public float[] GetCurveTimes(EditorCurveBinding[] curves) + { + if (m_KeysDirty || m_KeyTimes == null) + { + RebuildKeyCache(); + } + + var keyTimes = new List<float>(); + for (int i = 0; i < curves.Length; i++) + { + var c = curves[i]; + if (m_individualBindinsKey.ContainsKey(c)) + { + keyTimes.AddRange(m_individualBindinsKey[c]); + } + } + return keyTimes.ToArray(); + } + + void RebuildKeyCache() + { + m_individualBindinsKey = new Dictionary<EditorCurveBinding, float[]>(); + + List<float> keys = curves.SelectMany(y => y.keys).Select(z => z.time).ToList(); + for (int i = 0; i < objectCurves.Count; i++) + { + var kf = objectCurves[i]; + keys.AddRange(kf.Select(x => x.time)); + } + + for (int b = 0; b < bindings.Count(); b++) + { + m_individualBindinsKey.Add(bindings[b], curves[b].keys.Select(k => k.time).Distinct().ToArray()); + } + + m_KeyTimes = keys.OrderBy(x => x).Distinct().ToArray(); + m_KeysDirty = false; + } + + public void Update(AnimationClip clip) + { + List<EditorCurveBinding> postfilter = new List<EditorCurveBinding>(); + var clipBindings = AnimationUtility.GetCurveBindings(clip); + for (int i = 0; i < clipBindings.Length; i++) + { + var bind = clipBindings[i]; + if (!bind.propertyName.Contains("LocalRotation.w")) + postfilter.Add(RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(bind, clip)); + } + bindings = postfilter.ToArray(); + + curves = new AnimationCurve[bindings.Length]; + for (int i = 0; i < bindings.Length; i++) + { + curves[i] = AnimationUtility.GetEditorCurve(clip, bindings[i]); + } + + objectBindings = AnimationUtility.GetObjectReferenceCurveBindings(clip); + objectCurves = new List<ObjectReferenceKeyframe[]>(objectBindings.Length); + for (int i = 0; i < objectBindings.Length; i++) + { + objectCurves.Add(AnimationUtility.GetObjectReferenceCurve(clip, objectBindings[i])); + } + + m_CurveDirty = false; + m_KeysDirty = true; + + version = version + 1; + } + + public bool GetBindingForCurve(AnimationCurve curve, ref EditorCurveBinding binding) + { + for (int i = 0; i < curves.Length; i++) + { + if (curve == curves[i]) + { + binding = bindings[i]; + return true; + } + } + return false; + } + + public AnimationCurve GetCurveForBinding(EditorCurveBinding binding) + { + for (int i = 0; i < curves.Length; i++) + { + if (binding.Equals(bindings[i])) + { + return curves[i]; + } + } + return null; + } + + public ObjectReferenceKeyframe[] GetObjectCurveForBinding(EditorCurveBinding binding) + { + if (objectCurves == null) + return null; + + for (int i = 0; i < objectCurves.Count; i++) + { + if (binding.Equals(objectBindings[i])) + { + return objectCurves[i]; + } + } + return null; + } + + // given a groupID, get the list of curve bindings + public CurveBindingGroup GetGroupBinding(string groupID) + { + if (m_groupings == null) + m_groupings = new Dictionary<string, CurveBindingGroup>(); + + CurveBindingGroup result = null; + if (!m_groupings.TryGetValue(groupID, out result)) + { + result = new CurveBindingGroup(); + result.timeRange = new Vector2(float.MaxValue, float.MinValue); + result.valueRange = new Vector2(float.MaxValue, float.MinValue); + List<CurveBindingPair> found = new List<CurveBindingPair>(); + for (int i = 0; i < bindings.Length; i++) + { + if (bindings[i].GetGroupID() == groupID) + { + CurveBindingPair pair = new CurveBindingPair(); + pair.binding = bindings[i]; + pair.curve = curves[i]; + found.Add(pair); + + for (int k = 0; k < curves[i].keys.Length; k++) + { + var key = curves[i].keys[k]; + result.timeRange = new Vector2(Mathf.Min(key.time, result.timeRange.x), Mathf.Max(key.time, result.timeRange.y)); + result.valueRange = new Vector2(Mathf.Min(key.value, result.valueRange.x), Mathf.Max(key.value, result.valueRange.y)); + } + } + } + for (int i = 0; i < objectBindings.Length; i++) + { + if (objectBindings[i].GetGroupID() == groupID) + { + CurveBindingPair pair = new CurveBindingPair(); + pair.binding = objectBindings[i]; + pair.objectCurve = objectCurves[i]; + found.Add(pair); + + for (int k = 0; k < objectCurves[i].Length; k++) + { + var key = objectCurves[i][k]; + result.timeRange = new Vector2(Mathf.Min(key.time, result.timeRange.x), Mathf.Max(key.time, result.timeRange.y)); + } + } + } + + result.curveBindingPairs = found.OrderBy(x => AnimationWindowUtility.GetComponentIndex(x.binding.propertyName)).ToArray(); + + m_groupings.Add(groupID, result); + } + return result; + } + } + + // Cache for storing the animation clip data + class AnimationClipCurveCache + { + static AnimationClipCurveCache s_Instance; + Dictionary<AnimationClip, AnimationClipCurveInfo> m_ClipCache = new Dictionary<AnimationClip, AnimationClipCurveInfo>(); + bool m_IsEnabled; + + + public static AnimationClipCurveCache Instance + { + get + { + if (s_Instance == null) + { + s_Instance = new AnimationClipCurveCache(); + } + + return s_Instance; + } + } + + public void OnEnable() + { + if (!m_IsEnabled) + { + AnimationUtility.onCurveWasModified += OnCurveWasModified; + m_IsEnabled = true; + } + } + + public void OnDisable() + { + if (m_IsEnabled) + { + AnimationUtility.onCurveWasModified -= OnCurveWasModified; + m_IsEnabled = false; + } + } + + // callback when a curve is edited. Force the cache to update next time it's accessed + void OnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType modification) + { + if (modification == AnimationUtility.CurveModifiedType.CurveDeleted) + { + m_ClipCache.Remove(clip); + } + else + { + AnimationClipCurveInfo data; + if (m_ClipCache.TryGetValue(clip, out data)) + { + data.dirty = true; + } + } + } + + public AnimationClipCurveInfo GetCurveInfo(AnimationClip clip) + { + AnimationClipCurveInfo data; + if (clip == null) + return null; + if (!m_ClipCache.TryGetValue(clip, out data)) + { + data = new AnimationClipCurveInfo(); + data.dirty = true; + m_ClipCache[clip] = data; + } + if (data.dirty) + { + data.Update(clip); + } + return data; + } + + public void ClearCachedProxyClips() + { + var toRemove = new List<AnimationClip>(); + foreach (var entry in m_ClipCache) + { + var clip = entry.Key; + if (clip != null && (clip.hideFlags & HideFlags.HideAndDontSave) == HideFlags.HideAndDontSave) + toRemove.Add(clip); + } + + foreach (var clip in toRemove) + { + m_ClipCache.Remove(clip); + Object.DestroyImmediate(clip, true); + } + } + + + public void Clear() + { + ClearCachedProxyClips(); + m_ClipCache.Clear(); + } + + } + + static class EditorCurveBindingExtension + { + // identifier to generate an id thats the same for all curves in the same group + public static string GetGroupID(this EditorCurveBinding binding) + { + return binding.type + AnimationWindowUtility.GetPropertyGroupName(binding.propertyName); + } + } + + + static class CurveBindingGroupExtensions + { + // Extentions to determine curve types + public static bool IsEnableGroup(this CurveBindingGroup curves) + { + return curves.isFloatCurve && curves.count == 1 && curves.curveBindingPairs[0].binding.propertyName == "m_Enabled"; + } + + public static bool IsVectorGroup(this CurveBindingGroup curves) + { + if (!curves.isFloatCurve) + return false; + if (curves.count <= 1 || curves.count > 4) + return false; + char l = curves.curveBindingPairs[0].binding.propertyName.Last(); + return l == 'x' || l == 'y' || l == 'z' || l == 'w'; + } + + public static bool IsColorGroup(this CurveBindingGroup curves) + { + if (!curves.isFloatCurve) + return false; + if (curves.count != 3 && curves.count != 4) + return false; + char l = curves.curveBindingPairs[0].binding.propertyName.Last(); + return l == 'r' || l == 'g' || l == 'b' || l == 'a'; + } + + public static string GetDescription(this CurveBindingGroup group, float t) + { + string result = string.Empty; + if (group.isFloatCurve) + { + if (group.count > 1) + { + result += "(" + group.curveBindingPairs[0].curve.Evaluate(t).ToString("0.##"); + for (int j = 1; j < group.curveBindingPairs.Length; j++) + { + result += "," + group.curveBindingPairs[j].curve.Evaluate(t).ToString("0.##"); + } + result += ")"; + } + else + { + result = group.curveBindingPairs[0].curve.Evaluate(t).ToString("0.##"); + } + } + else if (group.isObjectCurve) + { + Object obj = null; + if (group.curveBindingPairs[0].objectCurve.Length > 0) + obj = CurveEditUtility.Evaluate(group.curveBindingPairs[0].objectCurve, t); + result = (obj == null ? "None" : obj.name); + } + + return result; + } + } +} |
