summaryrefslogtreecommitdiff
path: root/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation
diff options
context:
space:
mode:
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation')
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs96
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs436
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs82
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs65
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs151
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs224
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs139
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs80
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs332
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs272
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs302
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs435
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs.meta11
24 files changed, 2746 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs
new file mode 100644
index 0000000..4c79048
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs
@@ -0,0 +1,96 @@
+using System.ComponentModel;
+using System.Linq;
+using JetBrains.Annotations;
+using UnityEngine;
+using UnityEngine.Timeline;
+using UnityEngine.Playables;
+using ClipAction = UnityEditor.Timeline.ItemAction<UnityEngine.Timeline.TimelineClip>;
+
+namespace UnityEditor.Timeline
+{
+ [MenuEntry("Match Offsets To Previous Clip", MenuOrder.CustomClipAction.AnimClipMatchPrevious), UsedImplicitly]
+ class MatchOffsetsPreviousAction : ClipAction
+ {
+ public override bool Execute(WindowState state, TimelineClip[] items)
+ {
+ AnimationOffsetMenu.MatchClipsToPrevious(state, items.Where(x => IsValidClip(x, TimelineEditor.inspectedDirector)).ToArray());
+ return true;
+ }
+
+ private static bool IsValidClip(TimelineClip clip, PlayableDirector director)
+ {
+ return clip != null &&
+ clip.parentTrack != null &&
+ (clip.asset as AnimationPlayableAsset) != null &&
+ clip.parentTrack.clips.Any(x => x.start < clip.start) &&
+ TimelineUtility.GetSceneGameObject(director, clip.parentTrack) != null;
+ }
+
+ protected override MenuActionDisplayState GetDisplayState(WindowState state, TimelineClip[] items)
+ {
+ if (!items.All(TimelineAnimationUtilities.IsAnimationClip))
+ return MenuActionDisplayState.Hidden;
+
+ var director = TimelineEditor.inspectedDirector;
+ if (TimelineEditor.inspectedDirector == null)
+ return MenuActionDisplayState.Hidden;
+
+ if (items.Any(c => IsValidClip(c, director)))
+ return MenuActionDisplayState.Visible;
+
+ return MenuActionDisplayState.Hidden;
+ }
+ }
+
+ [MenuEntry("Match Offsets To Next Clip", MenuOrder.CustomClipAction.AnimClipMatchNext), UsedImplicitly]
+ class MatchOffsetsNextAction : ClipAction
+ {
+ public override bool Execute(WindowState state, TimelineClip[] items)
+ {
+ AnimationOffsetMenu.MatchClipsToNext(state, items.Where(x => IsValidClip(x, TimelineEditor.inspectedDirector)).ToArray());
+ return true;
+ }
+
+ private static bool IsValidClip(TimelineClip clip, PlayableDirector director)
+ {
+ return clip != null &&
+ clip.parentTrack != null &&
+ (clip.asset as AnimationPlayableAsset) != null &&
+ clip.parentTrack.clips.Any(x => x.start > clip.start) &&
+ TimelineUtility.GetSceneGameObject(director, clip.parentTrack) != null;
+ }
+
+ protected override MenuActionDisplayState GetDisplayState(WindowState state, TimelineClip[] items)
+ {
+ if (!items.All(TimelineAnimationUtilities.IsAnimationClip))
+ return MenuActionDisplayState.Hidden;
+
+ var director = TimelineEditor.inspectedDirector;
+ if (TimelineEditor.inspectedDirector == null)
+ return MenuActionDisplayState.Hidden;
+
+ if (items.Any(c => IsValidClip(c, director)))
+ return MenuActionDisplayState.Visible;
+
+ return MenuActionDisplayState.Hidden;
+ }
+ }
+
+ [MenuEntry("Reset Offsets", MenuOrder.CustomClipAction.AnimClipResetOffset), UsedImplicitly]
+ class ResetOffsets : ClipAction
+ {
+ public override bool Execute(WindowState state, TimelineClip[] items)
+ {
+ AnimationOffsetMenu.ResetClipOffsets(state, items.Where(TimelineAnimationUtilities.IsAnimationClip).ToArray());
+ return true;
+ }
+
+ protected override MenuActionDisplayState GetDisplayState(WindowState state, TimelineClip[] items)
+ {
+ if (!items.All(TimelineAnimationUtilities.IsAnimationClip))
+ return MenuActionDisplayState.Hidden;
+
+ return MenuActionDisplayState.Visible;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs.meta
new file mode 100644
index 0000000..0632984
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipActions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bf22284ca28e7ef4490033b61e9b52cd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
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;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs.meta
new file mode 100644
index 0000000..47fcaa3
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationClipCurveCache.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 07a967d2fca95324f8922df8394a5655
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs
new file mode 100644
index 0000000..dbfc688
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs
@@ -0,0 +1,82 @@
+using System.Linq;
+using UnityEngine;
+using UnityEngine.Timeline;
+
+namespace UnityEditor.Timeline
+{
+ static class AnimationOffsetMenu
+ {
+ public static GUIContent MatchPreviousMenuItem = EditorGUIUtility.TrTextContent("Match Offsets To Previous Clip");
+ public static GUIContent MatchNextMenuItem = EditorGUIUtility.TrTextContent("Match Offsets To Next Clip");
+ public static string MatchFieldsPrefix = "Match Offsets Fields/";
+ public static GUIContent ResetOffsetMenuItem = EditorGUIUtility.TrTextContent("Reset Offsets");
+
+ static bool EnforcePreviewMode(WindowState state)
+ {
+ state.previewMode = true; // try and set the preview mode
+ if (!state.previewMode)
+ {
+ Debug.LogError("Match clips cannot be completed because preview mode cannot be enabed");
+ return false;
+ }
+ return true;
+ }
+
+ internal static void MatchClipsToPrevious(WindowState state, TimelineClip[] clips)
+ {
+ if (!EnforcePreviewMode(state))
+ return;
+
+ clips = clips.OrderBy(x => x.start).ToArray();
+ foreach (var clip in clips)
+ {
+ var sceneObject = TimelineUtility.GetSceneGameObject(state.editSequence.director, clip.parentTrack);
+ if (sceneObject != null)
+ {
+ TimelineUndo.PushUndo(clip.asset, "Match Clip");
+ TimelineAnimationUtilities.MatchPrevious(clip, sceneObject.transform, state.editSequence.director);
+ }
+ }
+
+ InspectorWindow.RepaintAllInspectors();
+ TimelineEditor.Refresh(RefreshReason.ContentsModified);
+ }
+
+ internal static void MatchClipsToNext(WindowState state, TimelineClip[] clips)
+ {
+ if (!EnforcePreviewMode(state))
+ return;
+
+ clips = clips.OrderByDescending(x => x.start).ToArray();
+ foreach (var clip in clips)
+ {
+ var sceneObject = TimelineUtility.GetSceneGameObject(state.editSequence.director, clip.parentTrack);
+ if (sceneObject != null)
+ {
+ TimelineUndo.PushUndo(clip.asset, "Match Clip");
+ TimelineAnimationUtilities.MatchNext(clip, sceneObject.transform, state.editSequence.director);
+ }
+ }
+
+ InspectorWindow.RepaintAllInspectors();
+ TimelineEditor.Refresh(RefreshReason.ContentsModified);
+ }
+
+ public static void ResetClipOffsets(WindowState state, TimelineClip[] clips)
+ {
+ foreach (var clip in clips)
+ {
+ if (clip.asset is AnimationPlayableAsset)
+ {
+ TimelineUndo.PushUndo(clip.asset, "Reset Offsets");
+ var playableAsset = (AnimationPlayableAsset)clip.asset;
+ playableAsset.ResetOffsets();
+ }
+ }
+ state.rebuildGraph = true;
+
+ InspectorWindow.RepaintAllInspectors();
+ TimelineEditor.Refresh(RefreshReason.SceneNeedsUpdate);
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs.meta
new file mode 100644
index 0000000..e628663
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationOffsetMenu.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9ace5095cc37ed849b52109d2ee305d4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs
new file mode 100644
index 0000000..e4bebc1
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs
@@ -0,0 +1,65 @@
+using JetBrains.Annotations;
+using UnityEngine;
+using UnityEngine.Playables;
+using UnityEngine.Timeline;
+
+namespace UnityEditor.Timeline
+{
+ [CustomTimelineEditor(typeof(AnimationPlayableAsset)), UsedImplicitly]
+ class AnimationPlayableAssetEditor : ClipEditor
+ {
+ public static readonly string k_NoClipAssignedError = LocalizationDatabase.GetLocalizedString("No animation clip assigned");
+ public static readonly string k_LegacyClipError = LocalizationDatabase.GetLocalizedString("Legacy animation clips are not supported");
+ static readonly string k_MotionCurveError = LocalizationDatabase.GetLocalizedString("You are using motion curves without applyRootMotion enabled on the Animator. The root transform will not be animated");
+ static readonly string k_RootCurveError = LocalizationDatabase.GetLocalizedString("You are using root curves without applyRootMotion enabled on the Animator. The root transform will not be animated");
+
+ /// <inheritdoc/>
+ public override ClipDrawOptions GetClipOptions(TimelineClip clip)
+ {
+ var clipOptions = base.GetClipOptions(clip);
+ var asset = clip.asset as AnimationPlayableAsset;
+
+ if (asset != null)
+ clipOptions.errorText = GetErrorText(asset, clip.parentTrack as AnimationTrack, clipOptions.errorText);
+
+ if (clip.recordable)
+ clipOptions.highlightColor = DirectorStyles.Instance.customSkin.colorAnimationRecorded;
+
+ return clipOptions;
+ }
+
+ /// <inheritdoc />
+ public override void OnCreate(TimelineClip clip, TrackAsset track, TimelineClip clonedFrom)
+ {
+ var asset = clip.asset as AnimationPlayableAsset;
+ if (asset != null && asset.clip != null && asset.clip.legacy)
+ {
+ asset.clip = null;
+ Debug.LogError("Legacy Animation Clips are not supported");
+ }
+ }
+
+ string GetErrorText(AnimationPlayableAsset animationAsset, AnimationTrack track, string defaultError)
+ {
+ if (animationAsset.clip == null)
+ return k_NoClipAssignedError;
+ if (animationAsset.clip.legacy)
+ return k_LegacyClipError;
+ if (animationAsset.clip.hasMotionCurves || animationAsset.clip.hasRootCurves)
+ {
+ if (track != null && track.trackOffset == TrackOffset.Auto)
+ {
+ var animator = track.GetBinding(TimelineEditor.inspectedDirector);
+ if (animator != null && !animator.applyRootMotion && !animationAsset.clip.hasGenericRootTransform)
+ {
+ if (animationAsset.clip.hasMotionCurves)
+ return k_MotionCurveError;
+ return k_RootCurveError;
+ }
+ }
+ }
+
+ return defaultError;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs.meta
new file mode 100644
index 0000000..0a749e8
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationPlayableAssetEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f7fed0d9d0f7a7f41a8525aa79e790b1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs
new file mode 100644
index 0000000..0b1a171
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs
@@ -0,0 +1,151 @@
+using System.ComponentModel;
+using System.Linq;
+using JetBrains.Annotations;
+using UnityEngine;
+using UnityEngine.Timeline;
+
+namespace UnityEditor.Timeline
+{
+ [MenuEntry("Add Override Track", MenuOrder.CustomTrackAction.AnimAddOverrideTrack), UsedImplicitly]
+ class AddOverrideTrackAction : TrackAction
+ {
+ public override bool Execute(WindowState state, TrackAsset[] tracks)
+ {
+ foreach (var animTrack in tracks.OfType<AnimationTrack>())
+ {
+ TimelineHelpers.CreateTrack(typeof(AnimationTrack), animTrack, "Override " + animTrack.GetChildTracks().Count());
+ }
+
+ return true;
+ }
+
+ protected override MenuActionDisplayState GetDisplayState(WindowState state, TrackAsset[] tracks)
+ {
+ if (tracks.Any(t => t.isSubTrack || !t.GetType().IsAssignableFrom(typeof(AnimationTrack))))
+ return MenuActionDisplayState.Hidden;
+
+ if (tracks.Any(t => t.lockedInHierarchy))
+ return MenuActionDisplayState.Disabled;
+
+ return MenuActionDisplayState.Visible;
+ }
+ }
+
+ [MenuEntry("Convert To Clip Track", MenuOrder.CustomTrackAction.AnimConvertToClipMode), UsedImplicitly]
+ class ConvertToClipModeAction : TrackAction
+ {
+ public override bool Execute(WindowState state, TrackAsset[] tracks)
+ {
+ foreach (var animTrack in tracks.OfType<AnimationTrack>())
+ animTrack.ConvertToClipMode();
+
+ TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved);
+
+ return true;
+ }
+
+ protected override MenuActionDisplayState GetDisplayState(WindowState state, TrackAsset[] tracks)
+ {
+ if (tracks.Any(t => !t.GetType().IsAssignableFrom(typeof(AnimationTrack))))
+ return MenuActionDisplayState.Hidden;
+
+ if (tracks.Any(t => t.lockedInHierarchy))
+ return MenuActionDisplayState.Disabled;
+
+ if (tracks.OfType<AnimationTrack>().All(a => a.CanConvertToClipMode()))
+ return MenuActionDisplayState.Visible;
+
+ return MenuActionDisplayState.Hidden;
+ }
+ }
+
+ [MenuEntry("Convert To Infinite Clip", MenuOrder.CustomTrackAction.AnimConvertFromClipMode), UsedImplicitly]
+ class ConvertFromClipTrackAction : TrackAction
+ {
+ public override bool Execute(WindowState state, TrackAsset[] tracks)
+ {
+ foreach (var animTrack in tracks.OfType<AnimationTrack>())
+ animTrack.ConvertFromClipMode(state.editSequence.asset);
+
+ TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved);
+
+ return true;
+ }
+
+ protected override MenuActionDisplayState GetDisplayState(WindowState state, TrackAsset[] tracks)
+ {
+ if (tracks.Any(t => !t.GetType().IsAssignableFrom(typeof(AnimationTrack))))
+ return MenuActionDisplayState.Hidden;
+
+ if (tracks.Any(t => t.lockedInHierarchy))
+ return MenuActionDisplayState.Disabled;
+
+ if (tracks.OfType<AnimationTrack>().All(a => a.CanConvertFromClipMode()))
+ return MenuActionDisplayState.Visible;
+
+ return MenuActionDisplayState.Hidden;
+ }
+ }
+
+ abstract class TrackOffsetBaseAction : TrackAction
+ {
+ public abstract TrackOffset trackOffset { get; }
+
+ protected override MenuActionDisplayState GetDisplayState(WindowState state, TrackAsset[] tracks)
+ {
+ if (tracks.Any(t => !t.GetType().IsAssignableFrom(typeof(AnimationTrack))))
+ return MenuActionDisplayState.Hidden;
+
+ if (tracks.Any(t => t.lockedInHierarchy))
+ return MenuActionDisplayState.Disabled;
+
+ return MenuActionDisplayState.Visible;
+ }
+
+ protected override bool IsChecked(WindowState state, TrackAsset[] tracks)
+ {
+ return tracks.OfType<AnimationTrack>().All(t => t.trackOffset == trackOffset);
+ }
+
+ public override bool Execute(WindowState state, TrackAsset[] tracks)
+ {
+ foreach (var animTrack in tracks.OfType<AnimationTrack>())
+ {
+ state.UnarmForRecord(animTrack);
+ TimelineUndo.PushUndo(animTrack, "Set Transform Offsets");
+ animTrack.trackOffset = trackOffset;
+ }
+
+ TimelineEditor.Refresh(RefreshReason.ContentsModified);
+ return true;
+ }
+ }
+
+
+ [MenuEntry("Track Offsets/Apply Transform Offsets", MenuOrder.CustomTrackAction.AnimApplyTrackOffset), UsedImplicitly]
+ class ApplyTransformOffsetAction : TrackOffsetBaseAction
+ {
+ public override TrackOffset trackOffset
+ {
+ get { return TrackOffset.ApplyTransformOffsets; }
+ }
+ }
+
+ [MenuEntry("Track Offsets/Apply Scene Offsets", MenuOrder.CustomTrackAction.AnimApplySceneOffset), UsedImplicitly]
+ class ApplySceneOffsetAction : TrackOffsetBaseAction
+ {
+ public override TrackOffset trackOffset
+ {
+ get { return TrackOffset.ApplySceneOffsets; }
+ }
+ }
+
+ [MenuEntry("Track Offsets/Auto (Deprecated)", MenuOrder.CustomTrackAction.AnimApplyAutoOffset), UsedImplicitly]
+ class ApplyAutoAction : TrackOffsetBaseAction
+ {
+ public override TrackOffset trackOffset
+ {
+ get { return TrackOffset.Auto; }
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs.meta
new file mode 100644
index 0000000..4ca0e4d
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/AnimationTrackActions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d4553f2006f48b6448553cb525d2876e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs
new file mode 100644
index 0000000..7f3cdde
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs
@@ -0,0 +1,224 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEditor.IMGUI.Controls;
+using UnityEditor.Timeline;
+using UnityEditorInternal;
+using UnityEngine;
+using UnityEngine.Timeline;
+
+namespace UnityEditor
+{
+ class BindingSelector
+ {
+ TreeViewController m_TreeView;
+ public TreeViewController treeViewController
+ {
+ get { return m_TreeView; }
+ }
+
+ TreeViewState m_TrackGlobalTreeViewState;
+ TreeViewState m_TreeViewState;
+ BindingTreeViewDataSource m_TreeViewDataSource;
+ CurveDataSource m_CurveDataSource;
+ TimelineWindow m_Window;
+ CurveEditor m_CurveEditor;
+ ReorderableList m_DopeLines;
+ string[] m_StringList = {};
+ int[] m_Selection;
+ bool m_PartOfSelection;
+ public BindingSelector(EditorWindow window, CurveEditor curveEditor, TreeViewState trackGlobalTreeViewState)
+ {
+ m_Window = window as TimelineWindow;
+ m_CurveEditor = curveEditor;
+ m_TrackGlobalTreeViewState = trackGlobalTreeViewState;
+
+ m_DopeLines = new ReorderableList(m_StringList, typeof(string), false, false, false, false);
+ m_DopeLines.drawElementBackgroundCallback = null;
+ m_DopeLines.showDefaultBackground = false;
+ m_DopeLines.index = 0;
+ m_DopeLines.headerHeight = 0;
+ m_DopeLines.elementHeight = 20;
+ m_DopeLines.draggable = false;
+ }
+
+ public bool selectable { get { return true; } }
+
+ public object selectableObject
+ {
+ get { return this; }
+ }
+
+ public bool selected
+ {
+ get { return m_PartOfSelection; }
+ set
+ {
+ m_PartOfSelection = value;
+
+ if (!m_PartOfSelection)
+ {
+ m_DopeLines.index = -1;
+ }
+ }
+ }
+
+ public virtual void Delete(WindowState state)
+ {
+ // we dont support deleting the summary
+ if (m_DopeLines.index < 1)
+ return;
+
+ if (m_CurveDataSource == null)
+ return;
+
+ var clip = m_CurveDataSource.animationClip;
+ if (clip == null)
+ return;
+
+ int curveIndexToDelete = m_DopeLines.index - 1;
+ var bindings = AnimationUtility.GetCurveBindings(clip);
+
+ if (curveIndexToDelete >= bindings.Length)
+ return;
+
+ TimelineUndo.PushUndo(clip, "Delete Curve");
+ AnimationUtility.SetEditorCurve(clip, bindings[m_DopeLines.index - 1], null);
+ state.rebuildGraph = true;
+ }
+
+ public void OnGUI(Rect targetRect)
+ {
+ if (m_TreeView == null)
+ return;
+
+ m_TreeView.OnEvent();
+ m_TreeView.OnGUI(targetRect, GUIUtility.GetControlID(FocusType.Passive));
+ }
+
+ public void InitIfNeeded(Rect rect, CurveDataSource dataSource, bool isNewSelection)
+ {
+ if (Event.current.type != EventType.Layout)
+ return;
+
+ m_CurveDataSource = dataSource;
+ var clip = dataSource.animationClip;
+
+ List<EditorCurveBinding> allBindings = new List<EditorCurveBinding>();
+ allBindings.Add(new EditorCurveBinding { propertyName = "Summary" });
+ if (clip != null)
+ allBindings.AddRange(AnimationUtility.GetCurveBindings(clip));
+
+ m_DopeLines.list = allBindings.ToArray();
+
+ if (m_TreeViewState != null)
+ {
+ if (isNewSelection)
+ RefreshAll();
+
+ return;
+ }
+
+ m_TreeViewState = m_TrackGlobalTreeViewState != null ? m_TrackGlobalTreeViewState : new TreeViewState();
+
+ m_TreeView = new TreeViewController(m_Window, m_TreeViewState)
+ {
+ useExpansionAnimation = false,
+ deselectOnUnhandledMouseDown = true
+ };
+
+ m_TreeView.selectionChangedCallback += OnItemSelectionChanged;
+
+ m_TreeViewDataSource = new BindingTreeViewDataSource(m_TreeView, clip, m_CurveDataSource);
+
+ m_TreeView.Init(rect, m_TreeViewDataSource, new BindingTreeViewGUI(m_TreeView), null);
+
+ m_TreeViewDataSource.UpdateData();
+
+ RefreshSelection();
+ }
+
+ void OnItemSelectionChanged(int[] selection)
+ {
+ RefreshSelection(selection);
+ }
+
+ void RefreshAll()
+ {
+ RefreshTree();
+ RefreshSelection();
+ }
+
+ void RefreshSelection()
+ {
+ RefreshSelection(m_TreeViewState.selectedIDs != null ? m_TreeViewState.selectedIDs.ToArray() : null);
+ }
+
+ void RefreshSelection(int[] selection)
+ {
+ if (selection == null || selection.Length == 0)
+ {
+ // select all.
+ if (m_TreeViewDataSource.GetRows().Count > 0)
+ {
+ m_Selection = m_TreeViewDataSource.GetRows().Select(r => r.id).ToArray();
+ }
+ }
+ else
+ {
+ m_Selection = selection;
+ }
+
+ RefreshCurves();
+ }
+
+ public void RefreshCurves()
+ {
+ if (m_CurveDataSource == null || m_Selection == null)
+ return;
+
+ var bindings = new List<EditorCurveBinding>();
+ foreach (int s in m_Selection)
+ {
+ var item = (CurveTreeViewNode)m_TreeView.FindItem(s);
+ if (item != null && item.bindings != null)
+ bindings.AddRange(item.bindings);
+ }
+
+ var wrappers = m_CurveDataSource.GenerateWrappers(bindings);
+ m_CurveEditor.animationCurves = wrappers.ToArray();
+ }
+
+ public void RefreshTree()
+ {
+ if (m_TreeViewDataSource == null)
+ return;
+
+ if (m_Selection == null)
+ m_Selection = new int[0];
+
+ // get the names of the previous items
+ var selected = m_Selection.Select(x => m_TreeViewDataSource.FindItem(x)).Where(t => t != null).Select(c => c.displayName).ToArray();
+
+ // update the source
+ m_TreeViewDataSource.UpdateData();
+
+ // find the same items
+ var reselected = m_TreeViewDataSource.GetRows().Where(x => selected.Contains(x.displayName)).Select(x => x.id).ToArray();
+ if (!reselected.Any())
+ {
+ if (m_TreeViewDataSource.GetRows().Count > 0)
+ {
+ reselected = new[] { m_TreeViewDataSource.GetItem(0).id };
+ }
+ }
+
+ // update the selection
+ OnItemSelectionChanged(reselected);
+ }
+
+ internal virtual bool IsRenamingNodeAllowed(TreeViewItem node)
+ {
+ return false;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs.meta
new file mode 100644
index 0000000..b08aa56
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingSelector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c171b9ca03610ea4faa426e082a1075d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs
new file mode 100644
index 0000000..8118285
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs
@@ -0,0 +1,139 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEditor;
+using UnityEditor.IMGUI.Controls;
+using UnityEditor.Timeline;
+using UnityEngine;
+
+namespace UnityEditorInternal
+{
+ class BindingTreeViewDataSource : TreeViewDataSource
+ {
+ public const int RootID = int.MinValue;
+ public const int GroupID = -1;
+
+ AnimationClip m_Clip;
+ CurveDataSource m_CurveDataSource;
+
+ public BindingTreeViewDataSource(
+ TreeViewController treeView, AnimationClip clip, CurveDataSource curveDataSource)
+ : base(treeView)
+ {
+ m_Clip = clip;
+ showRootItem = false;
+ m_CurveDataSource = curveDataSource;
+ }
+
+ void SetupRootNodeSettings()
+ {
+ showRootItem = false;
+ SetExpanded(RootID, true);
+ SetExpanded(GroupID, true);
+ }
+
+ static string GroupName(EditorCurveBinding binding)
+ {
+ string property = AnimationWindowUtility.NicifyPropertyGroupName(binding.type, binding.propertyName);
+ if (!string.IsNullOrEmpty(binding.path))
+ {
+ property = binding.path + " : " + property;
+ }
+
+ int lastArrayIdx = property.LastIndexOf("Array.");
+ if (lastArrayIdx != -1)
+ {
+ property = property.Substring(0, lastArrayIdx - 1);
+ }
+ return property;
+ }
+
+ static string PropertyName(EditorCurveBinding binding, string arrayPrefixToRemove = "")
+ {
+ string propertyName = AnimationWindowUtility.GetPropertyDisplayName(binding.propertyName);
+ if (propertyName.Contains("Array"))
+ {
+ propertyName = propertyName.Replace("Array.", "");
+ propertyName = propertyName.Replace(arrayPrefixToRemove, "");
+ propertyName = propertyName.TrimStart('.');
+ }
+ return propertyName;
+ }
+
+ public override void FetchData()
+ {
+ if (m_Clip == null)
+ return;
+
+ var bindings = AnimationUtility.GetCurveBindings(m_Clip)
+ .Union(AnimationUtility.GetObjectReferenceCurveBindings(m_Clip))
+ .ToArray();
+
+ var results = bindings.GroupBy(p => GroupName(p), p => p, (key, g) => new
+ {
+ parent = key,
+ bindings = g.ToList()
+ }).OrderBy(t =>
+ {
+ //Force transform order first
+ if (t.parent == "Position") return -3;
+ if (t.parent == "Rotation") return -2;
+ if (t.parent == "Scale") return -1;
+ return 0;
+ }).ThenBy(t => t.parent);
+
+ m_RootItem = new CurveTreeViewNode(RootID, null, "root", null)
+ {
+ children = new List<TreeViewItem>(1)
+ };
+
+ var groupingNode = new CurveTreeViewNode(GroupID, m_RootItem, m_CurveDataSource.groupingName, bindings)
+ {
+ children = new List<TreeViewItem>()
+ };
+
+ m_RootItem.children.Add(groupingNode);
+
+ foreach (var r in results)
+ {
+ var newNode = new CurveTreeViewNode(r.parent.GetHashCode(), groupingNode, r.parent, r.bindings.ToArray());
+ groupingNode.children.Add(newNode);
+ if (r.bindings.Count > 1)
+ {
+ for (int b = 0; b < r.bindings.Count; b++)
+ {
+ if (newNode.children == null)
+ newNode.children = new List<TreeViewItem>();
+
+ var binding = r.bindings[b];
+ var bindingNode = new CurveTreeViewNode(binding.GetHashCode(), newNode, PropertyName(binding, newNode.displayName), new[] {binding});
+ newNode.children.Add(bindingNode);
+ }
+ }
+ }
+
+ SetupRootNodeSettings();
+ m_NeedRefreshRows = true;
+ }
+
+ public void UpdateData()
+ {
+ m_TreeView.ReloadData();
+ }
+ }
+
+ class CurveTreeViewNode : TreeViewItem
+ {
+ EditorCurveBinding[] m_Bindings;
+
+ public EditorCurveBinding[] bindings
+ {
+ get { return m_Bindings; }
+ }
+
+ public CurveTreeViewNode(int id, TreeViewItem parent, string displayName, EditorCurveBinding[] bindings)
+ : base(id, parent != null ? parent.depth + 1 : -1, parent, displayName)
+ {
+ m_Bindings = bindings;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs.meta
new file mode 100644
index 0000000..b553947
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSource.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9c2177aaf0fde92439246adc2dc0bfa2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs
new file mode 100644
index 0000000..443a216
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs
@@ -0,0 +1,80 @@
+using UnityEditor;
+using UnityEditor.IMGUI.Controls;
+using UnityEngine;
+
+namespace UnityEditorInternal
+{
+ class BindingTreeViewGUI : TreeViewGUI
+ {
+ static readonly float s_RowRightOffset = 10;
+ static readonly float s_ColorIndicatorTopMargin = 3;
+ static readonly Color s_KeyColorForNonCurves = new Color(0.7f, 0.7f, 0.7f, 0.5f);
+ static readonly Color s_ChildrenCurveLabelColor = new Color(1.0f, 1.0f, 1.0f, 0.7f);
+
+ public BindingTreeViewGUI(TreeViewController treeView)
+ : base(treeView, true)
+ {
+ k_IconWidth = 13.0f;
+ }
+
+ public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused)
+ {
+ Color originalColor = GUI.color;
+ GUI.color = node.parent == null ||
+ node.parent.id == BindingTreeViewDataSource.RootID ||
+ node.parent.id == BindingTreeViewDataSource.GroupID ?
+ Color.white :
+ s_ChildrenCurveLabelColor;
+
+ base.OnRowGUI(rowRect, node, row, selected, focused);
+
+ GUI.color = originalColor;
+ DoCurveColorIndicator(rowRect, node as CurveTreeViewNode);
+ }
+
+ protected override bool IsRenaming(int id)
+ {
+ return false;
+ }
+
+ public override bool BeginRename(TreeViewItem item, float delay)
+ {
+ return false;
+ }
+
+ void DoCurveColorIndicator(Rect rect, CurveTreeViewNode node)
+ {
+ if (node == null)
+ return;
+
+ if (Event.current.type != EventType.Repaint)
+ return;
+
+ Color originalColor = GUI.color;
+
+ if (node.bindings.Length == 1 && !node.bindings[0].isPPtrCurve)
+ GUI.color = CurveUtility.GetPropertyColor(node.bindings[0].propertyName);
+ else
+ GUI.color = s_KeyColorForNonCurves;
+
+ Texture icon = CurveUtility.GetIconCurve();
+ rect = new Rect(rect.xMax - s_RowRightOffset - (icon.width * 0.5f) - 5, rect.yMin + s_ColorIndicatorTopMargin, icon.width, icon.height);
+
+ GUI.DrawTexture(rect, icon, ScaleMode.ScaleToFit, true, 1);
+
+ GUI.color = originalColor;
+ }
+
+ protected override Texture GetIconForItem(TreeViewItem item)
+ {
+ var node = item as CurveTreeViewNode;
+ if (node == null)
+ return null;
+
+ if (node.bindings == null || node.bindings.Length == 0)
+ return null;
+
+ return AssetPreview.GetMiniTypeThumbnail(node.bindings[0].type);
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs.meta
new file mode 100644
index 0000000..2e16c1b
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/BindingTreeViewDataSourceGUI.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3c09dc5cd0a70cf40856b7d406106ee1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs
new file mode 100644
index 0000000..da1d0e6
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs
@@ -0,0 +1,332 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEditor.Timeline;
+using UnityEngine;
+using UnityEngine.Timeline;
+
+namespace UnityEditor
+{
+ class ClipCurveEditor
+ {
+ internal readonly CurveEditor m_CurveEditor;
+ static readonly CurveEditorSettings s_CurveEditorSettings = new CurveEditorSettings
+ {
+ hSlider = false,
+ vSlider = false,
+ hRangeLocked = false,
+ vRangeLocked = false,
+ scaleWithWindow = true,
+ hRangeMin = 0.0f,
+ showAxisLabels = true,
+ allowDeleteLastKeyInCurve = true,
+ rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.MiniRectangleTool
+ };
+
+ static readonly float s_GridLabelWidth = 40.0f;
+
+ readonly BindingSelector m_BindingHierarchy;
+ public BindingSelector bindingHierarchy
+ {
+ get { return m_BindingHierarchy; }
+ }
+
+ public Rect shownAreaInsideMargins
+ {
+ get { return m_CurveEditor != null ? m_CurveEditor.shownAreaInsideMargins : new Rect(1, 1, 1, 1); }
+ }
+
+ Vector2 m_ScrollPosition = Vector2.zero;
+
+ readonly CurveDataSource m_DataSource;
+
+ float m_LastFrameRate = 30.0f;
+ int m_LastClipVersion = -1;
+ int m_LastCurveCount = -1;
+ TrackViewModelData m_ViewModel;
+ bool m_ShouldRestoreShownArea;
+
+ bool isNewSelection
+ {
+ get
+ {
+ if (m_ViewModel == null || m_DataSource == null)
+ return true;
+
+ return m_ViewModel.lastInlineCurveDataID != m_DataSource.id;
+ }
+ }
+
+ internal CurveEditor curveEditor
+ {
+ get { return m_CurveEditor; }
+ }
+
+ public ClipCurveEditor(CurveDataSource dataSource, TimelineWindow parentWindow, TrackAsset hostTrack)
+ {
+ m_DataSource = dataSource;
+
+ m_CurveEditor = new CurveEditor(new Rect(0, 0, 1000, 100), new CurveWrapper[0], false);
+
+ s_CurveEditorSettings.vTickStyle = new TickStyle
+ {
+ tickColor = { color = DirectorStyles.Instance.customSkin.colorInlineCurveVerticalLines },
+ distLabel = 20,
+ stubs = true
+ };
+
+ s_CurveEditorSettings.hTickStyle = new TickStyle
+ {
+ // hide horizontal lines by giving them a transparent color
+ tickColor = { color = new Color(0.0f, 0.0f, 0.0f, 0.0f) },
+ distLabel = 0
+ };
+
+ m_CurveEditor.settings = s_CurveEditorSettings;
+
+ m_ViewModel = TimelineWindowViewPrefs.GetTrackViewModelData(hostTrack);
+
+ m_ShouldRestoreShownArea = true;
+ m_CurveEditor.ignoreScrollWheelUntilClicked = true;
+ m_CurveEditor.curvesUpdated = OnCurvesUpdated;
+
+ m_BindingHierarchy = new BindingSelector(parentWindow, m_CurveEditor, m_ViewModel.inlineCurvesState);
+ }
+
+ public void SelectAllKeys()
+ {
+ m_CurveEditor.SelectAll();
+ }
+
+ public void FrameClip()
+ {
+ m_CurveEditor.InvalidateBounds();
+ m_CurveEditor.FrameClip(false, true);
+ }
+
+ public CurveDataSource dataSource
+ {
+ get { return m_DataSource; }
+ }
+
+ internal void OnCurvesUpdated()
+ {
+ if (m_DataSource == null)
+ return;
+
+ if (m_CurveEditor == null)
+ return;
+
+ if (m_CurveEditor.animationCurves.Length == 0)
+ return;
+
+ List<CurveWrapper> curvesToUpdate = m_CurveEditor.animationCurves.Where(c => c.changed).ToList();
+
+ // nothing changed, return.
+ if (curvesToUpdate.Count == 0)
+ return;
+
+ AnimationClip clip = m_DataSource.animationClip;
+
+ // something changed, manage the undo properly.
+ Undo.RegisterCompleteObjectUndo(clip, "Edit Clip Curve");
+
+ foreach (CurveWrapper c in curvesToUpdate)
+ {
+ AnimationUtility.SetEditorCurve(clip, c.binding, c.curve);
+ c.changed = false;
+ }
+
+ m_DataSource.UpdateCurves(curvesToUpdate);
+ }
+
+ public void DrawHeader(Rect headerRect)
+ {
+ m_BindingHierarchy.InitIfNeeded(headerRect, m_DataSource, isNewSelection);
+
+ try
+ {
+ GUILayout.BeginArea(headerRect);
+ m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition, GUIStyle.none, GUI.skin.verticalScrollbar);
+ m_BindingHierarchy.OnGUI(new Rect(0, 0, headerRect.width, headerRect.height));
+ GUILayout.EndScrollView();
+ GUILayout.EndArea();
+ }
+ catch (Exception e)
+ {
+ Debug.LogException(e);
+ }
+ }
+
+ class FrameFormatCurveEditorState : ICurveEditorState
+ {
+ public TimeArea.TimeFormat timeFormat
+ {
+ get { return TimeArea.TimeFormat.Frame; }
+ }
+ public Vector2 timeRange { get { return new Vector2(0, 1); } }
+ public bool rippleTime { get { return false; } }
+ }
+
+ class UnformattedCurveEditorState : ICurveEditorState
+ {
+ public TimeArea.TimeFormat timeFormat
+ {
+ get { return TimeArea.TimeFormat.None; }
+ }
+ public Vector2 timeRange { get { return new Vector2(0, 1); } }
+ public bool rippleTime { get { return false; } }
+ }
+
+ void UpdateCurveEditorIfNeeded(WindowState state)
+ {
+ if ((Event.current.type != EventType.Layout) || (m_DataSource == null) || (m_BindingHierarchy == null) || (m_DataSource.animationClip == null))
+ return;
+
+ AnimationClipCurveInfo curveInfo = AnimationClipCurveCache.Instance.GetCurveInfo(m_DataSource.animationClip);
+ int version = curveInfo.version;
+ if (version != m_LastClipVersion)
+ {
+ // tree has changed
+ if (m_LastCurveCount != curveInfo.curves.Length)
+ {
+ m_BindingHierarchy.RefreshTree();
+ m_LastCurveCount = curveInfo.curves.Length;
+ }
+ else
+ {
+ // update just the curves
+ m_BindingHierarchy.RefreshCurves();
+ }
+ m_LastClipVersion = version;
+ }
+
+ if (state.timeInFrames)
+ m_CurveEditor.state = new FrameFormatCurveEditorState();
+ else
+ m_CurveEditor.state = new UnformattedCurveEditorState();
+
+ m_CurveEditor.invSnap = state.referenceSequence.frameRate;
+ }
+
+ public void DrawCurveEditor(Rect rect, WindowState state, Vector2 clipRange, bool loop, bool selected)
+ {
+ var curveEndTime = m_DataSource.start + m_DataSource.animationClip.length / m_DataSource.timeScale;
+ var curveRange = new Vector2(state.TimeToPixel(m_DataSource.start), state.TimeToPixel(curveEndTime));
+
+ SetupMarginsAndRect(rect, curveRange, state);
+ UpdateCurveEditorIfNeeded(state);
+
+ if (m_ShouldRestoreShownArea)
+ RestoreShownArea();
+ m_CurveEditor.SetShownHRangeInsideMargins(0.0f, m_DataSource.animationClip.length); //align the curve with the clip.
+
+ if (m_LastFrameRate != state.referenceSequence.frameRate)
+ {
+ m_CurveEditor.hTicks.SetTickModulosForFrameRate(state.referenceSequence.frameRate);
+ m_LastFrameRate = state.referenceSequence.frameRate;
+ }
+
+ foreach (var cw in m_CurveEditor.animationCurves)
+ cw.renderer.SetWrap(WrapMode.Default, loop ? WrapMode.Loop : WrapMode.Default);
+
+ using (new GUIGroupScope(rect))
+ {
+ var localRect = new Rect(0.0f, 0.0f, rect.width, rect.height);
+ var localClipRange = new Vector2(Mathf.Floor(clipRange.x - rect.xMin), Mathf.Ceil(clipRange.y - rect.xMin));
+ var localCurveRange = new Vector2(Mathf.Floor(curveRange.x - rect.xMin), Mathf.Ceil(curveRange.y - rect.xMin));
+
+ EditorGUI.DrawRect(new Rect(localCurveRange.x, 0.0f, 1.0f, rect.height), new Color(1.0f, 1.0f, 1.0f, 0.5f));
+ DrawCurveEditorBackground(localRect, localClipRange);
+
+ if (selected)
+ {
+ var selectionRect = new Rect(localClipRange.x, 0.0f, localClipRange.y - localClipRange.x, localRect.height);
+ DrawOutline(selectionRect);
+ }
+
+ EditorGUI.BeginChangeCheck();
+ {
+ var evt = Event.current;
+ if (evt.type == EventType.Layout || evt.type == EventType.Repaint || selected)
+ m_CurveEditor.CurveGUI();
+ }
+ if (EditorGUI.EndChangeCheck())
+ OnCurvesUpdated();
+
+ DrawOverlay(localRect, localClipRange, DirectorStyles.Instance.customSkin.colorInlineCurveOutOfRangeOverlay);
+ DrawGrid(localRect, localCurveRange);
+ }
+ }
+
+ void SetupMarginsAndRect(Rect rect, Vector2 curveRange, WindowState state)
+ {
+ var timelineWidth = state.TimeToPixel(Mathf.Max((float)state.editSequence.duration, state.timeAreaShownRange.y));
+ m_CurveEditor.rect = new Rect(-rect.xMin, 0.0f, timelineWidth, rect.height);
+ m_CurveEditor.leftmargin = curveRange.x;
+ m_CurveEditor.rightmargin = timelineWidth - curveRange.y;
+ m_CurveEditor.topmargin = m_CurveEditor.bottommargin = CalculateTopMargin(rect.height);
+ }
+
+ void RestoreShownArea()
+ {
+ if (isNewSelection)
+ FrameClip();
+ else
+ m_CurveEditor.shownAreaInsideMargins = m_ViewModel.inlineCurvesShownAreaInsideMargins;
+ m_ShouldRestoreShownArea = false;
+ }
+
+ static void DrawCurveEditorBackground(Rect rect, Vector2 activeRange)
+ {
+ if (EditorGUIUtility.isProSkin)
+ return;
+
+ var animEditorBackgroundRect = Rect.MinMaxRect(0.0f, rect.yMin, rect.xMax, rect.yMax);
+
+ // Curves are not legible in Personal Skin so we need to darken the background a bit.
+ EditorGUI.DrawRect(animEditorBackgroundRect, DirectorStyles.Instance.customSkin.colorInlineCurvesBackground);
+ }
+
+ static float CalculateTopMargin(float height)
+ {
+ return Mathf.Clamp(0.15f * height, 10.0f, 40.0f);
+ }
+
+ static void DrawOutline(Rect rect, float thickness = 2.0f)
+ {
+ // Draw top selected lines.
+ EditorGUI.DrawRect(new Rect(rect.xMin, rect.yMin, rect.width, thickness), Color.white);
+
+ // Draw bottom selected lines.
+ EditorGUI.DrawRect(new Rect(rect.xMin, rect.yMax - thickness, rect.width, thickness), Color.white);
+
+ // Draw Left Selected Lines
+ EditorGUI.DrawRect(new Rect(rect.xMin, rect.yMin, thickness, rect.height), Color.white);
+
+ // Draw Right Selected Lines
+ EditorGUI.DrawRect(new Rect(rect.xMax - thickness, rect.yMin, thickness, rect.height), Color.white);
+ }
+
+ static void DrawOverlay(Rect rect, Vector2 clipRange, Color color)
+ {
+ var leftSide = new Rect(rect.xMin, rect.yMin, clipRange.x - rect.xMin, rect.height);
+ EditorGUI.DrawRect(leftSide, color);
+
+ var rightSide = new Rect(Mathf.Max(0.0f, clipRange.y), rect.yMin, rect.xMax, rect.height);
+ EditorGUI.DrawRect(rightSide, color);
+ }
+
+ void DrawGrid(Rect rect, Vector2 curveRange)
+ {
+ var gridXPos = Mathf.Max(curveRange.x - s_GridLabelWidth, rect.xMin);
+ var gridRect = new Rect(gridXPos, rect.y, s_GridLabelWidth, rect.height);
+ var originalRect = m_CurveEditor.rect;
+
+ m_CurveEditor.rect = new Rect(0.0f, 0.0f, rect.width, rect.height);
+ using (new GUIGroupScope(gridRect))
+ m_CurveEditor.GridGUI();
+ m_CurveEditor.rect = originalRect;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs.meta
new file mode 100644
index 0000000..5ae80d2
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/ClipCurveEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d49b2ed20045e034f9cdf6a6d95e6183
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs
new file mode 100644
index 0000000..b5ad13b
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs
@@ -0,0 +1,272 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Timeline;
+
+namespace UnityEditor.Timeline
+{
+ abstract class CurveDataSource
+ {
+ public static CurveDataSource Create(IRowGUI trackGUI)
+ {
+ if (trackGUI.asset is AnimationTrack)
+ return new InfiniteClipCurveDataSource(trackGUI);
+
+ return new TrackParametersCurveDataSource(trackGUI);
+ }
+
+ public static CurveDataSource Create(TimelineClipGUI clipGUI)
+ {
+ if (clipGUI.clip.animationClip != null)
+ return new ClipAnimationCurveDataSource(clipGUI);
+
+ return new ClipParametersCurveDataSource(clipGUI);
+ }
+
+ int? m_ID = null;
+ public int id
+ {
+ get
+ {
+ if (!m_ID.HasValue)
+ m_ID = CreateHashCode();
+
+ return m_ID.Value;
+ }
+ }
+
+ readonly IRowGUI m_TrackGUI;
+ protected IRowGUI trackGUI { get { return m_TrackGUI; } }
+
+ protected CurveDataSource(IRowGUI trackGUI)
+ {
+ m_TrackGUI = trackGUI;
+ }
+
+ public abstract AnimationClip animationClip { get; }
+ public abstract float start { get; }
+ public abstract float timeScale { get; }
+ public abstract string groupingName { get; }
+ public virtual void UpdateCurves(List<CurveWrapper> updatedCurves) {}
+ public virtual void RebuildCurves() {} // Only necessary when using proxies
+
+ public Rect GetBackgroundRect(WindowState state)
+ {
+ var trackRect = m_TrackGUI.boundingRect;
+ return new Rect(
+ state.timeAreaTranslation.x + trackRect.xMin,
+ trackRect.y,
+ (float)state.editSequence.asset.duration * state.timeAreaScale.x,
+ trackRect.height
+ );
+ }
+
+ public List<CurveWrapper> GenerateWrappers(List<EditorCurveBinding> bindings)
+ {
+ var wrappers = new List<CurveWrapper>(bindings.Count);
+ int curveWrapperId = 0;
+
+ foreach (EditorCurveBinding b in bindings)
+ {
+ // General configuration
+ var wrapper = new CurveWrapper
+ {
+ id = curveWrapperId++,
+ binding = b,
+ groupId = -1,
+ hidden = false,
+ readOnly = false,
+ getAxisUiScalarsCallback = () => new Vector2(1, 1)
+ };
+
+ // Specific configuration
+ ConfigureCurveWrapper(wrapper);
+
+ wrappers.Add(wrapper);
+ }
+
+ return wrappers;
+ }
+
+ protected virtual void ConfigureCurveWrapper(CurveWrapper wrapper)
+ {
+ wrapper.color = CurveUtility.GetPropertyColor(wrapper.binding.propertyName);
+ wrapper.renderer = new NormalCurveRenderer(AnimationUtility.GetEditorCurve(animationClip, wrapper.binding));
+ wrapper.renderer.SetCustomRange(0.0f, animationClip.length);
+ }
+
+ protected virtual int CreateHashCode()
+ {
+ return m_TrackGUI.asset.GetHashCode();
+ }
+ }
+
+ class ClipAnimationCurveDataSource : CurveDataSource
+ {
+ static readonly string k_GroupingName = L10n.Tr("Animated Values");
+
+ readonly TimelineClipGUI m_ClipGUI;
+
+ public ClipAnimationCurveDataSource(TimelineClipGUI clipGUI) : base(clipGUI.parent)
+ {
+ m_ClipGUI = clipGUI;
+ }
+
+ public override AnimationClip animationClip
+ {
+ get { return m_ClipGUI.clip.animationClip; }
+ }
+
+ public override float start
+ {
+ get { return (float)m_ClipGUI.clip.FromLocalTimeUnbound(0.0); }
+ }
+
+ public override float timeScale
+ {
+ get { return (float)m_ClipGUI.clip.timeScale; }
+ }
+
+ public override string groupingName
+ {
+ get { return k_GroupingName; }
+ }
+
+ protected override int CreateHashCode()
+ {
+ return base.CreateHashCode().CombineHash(m_ClipGUI.clip.GetHashCode());
+ }
+ }
+
+ class ClipParametersCurveDataSource : CurveDataSource
+ {
+ static readonly string k_GroupingName = L10n.Tr("Clip Properties");
+
+ readonly TimelineClipGUI m_ClipGUI;
+ readonly CurvesProxy m_CurvesProxy;
+
+ public ClipParametersCurveDataSource(TimelineClipGUI clipGUI) : base(clipGUI.parent)
+ {
+ m_ClipGUI = clipGUI;
+ m_CurvesProxy = new CurvesProxy(clipGUI.clip);
+ }
+
+ public override AnimationClip animationClip
+ {
+ get { return m_CurvesProxy.curves; }
+ }
+
+ public override float start
+ {
+ get { return (float)m_ClipGUI.clip.FromLocalTimeUnbound(0.0); }
+ }
+
+ public override float timeScale
+ {
+ get { return (float)m_ClipGUI.clip.timeScale; }
+ }
+
+ public override string groupingName
+ {
+ get { return k_GroupingName; }
+ }
+
+ public override void UpdateCurves(List<CurveWrapper> updatedCurves)
+ {
+ m_CurvesProxy.UpdateCurves(updatedCurves);
+ }
+
+ public override void RebuildCurves()
+ {
+ m_CurvesProxy.RebuildCurves();
+ }
+
+ protected override void ConfigureCurveWrapper(CurveWrapper wrapper)
+ {
+ m_CurvesProxy.ConfigureCurveWrapper(wrapper);
+ }
+
+ protected override int CreateHashCode()
+ {
+ return base.CreateHashCode().CombineHash(m_ClipGUI.clip.GetHashCode());
+ }
+ }
+
+ class InfiniteClipCurveDataSource : CurveDataSource
+ {
+ static readonly string k_GroupingName = L10n.Tr("Animated Values");
+
+ readonly AnimationTrack m_AnimationTrack;
+
+ public InfiniteClipCurveDataSource(IRowGUI trackGui) : base(trackGui)
+ {
+ m_AnimationTrack = trackGui.asset as AnimationTrack;
+ }
+
+ public override AnimationClip animationClip
+ {
+ get { return m_AnimationTrack.infiniteClip; }
+ }
+
+ public override float start
+ {
+ get { return 0.0f; }
+ }
+
+ public override float timeScale
+ {
+ get { return 1.0f; }
+ }
+
+ public override string groupingName
+ {
+ get { return k_GroupingName; }
+ }
+ }
+
+ class TrackParametersCurveDataSource : CurveDataSource
+ {
+ static readonly string k_GroupingName = L10n.Tr("Track Properties");
+
+ readonly CurvesProxy m_CurvesProxy;
+
+ public TrackParametersCurveDataSource(IRowGUI trackGui) : base(trackGui)
+ {
+ m_CurvesProxy = new CurvesProxy(trackGui.asset);
+ }
+
+ public override AnimationClip animationClip
+ {
+ get { return m_CurvesProxy.curves; }
+ }
+
+ public override float start
+ {
+ get { return 0.0f; }
+ }
+
+ public override float timeScale
+ {
+ get { return 1.0f; }
+ }
+
+ public override string groupingName
+ {
+ get { return k_GroupingName; }
+ }
+
+ public override void UpdateCurves(List<CurveWrapper> updatedCurves)
+ {
+ m_CurvesProxy.UpdateCurves(updatedCurves);
+ }
+
+ public override void RebuildCurves()
+ {
+ m_CurvesProxy.RebuildCurves();
+ }
+
+ protected override void ConfigureCurveWrapper(CurveWrapper wrapper)
+ {
+ m_CurvesProxy.ConfigureCurveWrapper(wrapper);
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs.meta
new file mode 100644
index 0000000..6416ecf
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurveDataSource.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 87a1ae9719ec25d44a4dbec20ec0f892
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs
new file mode 100644
index 0000000..ce17112
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs
@@ -0,0 +1,302 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using JetBrains.Annotations;
+using UnityEngine;
+using UnityEngine.Timeline;
+using UnityObject = UnityEngine.Object;
+
+namespace UnityEditor.Timeline
+{
+ class CurvesProxy : ICurvesOwner
+ {
+ public AnimationClip curves
+ {
+ get { return proxyCurves != null ? proxyCurves : m_OriginalOwner.curves; }
+ }
+
+ public bool hasCurves
+ {
+ get { return m_IsAnimatable || m_OriginalOwner.hasCurves; }
+ }
+
+ public double duration
+ {
+ get { return m_OriginalOwner.duration; }
+ }
+
+ public string defaultCurvesName
+ {
+ get { return m_OriginalOwner.defaultCurvesName; }
+ }
+
+ public UnityObject asset
+ {
+ get { return m_OriginalOwner.asset; }
+ }
+
+ public UnityObject assetOwner
+ {
+ get { return m_OriginalOwner.assetOwner; }
+ }
+
+ public TrackAsset targetTrack
+ {
+ get { return m_OriginalOwner.targetTrack; }
+ }
+
+ readonly ICurvesOwner m_OriginalOwner;
+ readonly bool m_IsAnimatable;
+ readonly Dictionary<EditorCurveBinding, SerializedProperty> m_PropertiesMap = new Dictionary<EditorCurveBinding, SerializedProperty>();
+ int m_ProxyIsRebuilding = 0;
+
+ AnimationClip m_ProxyCurves;
+ AnimationClip proxyCurves
+ {
+ get
+ {
+ if (!m_IsAnimatable) return null;
+
+ if (m_ProxyCurves == null)
+ RebuildProxyCurves();
+
+ return m_ProxyCurves;
+ }
+ }
+
+ List<SerializedProperty> m_AllAnimatableParameters;
+ List<SerializedProperty> allAnimatableParameters
+ {
+ get
+ {
+ var so = AnimatedParameterUtility.GetSerializedPlayableAsset(m_OriginalOwner.asset);
+ if (so == null)
+ return null;
+
+ so.UpdateIfRequiredOrScript();
+
+ if (m_AllAnimatableParameters == null)
+ m_AllAnimatableParameters = m_OriginalOwner.GetAllAnimatableParameters().ToList();
+
+ return m_AllAnimatableParameters;
+ }
+ }
+
+ public CurvesProxy([NotNull] ICurvesOwner originalOwner)
+ {
+ m_OriginalOwner = originalOwner;
+ m_IsAnimatable = originalOwner.HasAnyAnimatableParameters();
+
+ RebuildProxyCurves();
+ }
+
+ public void CreateCurves(string curvesClipName)
+ {
+ m_OriginalOwner.CreateCurves(curvesClipName);
+ }
+
+ public void ConfigureCurveWrapper(CurveWrapper wrapper)
+ {
+ var color = CurveUtility.GetPropertyColor(wrapper.binding.propertyName);
+ wrapper.color = color;
+
+ float h, s, v;
+ Color.RGBToHSV(color, out h, out s, out v);
+ wrapper.wrapColorMultiplier = Color.HSVToRGB(h, s * 0.33f, v * 1.15f);
+
+ var curve = AnimationUtility.GetEditorCurve(proxyCurves, wrapper.binding);
+
+ wrapper.renderer = new NormalCurveRenderer(curve);
+
+ // Use curve length instead of animation clip length
+ wrapper.renderer.SetCustomRange(0.0f, curve.keys.Last().time);
+ }
+
+ public void RebuildCurves()
+ {
+ RebuildProxyCurves();
+ }
+
+ public void UpdateCurves(List<CurveWrapper> updatedCurves)
+ {
+ if (m_ProxyIsRebuilding > 0)
+ return;
+
+ Undo.RegisterCompleteObjectUndo(m_OriginalOwner.asset, "Edit Clip Curve");
+
+ if (m_OriginalOwner.curves != null)
+ Undo.RegisterCompleteObjectUndo(m_OriginalOwner.curves, "Edit Clip Curve");
+
+ foreach (var curve in updatedCurves)
+ {
+ UpdateCurve(curve.binding, curve.curve);
+ }
+
+ AnimatedParameterUtility.UpdateSerializedPlayableAsset(m_OriginalOwner.asset);
+ }
+
+ void UpdateCurve(EditorCurveBinding binding, AnimationCurve curve)
+ {
+ ApplyConstraints(binding, curve);
+
+ if (curve.length == 0)
+ {
+ HandleAllKeysDeleted(binding);
+ }
+ else if (curve.length == 1)
+ {
+ HandleConstantCurveValueChanged(binding, curve);
+ }
+ else
+ {
+ HandleCurveUpdated(binding, curve);
+ }
+ }
+
+ void ApplyConstraints(EditorCurveBinding binding, AnimationCurve curve)
+ {
+ if (curve.length == 0)
+ return;
+
+ var curveUpdated = false;
+
+ var property = m_PropertiesMap[binding];
+ if (property.propertyType == SerializedPropertyType.Boolean)
+ {
+ TimelineAnimationUtilities.ConstrainCurveToBooleanValues(curve);
+ curveUpdated = true;
+ }
+ else
+ {
+ var range = AnimatedParameterUtility.GetAttributeForProperty<RangeAttribute>(property);
+ if (range != null)
+ {
+ TimelineAnimationUtilities.ConstrainCurveToRange(curve, range.min, range.max);
+ curveUpdated = true;
+ }
+ }
+
+ if (!curveUpdated)
+ return;
+
+ using (new RebuildGuard(this))
+ {
+ AnimationUtility.SetEditorCurve(m_ProxyCurves, binding, curve);
+ }
+ }
+
+ void HandleCurveUpdated(EditorCurveBinding binding, AnimationCurve updatedCurve)
+ {
+ if (!m_OriginalOwner.hasCurves)
+ m_OriginalOwner.CreateCurves(null);
+
+ AnimationUtility.SetEditorCurve(m_OriginalOwner.curves, binding, updatedCurve);
+ }
+
+ void HandleConstantCurveValueChanged(EditorCurveBinding binding, AnimationCurve updatedCurve)
+ {
+ var prop = m_PropertiesMap[binding];
+ if (prop == null)
+ return;
+
+ Undo.RegisterCompleteObjectUndo(prop.serializedObject.targetObject, "Edit Clip Curve");
+ prop.serializedObject.UpdateIfRequiredOrScript();
+ CurveEditUtility.SetFromKeyValue(prop, updatedCurve.keys[0].value);
+ prop.serializedObject.ApplyModifiedProperties();
+ }
+
+ void HandleAllKeysDeleted(EditorCurveBinding binding)
+ {
+ if (m_OriginalOwner.hasCurves)
+ {
+ // Remove curve from original asset
+ AnimationUtility.SetEditorCurve(m_OriginalOwner.curves, binding, null);
+ m_OriginalOwner.SanitizeCurvesData();
+ }
+
+ // Ensure proxy still has constant value
+ RebuildProxyCurves();
+ }
+
+ void RebuildProxyCurves()
+ {
+ if (!m_IsAnimatable)
+ return;
+
+ using (new RebuildGuard(this))
+ {
+ if (m_ProxyCurves == null)
+ {
+ m_ProxyCurves = new AnimationClip
+ {
+ legacy = true,
+ name = "Constant Curves",
+ hideFlags = HideFlags.HideAndDontSave,
+ frameRate = m_OriginalOwner.targetTrack.timelineAsset == null
+ ? TimelineAsset.EditorSettings.kDefaultFps
+ : m_OriginalOwner.targetTrack.timelineAsset.editorSettings.fps
+ };
+ }
+ else
+ {
+ m_ProxyCurves.ClearCurves();
+ }
+
+ m_OriginalOwner.SanitizeCurvesData();
+ AnimatedParameterUtility.UpdateSerializedPlayableAsset(m_OriginalOwner.asset);
+
+ foreach (var param in allAnimatableParameters)
+ CreateProxyCurve(param, m_ProxyCurves, m_OriginalOwner.asset, param.propertyPath);
+
+ AnimationClipCurveCache.Instance.GetCurveInfo(m_ProxyCurves).dirty = true;
+ }
+ }
+
+ void CreateProxyCurve(SerializedProperty prop, AnimationClip clip, UnityObject owner, string propertyName)
+ {
+ var binding = AnimatedParameterUtility.GetCurveBinding(owner, propertyName);
+
+ var originalCurve = m_OriginalOwner.hasCurves
+ ? AnimationUtility.GetEditorCurve(m_OriginalOwner.curves, binding)
+ : null;
+
+ if (originalCurve != null)
+ {
+ AnimationUtility.SetEditorCurve(clip, binding, originalCurve);
+ }
+ else
+ {
+ var curve = new AnimationCurve();
+
+ CurveEditUtility.AddKeyFrameToCurve(
+ curve, 0.0f, clip.frameRate, CurveEditUtility.GetKeyValue(prop),
+ prop.propertyType == SerializedPropertyType.Boolean);
+
+ AnimationUtility.SetEditorCurve(clip, binding, curve);
+ }
+
+ m_PropertiesMap[binding] = prop;
+ }
+
+ struct RebuildGuard : IDisposable
+ {
+ CurvesProxy m_Owner;
+ AnimationUtility.OnCurveWasModified m_Callback;
+
+ public RebuildGuard(CurvesProxy owner)
+ {
+ m_Callback = AnimationUtility.onCurveWasModified;
+ AnimationUtility.onCurveWasModified = null;
+ m_Owner = owner;
+ m_Owner.m_ProxyIsRebuilding++;
+ }
+
+ public void Dispose()
+ {
+ AnimationUtility.onCurveWasModified = m_Callback;
+ m_Owner.m_ProxyIsRebuilding--;
+ m_Owner = null;
+ }
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs.meta
new file mode 100644
index 0000000..18e3029
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/CurvesProxy.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d72ccd2c66ea846fc842adf682b11526
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs
new file mode 100644
index 0000000..60cf7cc
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs
@@ -0,0 +1,435 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using UnityEditor;
+using UnityEngineInternal;
+using UnityEngine.Timeline;
+using UnityEngine.Playables;
+using Object = UnityEngine.Object;
+
+namespace UnityEditor.Timeline
+{
+ class TimelineAnimationUtilities
+ {
+ public enum OffsetEditMode
+ {
+ None = -1,
+ Translation = 0,
+ Rotation = 1
+ }
+
+ public static bool ValidateOffsetAvailabitity(PlayableDirector director, Animator animator)
+ {
+ if (director == null || animator == null)
+ return false;
+
+ return true;
+ }
+
+ public static TimelineClip GetPreviousClip(TimelineClip clip)
+ {
+ TimelineClip previousClip = null;
+ foreach (var c in clip.parentTrack.clips)
+ {
+ if (c.start < clip.start && (previousClip == null || c.start >= previousClip.start))
+ previousClip = c;
+ }
+ return previousClip;
+ }
+
+ public static TimelineClip GetNextClip(TimelineClip clip)
+ {
+ return clip.parentTrack.clips.Where(c => c.start > clip.start).OrderBy(c => c.start).FirstOrDefault();
+ }
+
+ public struct RigidTransform
+ {
+ public Vector3 position;
+ public Quaternion rotation;
+
+ public static RigidTransform Compose(Vector3 pos, Quaternion rot)
+ {
+ RigidTransform ret;
+ ret.position = pos;
+ ret.rotation = rot;
+ return ret;
+ }
+
+ public static RigidTransform Mul(RigidTransform a, RigidTransform b)
+ {
+ RigidTransform ret;
+ ret.rotation = a.rotation * b.rotation;
+ ret.position = a.position + a.rotation * b.position;
+ return ret;
+ }
+
+ public static RigidTransform Inverse(RigidTransform a)
+ {
+ RigidTransform ret;
+ ret.rotation = Quaternion.Inverse(a.rotation);
+ ret.position = ret.rotation * (-a.position);
+ return ret;
+ }
+
+ public static RigidTransform identity
+ {
+ get { return Compose(Vector3.zero, Quaternion.identity); }
+ }
+ }
+
+
+ private static Matrix4x4 GetTrackMatrix(Transform transform, AnimationTrack track)
+ {
+ Matrix4x4 trackMatrix = Matrix4x4.TRS(track.position, track.rotation, Vector3.one);
+
+ // in scene off mode, the track offsets are set to the preview position which is stored in the track
+ if (track.trackOffset == TrackOffset.ApplySceneOffsets)
+ {
+ trackMatrix = Matrix4x4.TRS(track.sceneOffsetPosition, Quaternion.Euler(track.sceneOffsetRotation), Vector3.one);
+ }
+
+ // put the parent transform on to the track matrix
+ if (transform.parent != null)
+ {
+ trackMatrix = transform.parent.localToWorldMatrix * trackMatrix;
+ }
+
+ return trackMatrix;
+ }
+
+ // Given a world space position and rotation, updates the clip offsets to match that
+ public static RigidTransform UpdateClipOffsets(AnimationPlayableAsset asset, AnimationTrack track, Transform transform, Vector3 globalPosition, Quaternion globalRotation)
+ {
+ Matrix4x4 worldToLocal = transform.worldToLocalMatrix;
+ Matrix4x4 clipMatrix = Matrix4x4.TRS(asset.position, asset.rotation, Vector3.one);
+ Matrix4x4 trackMatrix = GetTrackMatrix(transform, track);
+
+
+ // Use the transform to find the proper goal matrix with scale taken into account
+ var oldPos = transform.position;
+ var oldRot = transform.rotation;
+ transform.position = globalPosition;
+ transform.rotation = globalRotation;
+ Matrix4x4 goal = transform.localToWorldMatrix;
+ transform.position = oldPos;
+ transform.rotation = oldRot;
+
+ // compute the new clip matrix.
+ Matrix4x4 newClip = trackMatrix.inverse * goal * worldToLocal * trackMatrix * clipMatrix;
+ return RigidTransform.Compose(newClip.GetColumn(3), MathUtils.QuaternionFromMatrix(newClip));
+ }
+
+ public static RigidTransform GetTrackOffsets(AnimationTrack track, Transform transform)
+ {
+ Vector3 position = track.position;
+ Quaternion rotation = track.rotation;
+ if (transform != null && transform.parent != null)
+ {
+ position = transform.parent.TransformPoint(position);
+ rotation = transform.parent.rotation * rotation;
+ MathUtils.QuaternionNormalize(ref rotation);
+ }
+
+ return RigidTransform.Compose(position, rotation);
+ }
+
+ public static void UpdateTrackOffset(AnimationTrack track, Transform transform, RigidTransform offsets)
+ {
+ if (transform != null && transform.parent != null)
+ {
+ offsets.position = transform.parent.InverseTransformPoint(offsets.position);
+ offsets.rotation = Quaternion.Inverse(transform.parent.rotation) * offsets.rotation;
+ MathUtils.QuaternionNormalize(ref offsets.rotation);
+ }
+
+ track.position = offsets.position;
+ track.eulerAngles = AnimationUtility.GetClosestEuler(offsets.rotation, track.eulerAngles, RotationOrder.OrderZXY);
+ track.UpdateClipOffsets();
+ }
+
+ static MatchTargetFields GetMatchFields(TimelineClip clip)
+ {
+ var track = clip.parentTrack as AnimationTrack;
+ if (track == null)
+ return MatchTargetFieldConstants.None;
+
+ var asset = clip.asset as AnimationPlayableAsset;
+ var fields = track.matchTargetFields;
+ if (asset != null && !asset.useTrackMatchFields)
+ fields = asset.matchTargetFields;
+ return fields;
+ }
+
+ static void WriteMatchFields(AnimationPlayableAsset asset, RigidTransform result, MatchTargetFields fields)
+ {
+ Vector3 position = asset.position;
+
+ position.x = fields.HasAny(MatchTargetFields.PositionX) ? result.position.x : position.x;
+ position.y = fields.HasAny(MatchTargetFields.PositionY) ? result.position.y : position.y;
+ position.z = fields.HasAny(MatchTargetFields.PositionZ) ? result.position.z : position.z;
+
+ asset.position = position;
+
+ // check first to avoid unnecessary conversion errors
+ if (fields.HasAny(MatchTargetFieldConstants.Rotation))
+ {
+ Vector3 eulers = asset.eulerAngles;
+ Vector3 resultEulers = result.rotation.eulerAngles;
+
+ eulers.x = fields.HasAny(MatchTargetFields.RotationX) ? resultEulers.x : eulers.x;
+ eulers.y = fields.HasAny(MatchTargetFields.RotationY) ? resultEulers.y : eulers.y;
+ eulers.z = fields.HasAny(MatchTargetFields.RotationZ) ? resultEulers.z : eulers.z;
+
+ asset.eulerAngles = AnimationUtility.GetClosestEuler(Quaternion.Euler(eulers), asset.eulerAngles, RotationOrder.OrderZXY);
+ }
+ }
+
+ public static void MatchPrevious(TimelineClip currentClip, Transform matchPoint, PlayableDirector director)
+ {
+ const double timeEpsilon = 0.00001;
+ MatchTargetFields matchFields = GetMatchFields(currentClip);
+ if (matchFields == MatchTargetFieldConstants.None || matchPoint == null)
+ return;
+
+ double cachedTime = director.time;
+
+ // finds previous clip
+ TimelineClip previousClip = GetPreviousClip(currentClip);
+ if (previousClip == null || currentClip == previousClip)
+ return;
+
+ // make sure the transform is properly updated before modifying the graph
+ director.Evaluate();
+
+ var parentTrack = currentClip.parentTrack as AnimationTrack;
+
+ var blendIn = currentClip.blendInDuration;
+ currentClip.blendInDuration = 0;
+ var blendOut = previousClip.blendOutDuration;
+ previousClip.blendOutDuration = 0;
+
+ //evaluate previous without current
+ parentTrack.RemoveClip(currentClip);
+ director.RebuildGraph();
+ double previousEndTime = currentClip.start > previousClip.end ? previousClip.end : currentClip.start;
+ director.time = previousEndTime - timeEpsilon;
+ director.Evaluate(); // add port to evaluate only track
+
+ var targetPosition = matchPoint.position;
+ var targetRotation = matchPoint.rotation;
+
+ // evaluate current without previous
+ parentTrack.AddClip(currentClip);
+ parentTrack.RemoveClip(previousClip);
+ director.RebuildGraph();
+ director.time = currentClip.start + timeEpsilon;
+ director.Evaluate();
+
+ //////////////////////////////////////////////////////////////////////
+ //compute offsets
+
+ var animationPlayable = currentClip.asset as AnimationPlayableAsset;
+ var match = UpdateClipOffsets(animationPlayable, parentTrack, matchPoint, targetPosition, targetRotation);
+ WriteMatchFields(animationPlayable, match, matchFields);
+
+ //////////////////////////////////////////////////////////////////////
+
+ currentClip.blendInDuration = blendIn;
+ previousClip.blendOutDuration = blendOut;
+
+ parentTrack.AddClip(previousClip);
+ director.RebuildGraph();
+ director.time = cachedTime;
+ director.Evaluate();
+ }
+
+ public static void MatchNext(TimelineClip currentClip, Transform matchPoint, PlayableDirector director)
+ {
+ const double timeEpsilon = 0.00001;
+ MatchTargetFields matchFields = GetMatchFields(currentClip);
+ if (matchFields == MatchTargetFieldConstants.None || matchPoint == null)
+ return;
+
+ double cachedTime = director.time;
+
+ // finds next clip
+ TimelineClip nextClip = GetNextClip(currentClip);
+ if (nextClip == null || currentClip == nextClip)
+ return;
+
+ // make sure the transform is properly updated before modifying the graph
+ director.Evaluate();
+
+ var parentTrack = currentClip.parentTrack as AnimationTrack;
+
+ var blendOut = currentClip.blendOutDuration;
+ var blendIn = nextClip.blendInDuration;
+ currentClip.blendOutDuration = 0;
+ nextClip.blendInDuration = 0;
+
+ //evaluate previous without current
+ parentTrack.RemoveClip(currentClip);
+ director.RebuildGraph();
+ director.time = nextClip.start + timeEpsilon;
+ director.Evaluate(); // add port to evaluate only track
+
+ var targetPosition = matchPoint.position;
+ var targetRotation = matchPoint.rotation;
+
+ // evaluate current without next
+ parentTrack.AddClip(currentClip);
+ parentTrack.RemoveClip(nextClip);
+ director.RebuildGraph();
+ director.time = Math.Min(nextClip.start, currentClip.end - timeEpsilon);
+ director.Evaluate();
+
+ //////////////////////////////////////////////////////////////////////
+ //compute offsets
+
+ var animationPlayable = currentClip.asset as AnimationPlayableAsset;
+ var match = UpdateClipOffsets(animationPlayable, parentTrack, matchPoint, targetPosition, targetRotation);
+ WriteMatchFields(animationPlayable, match, matchFields);
+
+ //////////////////////////////////////////////////////////////////////
+
+ currentClip.blendOutDuration = blendOut;
+ nextClip.blendInDuration = blendIn;
+
+ parentTrack.AddClip(nextClip);
+ director.RebuildGraph();
+ director.time = cachedTime;
+ director.Evaluate();
+ }
+
+ public static TimelineWindowTimeControl CreateTimeController(WindowState state, TimelineClip clip)
+ {
+ var animationWindow = EditorWindow.GetWindow<AnimationWindow>();
+ var timeController = ScriptableObject.CreateInstance<TimelineWindowTimeControl>();
+ timeController.Init(animationWindow.state, clip);
+ return timeController;
+ }
+
+ public static TimelineWindowTimeControl CreateTimeController(WindowState state, TimelineWindowTimeControl.ClipData clipData)
+ {
+ var animationWindow = EditorWindow.GetWindow<AnimationWindow>();
+ var timeController = ScriptableObject.CreateInstance<TimelineWindowTimeControl>();
+ timeController.Init(animationWindow.state, clipData);
+ return timeController;
+ }
+
+ public static void EditAnimationClipWithTimeController(AnimationClip animationClip, TimelineWindowTimeControl timeController, Object sourceObject)
+ {
+ var animationWindow = EditorWindow.GetWindow<AnimationWindow>();
+ animationWindow.EditSequencerClip(animationClip, sourceObject, timeController);
+ }
+
+ public static void UnlinkAnimationWindowFromTracks(IEnumerable<TrackAsset> tracks)
+ {
+ var clips = new List<AnimationClip>();
+ foreach (var track in tracks)
+ {
+ var animationTrack = track as AnimationTrack;
+ if (animationTrack != null && animationTrack.infiniteClip != null)
+ clips.Add(animationTrack.infiniteClip);
+
+ GetAnimationClips(track.GetClips(), clips);
+ }
+ UnlinkAnimationWindowFromAnimationClips(clips);
+ }
+
+ public static void UnlinkAnimationWindowFromClips(IEnumerable<TimelineClip> timelineClips)
+ {
+ var clips = new List<AnimationClip>();
+ GetAnimationClips(timelineClips, clips);
+ UnlinkAnimationWindowFromAnimationClips(clips);
+ }
+
+ public static void UnlinkAnimationWindowFromAnimationClips(ICollection<AnimationClip> clips)
+ {
+ if (clips.Count == 0)
+ return;
+
+ UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(typeof(AnimationWindow));
+ foreach (var animWindow in windows.OfType<AnimationWindow>())
+ {
+ if (animWindow != null && animWindow.state != null && animWindow.state.linkedWithSequencer && clips.Contains(animWindow.state.activeAnimationClip))
+ animWindow.UnlinkSequencer();
+ }
+ }
+
+ public static void UnlinkAnimationWindow()
+ {
+ UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(typeof(AnimationWindow));
+ foreach (var animWindow in windows.OfType<AnimationWindow>())
+ {
+ if (animWindow != null && animWindow.state != null && animWindow.state.linkedWithSequencer)
+ animWindow.UnlinkSequencer();
+ }
+ }
+
+ private static void GetAnimationClips(IEnumerable<TimelineClip> timelineClips, List<AnimationClip> clips)
+ {
+ foreach (var timelineClip in timelineClips)
+ {
+ if (timelineClip.curves != null)
+ clips.Add(timelineClip.curves);
+ AnimationPlayableAsset apa = timelineClip.asset as AnimationPlayableAsset;
+ if (apa != null && apa.clip != null)
+ clips.Add(apa.clip);
+ }
+ }
+
+ public static int GetAnimationWindowCurrentFrame()
+ {
+ var animationWindow = EditorWindow.GetWindow<AnimationWindow>();
+ if (animationWindow)
+ return animationWindow.state.currentFrame;
+ return -1;
+ }
+
+ public static void SetAnimationWindowCurrentFrame(int frame)
+ {
+ var animationWindow = EditorWindow.GetWindow<AnimationWindow>();
+ if (animationWindow)
+ animationWindow.state.currentFrame = frame;
+ }
+
+ public static void ConstrainCurveToBooleanValues(AnimationCurve curve)
+ {
+ // Clamp the values first
+ var keys = curve.keys;
+ for (var i = 0; i < keys.Length; i++)
+ {
+ var key = keys[i];
+ key.value = key.value < 0.5f ? 0.0f : 1.0f;
+ keys[i] = key;
+ }
+ curve.keys = keys;
+
+ // Update the tangents once all the values are clamped
+ for (var i = 0; i < curve.length; i++)
+ {
+ AnimationUtility.SetKeyLeftTangentMode(curve, i, AnimationUtility.TangentMode.Constant);
+ AnimationUtility.SetKeyRightTangentMode(curve, i, AnimationUtility.TangentMode.Constant);
+ }
+ }
+
+ public static void ConstrainCurveToRange(AnimationCurve curve, float minValue, float maxValue)
+ {
+ var keys = curve.keys;
+ for (var i = 0; i < keys.Length; i++)
+ {
+ var key = keys[i];
+ key.value = Mathf.Clamp(key.value, minValue, maxValue);
+ keys[i] = key;
+ }
+ curve.keys = keys;
+ }
+
+ public static bool IsAnimationClip(TimelineClip clip)
+ {
+ return clip != null && (clip.asset as AnimationPlayableAsset) != null;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs.meta
new file mode 100644
index 0000000..78ae589
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Animation/TimelineAnimationUtilities.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9685354eb873b8d4699078b307b0f260
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: