440 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			440 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using UnityEngine;
 | |
| using UnityEngine.Timeline;
 | |
| 
 | |
| namespace UnityEditor.Timeline
 | |
| {
 | |
|     enum CurveChangeType
 | |
|     {
 | |
|         None,
 | |
|         CurveModified,
 | |
|         CurveAddedOrRemoved
 | |
|     }
 | |
| 
 | |
|     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 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; }
 | |
| 
 | |
|         // Applies changes from the visual curve in the curve wrapper back to the animation clips
 | |
|         public virtual void ApplyCurveChanges(IEnumerable<CurveWrapper> updatedCurves)
 | |
|         {
 | |
|             Undo.RegisterCompleteObjectUndo(animationClip, "Edit Clip Curve");
 | |
|             foreach (CurveWrapper c in updatedCurves)
 | |
|             {
 | |
|                 if (c.curve.length > 0)
 | |
|                     AnimationUtility.SetEditorCurve(animationClip, c.binding, c.curve);
 | |
|                 else
 | |
|                     RemoveCurves(new[] { c.binding });
 | |
|                 c.changed = false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>The clip version is a value that will change when a curve gets updated.
 | |
|         /// it's used to detect when an animation clip has been changed externally </summary>
 | |
|         /// <returns>A versioning value indicating the state of the curve. If the curve is updated externally this value will change. </returns>
 | |
|         public virtual UInt64 GetClipVersion()
 | |
|         {
 | |
|             return animationClip.ClipVersion();
 | |
|         }
 | |
| 
 | |
|         /// <summary>Call this method to check if the underlying clip has changed</summary>
 | |
|         /// <param name="curveVersion">A versioning value. This will be updated to the latest version</param>
 | |
|         /// <returns>A value indicating how the clip has changed</returns>
 | |
|         public virtual CurveChangeType UpdateExternalChanges(ref UInt64 curveVersion)
 | |
|         {
 | |
|             return animationClip.GetChangeType(ref curveVersion);
 | |
|         }
 | |
| 
 | |
|         public virtual string ModifyPropertyDisplayName(string path, string propertyName) => propertyName;
 | |
| 
 | |
|         public virtual void RemoveCurves(IEnumerable<EditorCurveBinding> bindings)
 | |
|         {
 | |
|             Undo.RegisterCompleteObjectUndo(animationClip, "Remove Curve(s)");
 | |
|             foreach (var binding in bindings)
 | |
|             {
 | |
|                 if (binding.isPPtrCurve)
 | |
|                     AnimationUtility.SetObjectReferenceCurve(animationClip, binding, null);
 | |
|                 else
 | |
|                     AnimationUtility.SetEditorCurve(animationClip, binding, null);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         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(IEnumerable<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());
 | |
|         }
 | |
| 
 | |
|         public override string ModifyPropertyDisplayName(string path, string propertyName)
 | |
|         {
 | |
|             if (!AnimatedPropertyUtility.IsMaterialProperty(propertyName))
 | |
|                 return propertyName;
 | |
| 
 | |
|             var track = m_ClipGUI.clip.GetParentTrack();
 | |
|             if (track == null)
 | |
|                 return propertyName;
 | |
| 
 | |
|             var gameObjectBinding = TimelineUtility.GetSceneGameObject(TimelineEditor.inspectedDirector, track);
 | |
|             if (gameObjectBinding == null)
 | |
|                 return propertyName;
 | |
| 
 | |
|             if (!string.IsNullOrEmpty(path))
 | |
|             {
 | |
|                 var transform = gameObjectBinding.transform.Find(path);
 | |
|                 if (transform == null)
 | |
|                     return propertyName;
 | |
|                 gameObjectBinding = transform.gameObject;
 | |
|             }
 | |
| 
 | |
|             return AnimatedPropertyUtility.RemapMaterialName(gameObjectBinding, propertyName);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class ClipParametersCurveDataSource : CurveDataSource
 | |
|     {
 | |
|         static readonly string k_GroupingName = L10n.Tr("Clip Properties");
 | |
| 
 | |
|         readonly TimelineClipGUI m_ClipGUI;
 | |
|         readonly CurvesProxy m_CurvesProxy;
 | |
| 
 | |
|         private int m_ClipDirtyVersion;
 | |
| 
 | |
|         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 UInt64 GetClipVersion()
 | |
|         {
 | |
|             return sourceAnimationClip.ClipVersion();
 | |
|         }
 | |
| 
 | |
|         public override CurveChangeType UpdateExternalChanges(ref ulong curveVersion)
 | |
|         {
 | |
|             if (m_ClipGUI == null || m_ClipGUI.clip == null)
 | |
|                 return CurveChangeType.None;
 | |
| 
 | |
|             var changeType = sourceAnimationClip.GetChangeType(ref curveVersion);
 | |
|             if (changeType != CurveChangeType.None)
 | |
|             {
 | |
|                 m_CurvesProxy.ApplyExternalChangesToProxy();
 | |
|             }
 | |
|             else if (m_ClipDirtyVersion != m_ClipGUI.clip.DirtyIndex)
 | |
|             {
 | |
|                 m_CurvesProxy.UpdateProxyCurves();
 | |
|                 if (changeType == CurveChangeType.None)
 | |
|                     changeType = CurveChangeType.CurveModified;
 | |
|             }
 | |
|             m_ClipDirtyVersion = m_ClipGUI.clip.DirtyIndex;
 | |
|             return changeType;
 | |
|         }
 | |
| 
 | |
|         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 RemoveCurves(IEnumerable<EditorCurveBinding> bindings)
 | |
|         {
 | |
|             m_CurvesProxy.RemoveCurves(bindings);
 | |
|         }
 | |
| 
 | |
|         public override void ApplyCurveChanges(IEnumerable<CurveWrapper> updatedCurves)
 | |
|         {
 | |
|             m_CurvesProxy.UpdateCurves(updatedCurves);
 | |
|         }
 | |
| 
 | |
|         protected override void ConfigureCurveWrapper(CurveWrapper wrapper)
 | |
|         {
 | |
|             m_CurvesProxy.ConfigureCurveWrapper(wrapper);
 | |
|         }
 | |
| 
 | |
|         protected override int CreateHashCode()
 | |
|         {
 | |
|             return base.CreateHashCode().CombineHash(m_ClipGUI.clip.GetHashCode());
 | |
|         }
 | |
| 
 | |
|         private AnimationClip sourceAnimationClip
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (m_ClipGUI == null || m_ClipGUI.clip == null || m_ClipGUI.clip.curves == null)
 | |
|                     return null;
 | |
|                 return m_ClipGUI.clip.curves;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     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; }
 | |
|         }
 | |
| 
 | |
|         public override string ModifyPropertyDisplayName(string path, string propertyName)
 | |
|         {
 | |
|             if (m_AnimationTrack == null || !AnimatedPropertyUtility.IsMaterialProperty(propertyName))
 | |
|                 return propertyName;
 | |
| 
 | |
|             var binding = m_AnimationTrack.GetBinding(TimelineEditor.inspectedDirector);
 | |
|             if (binding == null)
 | |
|                 return propertyName;
 | |
| 
 | |
|             var target = binding.transform;
 | |
|             if (!string.IsNullOrEmpty(path))
 | |
|                 target = target.Find(path);
 | |
| 
 | |
|             if (target == null)
 | |
|                 return propertyName;
 | |
| 
 | |
|             return AnimatedPropertyUtility.RemapMaterialName(target.gameObject, propertyName);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     class TrackParametersCurveDataSource : CurveDataSource
 | |
|     {
 | |
|         static readonly string k_GroupingName = L10n.Tr("Track Properties");
 | |
| 
 | |
|         readonly CurvesProxy m_CurvesProxy;
 | |
|         private int m_TrackDirtyVersion;
 | |
| 
 | |
|         public TrackParametersCurveDataSource(IRowGUI trackGui) : base(trackGui)
 | |
|         {
 | |
|             m_CurvesProxy = new CurvesProxy(trackGui.asset);
 | |
|         }
 | |
| 
 | |
|         public override AnimationClip animationClip
 | |
|         {
 | |
|             get { return m_CurvesProxy.curves; }
 | |
|         }
 | |
| 
 | |
|         public override UInt64 GetClipVersion()
 | |
|         {
 | |
|             return sourceAnimationClip.ClipVersion();
 | |
|         }
 | |
| 
 | |
|         public override CurveChangeType UpdateExternalChanges(ref ulong curveVersion)
 | |
|         {
 | |
|             if (m_CurvesProxy.targetTrack == null)
 | |
|                 return CurveChangeType.None;
 | |
| 
 | |
|             var changeType = sourceAnimationClip.GetChangeType(ref curveVersion);
 | |
|             if (changeType != CurveChangeType.None)
 | |
|             {
 | |
|                 m_CurvesProxy.ApplyExternalChangesToProxy();
 | |
|             }
 | |
|             // track property has changed externally, update the curve proxies
 | |
|             else if (m_TrackDirtyVersion != m_CurvesProxy.targetTrack.DirtyIndex)
 | |
|             {
 | |
|                 if (changeType == CurveChangeType.None)
 | |
|                     changeType = CurveChangeType.CurveModified;
 | |
|                 m_CurvesProxy.UpdateProxyCurves();
 | |
|             }
 | |
|             m_TrackDirtyVersion = m_CurvesProxy.targetTrack.DirtyIndex;
 | |
|             return changeType;
 | |
|         }
 | |
| 
 | |
|         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 RemoveCurves(IEnumerable<EditorCurveBinding> bindings)
 | |
|         {
 | |
|             m_CurvesProxy.RemoveCurves(bindings);
 | |
|         }
 | |
| 
 | |
|         public override void ApplyCurveChanges(IEnumerable<CurveWrapper> updatedCurves)
 | |
|         {
 | |
|             m_CurvesProxy.UpdateCurves(updatedCurves);
 | |
|         }
 | |
| 
 | |
|         protected override void ConfigureCurveWrapper(CurveWrapper wrapper)
 | |
|         {
 | |
|             m_CurvesProxy.ConfigureCurveWrapper(wrapper);
 | |
|         }
 | |
| 
 | |
|         private AnimationClip sourceAnimationClip
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (m_CurvesProxy.targetTrack == null || m_CurvesProxy.targetTrack.curves == null)
 | |
|                     return null;
 | |
|                 return m_CurvesProxy.targetTrack.curves;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |