PropertyCollector.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.Playables;
  6. using UnityEngine.Timeline;
  7. using Object = UnityEngine.Object;
  8. namespace UnityEditor.Timeline
  9. {
  10. class PropertyCollector : IPropertyCollector
  11. {
  12. readonly Stack<GameObject> m_ObjectStack = new Stack<GameObject>();
  13. // Call immediately before use
  14. public void Reset()
  15. {
  16. m_ObjectStack.Clear();
  17. }
  18. // call to reset caches. should be called when switching master timelines
  19. public void Clear()
  20. {
  21. m_ObjectStack.Clear();
  22. AnimationPreviewUtilities.ClearCaches();
  23. }
  24. public void PushActiveGameObject(GameObject gameObject)
  25. {
  26. m_ObjectStack.Push(gameObject);
  27. }
  28. public void PopActiveGameObject()
  29. {
  30. m_ObjectStack.Pop();
  31. }
  32. public void AddFromClip(AnimationClip clip)
  33. {
  34. var go = m_ObjectStack.Peek(); // allow it to throw if empty
  35. if (go != null && clip != null) // null game object is allowed for calls to be ignored
  36. AddFromClip(go, clip);
  37. }
  38. public void AddFromClips(IEnumerable<AnimationClip> clips)
  39. {
  40. var go = m_ObjectStack.Peek();
  41. if (go != null)
  42. AddFromClips(go, clips);
  43. }
  44. public void AddFromName<T>(string name) where T : Component
  45. {
  46. var go = m_ObjectStack.Peek(); // allow it to throw if empty
  47. if (go != null) // null game object is allowed for calls to be ignored
  48. AddFromName<T>(go, name);
  49. }
  50. public void AddFromName(string name)
  51. {
  52. var go = m_ObjectStack.Peek(); // allow it to throw if empty
  53. if (go != null) // null game object is allowed for calls to be ignored
  54. AddFromName(go, name);
  55. }
  56. public void AddFromClip(GameObject obj, AnimationClip clip)
  57. {
  58. if (!Application.isPlaying)
  59. AddPropertiesFromClip(obj, clip);
  60. }
  61. public void AddFromClips(GameObject animatorRoot, IEnumerable<AnimationClip> clips)
  62. {
  63. if (Application.isPlaying)
  64. return;
  65. AnimationPreviewUtilities.PreviewFromCurves(animatorRoot, AnimationPreviewUtilities.GetBindings(animatorRoot, clips));
  66. }
  67. public void AddFromName<T>(GameObject obj, string name) where T : Component
  68. {
  69. if (!Application.isPlaying)
  70. AddPropertiesFromName(obj, typeof(T), name);
  71. }
  72. public void AddFromName(GameObject obj, string name)
  73. {
  74. if (!Application.isPlaying)
  75. AddPropertiesFromName(obj, name);
  76. }
  77. public void AddFromName(Component component, string name)
  78. {
  79. if (!Application.isPlaying)
  80. AddPropertyModification(component, name);
  81. }
  82. public void AddFromComponent(GameObject obj, Component component)
  83. {
  84. if (Application.isPlaying)
  85. return;
  86. if (obj == null || component == null)
  87. return;
  88. var serializedObject = new SerializedObject(component);
  89. SerializedProperty property = serializedObject.GetIterator();
  90. while (property.NextVisible(true))
  91. {
  92. if (property.hasVisibleChildren || !AnimatedParameterUtility.IsTypeAnimatable(property.propertyType))
  93. continue;
  94. AddPropertyModification(component, property.propertyPath);
  95. }
  96. }
  97. void AddPropertiesFromClip(GameObject go, AnimationClip clip)
  98. {
  99. if (go != null && clip != null)
  100. {
  101. AnimationMode.InitializePropertyModificationForGameObject(go, clip);
  102. }
  103. }
  104. static void AddPropertiesFromName(GameObject go, string property)
  105. {
  106. if (go == null)
  107. return;
  108. AddPropertyModification(go, property);
  109. }
  110. static void AddPropertiesFromName(GameObject go, Type compType, string property)
  111. {
  112. if (go == null)
  113. return;
  114. var comp = go.GetComponent(compType);
  115. if (comp == null)
  116. return;
  117. AddPropertyModification(comp, property);
  118. }
  119. public void AddObjectProperties(Object obj, AnimationClip clip)
  120. {
  121. if (obj == null || clip == null)
  122. return;
  123. IPlayableAsset asset = obj as IPlayableAsset;
  124. IPlayableBehaviour playable = obj as IPlayableBehaviour;
  125. // special case for assets that contain animated script playables.
  126. // The paths in the clip start from the field with the templated playable
  127. if (asset != null)
  128. {
  129. if (playable == null)
  130. {
  131. AddSerializedPlayableModifications(asset, clip);
  132. }
  133. else
  134. {
  135. // in this case the asset is the playable. The clip applies directly
  136. AnimationMode.InitializePropertyModificationForObject(obj, clip);
  137. }
  138. }
  139. }
  140. void AddSerializedPlayableModifications(IPlayableAsset asset, AnimationClip clip)
  141. {
  142. var obj = asset as Object;
  143. if (obj == null)
  144. return;
  145. var driver = WindowState.previewDriver;
  146. if (driver == null || !AnimationMode.InAnimationMode(driver))
  147. return;
  148. var serializedObj = new SerializedObject(obj);
  149. var bindings = AnimationClipCurveCache.Instance.GetCurveInfo(clip).bindings;
  150. var fields = AnimatedParameterUtility.GetScriptPlayableFields(asset);
  151. // go through each binding and offset using the field name
  152. // so the modification system can find the particle object using the asset as a root
  153. foreach (var b in bindings)
  154. {
  155. foreach (var f in fields)
  156. {
  157. var propertyPath = f.Name + "." + b.propertyName;
  158. if (serializedObj.FindProperty(propertyPath) != null)
  159. {
  160. DrivenPropertyManager.RegisterProperty(driver, obj, propertyPath);
  161. break;
  162. }
  163. }
  164. }
  165. }
  166. private static void AddPropertyModification(GameObject obj, string propertyName)
  167. {
  168. var driver = WindowState.previewDriver;
  169. if (driver == null || !AnimationMode.InAnimationMode(driver))
  170. return;
  171. DrivenPropertyManager.RegisterProperty(driver, obj, propertyName);
  172. }
  173. private static void AddPropertyModification(Component comp, string name)
  174. {
  175. if (comp == null)
  176. return;
  177. var driver = WindowState.previewDriver;
  178. if (driver == null || !AnimationMode.InAnimationMode(driver))
  179. return;
  180. // Register Property will display an error if a property doesn't exist (wanted behaviour)
  181. // However, it also displays an error on Monobehaviour m_Script property, since it can't be driven. (not wanted behaviour)
  182. // case 967026
  183. if (name == "m_Script" && (comp as MonoBehaviour) != null)
  184. return;
  185. DrivenPropertyManager.RegisterProperty(driver, comp, name);
  186. }
  187. }
  188. }