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