TimelineRecording_PlayableAsset.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEngine;
  4. using UnityEngine.Timeline;
  5. using UnityEngine.Playables;
  6. namespace UnityEditor.Timeline
  7. {
  8. // Handles Undo animated properties on PlayableAssets from clips to create parameter animation
  9. static partial class TimelineRecording
  10. {
  11. internal static bool HasAnyPlayableAssetModifications(UndoPropertyModification[] modifications)
  12. {
  13. return modifications.Any(x => GetTarget(x) as IPlayableAsset != null);
  14. }
  15. internal static UndoPropertyModification[] ProcessPlayableAssetModification(UndoPropertyModification[] modifications, WindowState state)
  16. {
  17. // can't record without a director since the asset being modified might be a scene instance
  18. if (state == null || state.editSequence.director == null)
  19. return modifications;
  20. var remaining = new List<UndoPropertyModification>();
  21. foreach (UndoPropertyModification mod in modifications)
  22. {
  23. if (!ProcessPlayableAssetModification(mod, state))
  24. remaining.Add(mod);
  25. }
  26. if (remaining.Count != modifications.Length)
  27. {
  28. state.rebuildGraph = true;
  29. state.GetWindow().Repaint();
  30. }
  31. return remaining.ToArray();
  32. }
  33. static bool ProcessPlayableAssetModification(UndoPropertyModification mod, WindowState state)
  34. {
  35. var target = GetTarget(mod) as IPlayableAsset;
  36. if (target == null)
  37. return false;
  38. var curvesOwner = AnimatedParameterUtility.ToCurvesOwner(target, state.editSequence.asset);
  39. if (curvesOwner == null || !curvesOwner.HasAnyAnimatableParameters())
  40. return false;
  41. return ProcessPlayableAssetRecording(mod, state, curvesOwner);
  42. }
  43. internal static TimelineClip FindClipWithAsset(TimelineAsset asset, IPlayableAsset target)
  44. {
  45. if (target == null || asset == null)
  46. return null;
  47. var clips = asset.flattenedTracks.SelectMany(x => x.clips);
  48. return clips.FirstOrDefault(x => x != null && x.asset != null && target == x.asset as IPlayableAsset);
  49. }
  50. static bool ProcessPlayableAssetRecording(UndoPropertyModification mod, WindowState state, ICurvesOwner curvesOwner)
  51. {
  52. if (mod.currentValue == null)
  53. return false;
  54. if (!curvesOwner.IsParameterAnimatable(mod.currentValue.propertyPath))
  55. return false;
  56. var localTime = state.editSequence.time;
  57. var timelineClip = curvesOwner as TimelineClip;
  58. if (timelineClip != null)
  59. {
  60. // don't use time global to local since it will possibly loop.
  61. localTime = timelineClip.ToLocalTimeUnbound(state.editSequence.time);
  62. }
  63. if (localTime < 0)
  64. return false;
  65. // grab the value from the current modification
  66. float fValue = 0;
  67. if (!float.TryParse(mod.currentValue.value, out fValue))
  68. {
  69. // case 916913 -- 'Add Key' menu item will passes 'True' or 'False' (instead of 1, 0)
  70. // so we need a special case to parse the boolean string
  71. bool bValue;
  72. if (!bool.TryParse(mod.currentValue.value, out bValue))
  73. {
  74. Debug.Assert(false, "Invalid type in PlayableAsset recording");
  75. return false;
  76. }
  77. fValue = bValue ? 1 : 0;
  78. }
  79. var added = curvesOwner.AddAnimatedParameterValueAt(mod.currentValue.propertyPath, fValue, (float)localTime);
  80. if (added && AnimationMode.InAnimationMode())
  81. {
  82. EditorCurveBinding binding = curvesOwner.GetCurveBinding(mod.previousValue.propertyPath);
  83. AnimationMode.AddPropertyModification(binding, mod.previousValue, true);
  84. curvesOwner.targetTrack.SetShowInlineCurves(true);
  85. if (state.GetWindow() != null && state.GetWindow().treeView != null)
  86. state.GetWindow().treeView.CalculateRowRects();
  87. }
  88. return added;
  89. }
  90. static bool IsPlayableAssetProperty(SerializedProperty property)
  91. {
  92. return property.serializedObject.targetObject is IPlayableAsset;
  93. }
  94. }
  95. }