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); | ||
|  |         } | ||
|  |     } | ||
|  | } |