123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- 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;
- }
- }
- }
|