227 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using UnityEngine;
 | |
| using UnityEngine.Playables;
 | |
| using UnityEngine.Timeline;
 | |
| using Object = UnityEngine.Object;
 | |
| 
 | |
| namespace UnityEditor.Timeline
 | |
| {
 | |
|     class PropertyCollector : IPropertyCollector
 | |
|     {
 | |
|         readonly Stack<GameObject> m_ObjectStack = new Stack<GameObject>();
 | |
| 
 | |
|         // Call immediately before use
 | |
|         public void Reset()
 | |
|         {
 | |
|             m_ObjectStack.Clear();
 | |
|         }
 | |
| 
 | |
|         // call to reset caches. should be called when switching master timelines
 | |
|         public void Clear()
 | |
|         {
 | |
|             m_ObjectStack.Clear();
 | |
|             AnimationPreviewUtilities.ClearCaches();
 | |
|         }
 | |
| 
 | |
|         public void PushActiveGameObject(GameObject gameObject)
 | |
|         {
 | |
|             m_ObjectStack.Push(gameObject);
 | |
|         }
 | |
| 
 | |
|         public void PopActiveGameObject()
 | |
|         {
 | |
|             m_ObjectStack.Pop();
 | |
|         }
 | |
| 
 | |
|         public void AddFromClip(AnimationClip clip)
 | |
|         {
 | |
|             var go = m_ObjectStack.Peek(); // allow it to throw if empty
 | |
|             if (go != null && clip != null) // null game object is allowed for calls to be ignored
 | |
|                 AddFromClip(go, clip);
 | |
|         }
 | |
| 
 | |
|         public void AddFromClips(IEnumerable<AnimationClip> clips)
 | |
|         {
 | |
|             var go = m_ObjectStack.Peek();
 | |
|             if (go != null)
 | |
|                 AddFromClips(go, clips);
 | |
|         }
 | |
| 
 | |
|         public void AddFromName<T>(string name) where T : Component
 | |
|         {
 | |
|             var go = m_ObjectStack.Peek(); // allow it to throw if empty
 | |
|             if (go != null) // null game object is allowed for calls to be ignored
 | |
|                 AddFromName<T>(go, name);
 | |
|         }
 | |
| 
 | |
|         public void AddFromName(string name)
 | |
|         {
 | |
|             var go = m_ObjectStack.Peek(); // allow it to throw if empty
 | |
|             if (go != null) // null game object is allowed for calls to be ignored
 | |
|                 AddFromName(go, name);
 | |
|         }
 | |
| 
 | |
|         public void AddFromClip(GameObject obj, AnimationClip clip)
 | |
|         {
 | |
|             if (!Application.isPlaying)
 | |
|                 AddPropertiesFromClip(obj, clip);
 | |
|         }
 | |
| 
 | |
|         public void AddFromClips(GameObject animatorRoot, IEnumerable<AnimationClip> clips)
 | |
|         {
 | |
|             if (Application.isPlaying)
 | |
|                 return;
 | |
| 
 | |
|             AnimationPreviewUtilities.PreviewFromCurves(animatorRoot, AnimationPreviewUtilities.GetBindings(animatorRoot, clips));
 | |
|         }
 | |
| 
 | |
|         public void AddFromName<T>(GameObject obj, string name) where T : Component
 | |
|         {
 | |
|             if (!Application.isPlaying)
 | |
|                 AddPropertiesFromName(obj, typeof(T), name);
 | |
|         }
 | |
| 
 | |
|         public void AddFromName(GameObject obj, string name)
 | |
|         {
 | |
|             if (!Application.isPlaying)
 | |
|                 AddPropertiesFromName(obj, name);
 | |
|         }
 | |
| 
 | |
|         public void AddFromName(Component component, string name)
 | |
|         {
 | |
|             if (!Application.isPlaying)
 | |
|                 AddPropertyModification(component, name);
 | |
|         }
 | |
| 
 | |
|         public void AddFromComponent(GameObject obj, Component component)
 | |
|         {
 | |
|             if (Application.isPlaying)
 | |
|                 return;
 | |
| 
 | |
|             if (obj == null || component == null)
 | |
|                 return;
 | |
| 
 | |
|             var serializedObject = new SerializedObject(component);
 | |
|             SerializedProperty property = serializedObject.GetIterator();
 | |
| 
 | |
|             while (property.NextVisible(true))
 | |
|             {
 | |
|                 if (property.hasVisibleChildren || !AnimatedParameterUtility.IsTypeAnimatable(property.propertyType))
 | |
|                     continue;
 | |
| 
 | |
|                 AddPropertyModification(component, property.propertyPath);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void AddPropertiesFromClip(GameObject go, AnimationClip clip)
 | |
|         {
 | |
|             if (go != null && clip != null)
 | |
|             {
 | |
|                 AnimationMode.InitializePropertyModificationForGameObject(go, clip);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         static void AddPropertiesFromName(GameObject go, string property)
 | |
|         {
 | |
|             if (go == null)
 | |
|                 return;
 | |
| 
 | |
|             AddPropertyModification(go, property);
 | |
|         }
 | |
| 
 | |
|         static void AddPropertiesFromName(GameObject go, Type compType, string property)
 | |
|         {
 | |
|             if (go == null)
 | |
|                 return;
 | |
|             var comp = go.GetComponent(compType);
 | |
|             if (comp == null)
 | |
|                 return;
 | |
| 
 | |
|             AddPropertyModification(comp, property);
 | |
|         }
 | |
| 
 | |
|         public void AddObjectProperties(Object obj, AnimationClip clip)
 | |
|         {
 | |
|             if (obj == null || clip == null)
 | |
|                 return;
 | |
| 
 | |
|             IPlayableAsset asset = obj as IPlayableAsset;
 | |
|             IPlayableBehaviour playable = obj as IPlayableBehaviour;
 | |
| 
 | |
|             // special case for assets that contain animated script playables.
 | |
|             // The paths in the clip start from the field with the templated playable
 | |
|             if (asset != null)
 | |
|             {
 | |
|                 if (playable == null)
 | |
|                 {
 | |
|                     AddSerializedPlayableModifications(asset, clip);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     // in this case the asset is the playable. The clip applies directly
 | |
|                     AnimationMode.InitializePropertyModificationForObject(obj, clip);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void AddSerializedPlayableModifications(IPlayableAsset asset, AnimationClip clip)
 | |
|         {
 | |
|             var obj = asset as Object;
 | |
|             if (obj == null)
 | |
|                 return;
 | |
| 
 | |
|             var driver = WindowState.previewDriver;
 | |
|             if (driver == null || !AnimationMode.InAnimationMode(driver))
 | |
|                 return;
 | |
| 
 | |
|             var serializedObj = new SerializedObject(obj);
 | |
|             var bindings = AnimationClipCurveCache.Instance.GetCurveInfo(clip).bindings;
 | |
|             var fields = AnimatedParameterUtility.GetScriptPlayableFields(asset);
 | |
| 
 | |
|             // go through each binding and offset using the field name
 | |
|             //  so the modification system can find the particle object using the asset as a root
 | |
|             foreach (var b in bindings)
 | |
|             {
 | |
|                 foreach (var f in fields)
 | |
|                 {
 | |
|                     var propertyPath = f.Name + "." + b.propertyName;
 | |
|                     if (serializedObj.FindProperty(propertyPath) != null)
 | |
|                     {
 | |
|                         DrivenPropertyManager.RegisterProperty(driver, obj, propertyPath);
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static void AddPropertyModification(GameObject obj, string propertyName)
 | |
|         {
 | |
|             var driver = WindowState.previewDriver;
 | |
|             if (driver == null || !AnimationMode.InAnimationMode(driver))
 | |
|                 return;
 | |
| 
 | |
|             DrivenPropertyManager.RegisterProperty(driver, obj, propertyName);
 | |
|         }
 | |
| 
 | |
|         private static void AddPropertyModification(Component comp, string name)
 | |
|         {
 | |
|             if (comp == null)
 | |
|                 return;
 | |
| 
 | |
|             var driver = WindowState.previewDriver;
 | |
|             if (driver == null || !AnimationMode.InAnimationMode(driver))
 | |
|                 return;
 | |
| 
 | |
|             // Register Property will display an error if a property doesn't exist (wanted behaviour)
 | |
|             // However, it also displays an error on Monobehaviour m_Script property, since it can't be driven. (not wanted behaviour)
 | |
|             // case 967026
 | |
|             if (name == "m_Script" && (comp as MonoBehaviour) != null)
 | |
|                 return;
 | |
| 
 | |
|             DrivenPropertyManager.RegisterProperty(driver, comp, name);
 | |
|         }
 | |
|     }
 | |
| }
 |