131 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			131 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using System.Linq; | ||
|  | using UnityEngine; | ||
|  | using UnityEngine.Playables; | ||
|  | using UnityEngine.Timeline; | ||
|  | using Object = UnityEngine.Object; | ||
|  | 
 | ||
|  | namespace UnityEditor.Timeline | ||
|  | { | ||
|  |     static class BindingUtility | ||
|  |     { | ||
|  |         public enum BindingAction | ||
|  |         { | ||
|  |             DoNotBind, | ||
|  |             BindDirectly, | ||
|  |             BindToExistingComponent, | ||
|  |             BindToMissingComponent | ||
|  |         } | ||
|  | 
 | ||
|  |         const string k_BindingOperation = "Bind Track"; | ||
|  | 
 | ||
|  |         public static void Bind(PlayableDirector director, TrackAsset bindTo, Object objectToBind) | ||
|  |         { | ||
|  |             if (director == null || bindTo == null || TimelineWindow.instance == null) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             if (director.GetGenericBinding(bindTo) == objectToBind) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             TimelineWindow.instance.state.previewMode = false; // returns all objects to previous state | ||
|  |             TimelineUndo.PushUndo(director, k_BindingOperation); | ||
|  |             director.SetGenericBinding(bindTo, objectToBind); | ||
|  |             TimelineWindow.instance.state.rebuildGraph = true; | ||
|  |         } | ||
|  | 
 | ||
|  |         public static void BindWithEditorValidation(PlayableDirector director, TrackAsset bindTo, Object objectToBind) | ||
|  |         { | ||
|  |             TrackEditor trackEditor = CustomTimelineEditorCache.GetTrackEditor(bindTo); | ||
|  |             Object validatedObject = trackEditor.GetBindingFrom_Safe(objectToBind, bindTo); | ||
|  |             Bind(director, bindTo, validatedObject); | ||
|  |         } | ||
|  | 
 | ||
|  |         public static void BindWithInteractiveEditorValidation(PlayableDirector director, TrackAsset bindTo, Object objectToBind) | ||
|  |         { | ||
|  |             TrackEditor trackEditor = CustomTimelineEditorCache.GetTrackEditor(bindTo); | ||
|  |             if (trackEditor.SupportsBindingAssign()) | ||
|  |                 BindWithEditorValidation(director, bindTo, objectToBind); | ||
|  |             else | ||
|  |             { | ||
|  |                 Type bindingType = TypeUtility.GetTrackBindingAttribute(bindTo.GetType())?.type; | ||
|  |                 BindingAction action = GetBindingAction(bindingType, objectToBind); | ||
|  |                 if (action == BindingAction.BindToMissingComponent) | ||
|  |                     InteractiveBindToMissingComponent(director, bindTo, objectToBind, bindingType); | ||
|  |                 else | ||
|  |                 { | ||
|  |                     var validatedObject = GetBinding(action, objectToBind, bindingType); | ||
|  |                     Bind(director, bindTo, validatedObject); | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public static BindingAction GetBindingAction(Type requiredBindingType, Object objectToBind) | ||
|  |         { | ||
|  |             if (requiredBindingType == null || objectToBind == null) | ||
|  |                 return BindingAction.DoNotBind; | ||
|  | 
 | ||
|  |             // prevent drag and drop of prefab assets | ||
|  |             if (PrefabUtility.IsPartOfPrefabAsset(objectToBind)) | ||
|  |                 return BindingAction.DoNotBind; | ||
|  | 
 | ||
|  |             if (requiredBindingType.IsInstanceOfType(objectToBind)) | ||
|  |                 return BindingAction.BindDirectly; | ||
|  | 
 | ||
|  |             var draggedGameObject = objectToBind as GameObject; | ||
|  | 
 | ||
|  |             if (!typeof(Component).IsAssignableFrom(requiredBindingType) || draggedGameObject == null) | ||
|  |                 return BindingAction.DoNotBind; | ||
|  | 
 | ||
|  |             if (draggedGameObject.GetComponent(requiredBindingType) == null) | ||
|  |                 return BindingAction.BindToMissingComponent; | ||
|  | 
 | ||
|  |             return BindingAction.BindToExistingComponent; | ||
|  |         } | ||
|  | 
 | ||
|  |         public static Object GetBinding(BindingAction bindingAction, Object objectToBind, Type requiredBindingType) | ||
|  |         { | ||
|  |             if (objectToBind == null) return null; | ||
|  | 
 | ||
|  |             switch (bindingAction) | ||
|  |             { | ||
|  |                 case BindingAction.BindDirectly: | ||
|  |                 { | ||
|  |                     return objectToBind; | ||
|  |                 } | ||
|  |                 case BindingAction.BindToExistingComponent: | ||
|  |                 { | ||
|  |                     var gameObjectBeingDragged = objectToBind as GameObject; | ||
|  |                     Debug.Assert(gameObjectBeingDragged != null, "The object being dragged was detected as being a GameObject"); | ||
|  |                     return gameObjectBeingDragged.GetComponent(requiredBindingType); | ||
|  |                 } | ||
|  |                 case BindingAction.BindToMissingComponent: | ||
|  |                 { | ||
|  |                     var gameObjectBeingDragged = objectToBind as GameObject; | ||
|  |                     Debug.Assert(gameObjectBeingDragged != null, "The object being dragged was detected as being a GameObject"); | ||
|  |                     return Undo.AddComponent(gameObjectBeingDragged, requiredBindingType); | ||
|  |                 } | ||
|  |                 default: | ||
|  |                     return null; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         static void InteractiveBindToMissingComponent(PlayableDirector director, TrackAsset bindTo, Object objectToBind, Type requiredComponentType) | ||
|  |         { | ||
|  |             var gameObjectBeingDragged = objectToBind as GameObject; | ||
|  |             Debug.Assert(gameObjectBeingDragged != null, "The object being dragged was detected as being a GameObject"); | ||
|  | 
 | ||
|  |             string typeNameOfComponent = requiredComponentType.ToString().Split(".".ToCharArray()).Last(); | ||
|  |             var bindMenu = new GenericMenu(); | ||
|  |             bindMenu.AddItem( | ||
|  |                 EditorGUIUtility.TextContent("Create " + typeNameOfComponent + " on " + gameObjectBeingDragged.name), | ||
|  |                 false, | ||
|  |                 nullParam => Bind(director, bindTo, Undo.AddComponent(gameObjectBeingDragged, requiredComponentType)), | ||
|  |                 null); | ||
|  | 
 | ||
|  |             bindMenu.AddSeparator(""); | ||
|  |             bindMenu.AddItem(EditorGUIUtility.TrTextContent("Cancel"), false, userData => { }, null); | ||
|  |             bindMenu.ShowAsContext(); | ||
|  |         } | ||
|  |     } | ||
|  | } |