You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
5.4 KiB
130 lines
5.4 KiB
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(); |
|
} |
|
} |
|
}
|
|
|