// Called by the Timeline editor to draw the background of a TweenClip. public override void DrawBackground(TimelineClip clip, ClipBackgroundRegion region) { TweenClip asset = clip.asset as TweenClip; if (asset == null) { return; } PlayableDirector director = TimelineEditor.inspectedDirector; if (director == null) { return; } Transform startLocation = director.GetReferenceValue(asset.startLocation.exposedName, out bool startFound) as Transform; Transform endLocation = director.GetReferenceValue(asset.endLocation.exposedName, out bool endFound) as Transform; if (startFound && startLocation != null) { EditorGUI.LabelField(region.position, startLocation.gameObject.name, s_StartTextStyle); } if (endFound && endLocation != null) { EditorGUI.LabelField(region.position, endLocation.gameObject.name, s_EndTextStyle); } }
private void Start() { mixers = new List <AnimationLayerMixerPlayable>(); for (var i = 0; i < dir.playableGraph.GetOutputCount(); i++) { var p = dir.playableGraph.GetRootPlayable(i); if (!p.IsValid()) { continue; } Debug.Log(p.GetPlayableType()); Debug.Log("OUTPUT: " + i + " = " + p.GetPlayableType() + ", outputs: " + p.GetOutputCount() + ", inputs: " + p.GetInputCount()); Traverse(p, mixers); } var arr = dir.playableAsset.outputs.ToArray(); for (var i = 0; i < arr.Length; i++) { var entry = arr[i]; if (entry.outputTargetType == typeof(Animator)) { var binding = dir.GetGenericBinding(entry.sourceObject); var b2 = dir.GetReferenceValue(new PropertyName(entry.streamName), out var valid); Debug.Log("BINDING: " + i + ", " + binding + ", " + b2 + " valid=" + valid + " " + entry.streamName + " - " + entry.sourceObject + ", " + binding); boundAnimators.Add(binding as Animator); } else { var binding = dir.GetGenericBinding(entry.sourceObject); var b2 = dir.GetReferenceValue(new PropertyName(entry.streamName), out var valid); Debug.Log("BINDING: " + i + " is " + entry.outputTargetType + " for " + b2 + ", " + entry.streamName + ", " + binding); } } if (InjectOnStart) { InjectMixers(); } Debug.Log("-----------"); if (TimelineUtilities.TryFindTimelinePlayable(dir.playableGraph, out var timeline)) { Debug.Log(timeline.GetPlayableType() + ", " + timeline.GetType()); if (TimelineUtilities.TryInjectMixer(dir, timeline, GetComponent <Animator>(), out var mixer)) { Debug.Log("INJECTED MIXER" + mixer); } } }
static ScriptableObject CloneReferencedPlayableAsset(ScriptableObject original, PlayableDirector directorInstance) { var clone = Object.Instantiate(original); TimelineUndo.RegisterCreatedObjectUndo(clone, "Create clip"); if (clone == null || (clone as IPlayableAsset) == null) { throw new InvalidCastException("could not cast instantiated object into IPlayableAsset"); } if (directorInstance != null) { // Use serialize object to make a copy var originalObject = new SerializedObject(original); var cloneObject = new SerializedObject(clone); SerializedProperty prop = originalObject.GetIterator(); if (prop.Next(true)) { do { cloneObject.CopyFromSerializedProperty(prop); } while (prop.Next(false)); } cloneObject.ApplyModifiedProperties(); EditorUtility.SetDirty(directorInstance); // The exposedName of exposed properties needs to be cleared otherwise the clone will act as an instance var exposedRefs = clone.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(f => f.FieldType.IsGenericType && f.FieldType.GetGenericTypeDefinition() == typeof(ExposedReference <>)).ToList(); foreach (FieldInfo fi in exposedRefs) { var exposedRefInstance = fi.GetValue(clone); var exposedNameProperty = exposedRefInstance.GetType().GetField("exposedName"); if (exposedNameProperty != null) { var exposedNameValue = (PropertyName)exposedNameProperty.GetValue(exposedRefInstance); bool isValid = false; var originalReference = directorInstance.GetReferenceValue(exposedNameValue, out isValid); if (isValid) { // generate new reference in directorInstance var newPropertyName = new PropertyName(GUID.Generate().ToString()); directorInstance.SetReferenceValue(newPropertyName, originalReference); exposedNameProperty.SetValue(exposedRefInstance, newPropertyName); if (!EditorApplication.isPlaying) { EditorSceneManager.MarkSceneDirty(directorInstance.gameObject.scene); } } } fi.SetValue(clone, exposedRefInstance); } } return(clone); }
private static ScriptableObject CloneReferencedPlayableAsset(ScriptableObject original, PlayableDirector directorInstance) { ScriptableObject scriptableObject = Object.Instantiate <ScriptableObject>(original); if (scriptableObject == null || !(scriptableObject is IPlayableAsset)) { throw new InvalidCastException("could not cast instantiated object into IPlayableAsset"); } if (directorInstance != null) { SerializedObject serializedObject = new SerializedObject(original); SerializedObject serializedObject2 = new SerializedObject(scriptableObject); SerializedProperty iterator = serializedObject.GetIterator(); if (iterator.Next(true)) { do { serializedObject2.CopyFromSerializedProperty(iterator); }while (iterator.Next(false)); } serializedObject2.ApplyModifiedProperties(); EditorUtility.SetDirty(directorInstance); } if (directorInstance != null) { List <FieldInfo> list = (from f in scriptableObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where f.FieldType.IsGenericType && f.FieldType.GetGenericTypeDefinition() == typeof(ExposedReference) select f).ToList <FieldInfo>(); foreach (FieldInfo current in list) { object value = current.GetValue(scriptableObject); FieldInfo field = value.GetType().GetField("exposedName"); if (field != null) { PropertyName propertyName = (PropertyName)field.GetValue(value); bool flag = false; Object referenceValue = directorInstance.GetReferenceValue(propertyName, ref flag); if (flag) { PropertyName propertyName2 = new PropertyName(GUID.Generate().ToString()); directorInstance.SetReferenceValue(propertyName2, referenceValue); field.SetValue(value, propertyName2); } } current.SetValue(scriptableObject, value); } } IEnumerable <FieldInfo> enumerable = from f in scriptableObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where !f.IsNotSerialized && f.FieldType == typeof(AnimationClip) select f; foreach (FieldInfo current2 in enumerable) { current2.SetValue(scriptableObject, TimelineHelpers.CloneAnimationClipIfRequired(current2.GetValue(scriptableObject) as AnimationClip, original)); } return(scriptableObject); }
public void BindTimelineGlobal(PlayableDirector director) { foreach (var output in director.playableAsset.outputs) { if (!output.sourceObject || director.GetGenericBinding(output.sourceObject)) { continue; } GameObject go = PlayableManager.I.GetBindTarget(output.streamName); if (!go) { continue; } if (output.outputTargetType.Equals(typeof(GameObject))) { director.SetGenericBinding(output.sourceObject, go); } else { var bind = go.GetComponent(output.outputTargetType); director.SetGenericBinding(output.sourceObject, bind); } if (!(output.sourceObject is CinemachineTrack)) { continue; } var cinemachineTrack = output.sourceObject as CinemachineTrack; bool b; foreach (var clip in cinemachineTrack.GetClips()) { var cinemachineShot = clip.asset as CinemachineShot; if (director.GetReferenceValue(cinemachineShot.VirtualCamera.exposedName, out b)) { continue; } GameObject go2 = PlayableManager.I.GetBindTarget(clip.displayName); if (!go2) { continue; } var vc = go2.GetComponent <Cinemachine.CinemachineVirtualCameraBase>(); director.SetReferenceValue(cinemachineShot.VirtualCamera.exposedName, vc); } } }
public static void DupTimeline() { // Fetch playable director, fetch timeline GameObject playableDirectorObj = UnityEditor.Selection.activeObject as GameObject; PlayableDirector playableDirector = playableDirectorObj.GetComponent <PlayableDirector>(); TimelineAsset timelineAsset = playableDirector.playableAsset as TimelineAsset; // Duplicate string path = AssetDatabase.GetAssetPath(timelineAsset); string newPath = path.Replace(".", "(Clone)."); if (!AssetDatabase.CopyAsset(path, newPath)) { if (showLogs) { Debug.LogError("Couldn't Clone Asset"); } return; } // Copy Bindings TimelineAsset newTimelineAsset = AssetDatabase.LoadMainAssetAtPath(newPath) as TimelineAsset; PlayableBinding[] oldBindings = timelineAsset.outputs.ToArray(); PlayableBinding[] newBindings = newTimelineAsset.outputs.ToArray(); for (int i = 0; i < oldBindings.Length; i++) { playableDirector.playableAsset = timelineAsset; Object boundTo = playableDirector.GetGenericBinding(oldBindings[i].sourceObject); playableDirector.playableAsset = newTimelineAsset; playableDirector.SetGenericBinding(newBindings[i].sourceObject, boundTo); } // Copy Exposed References playableDirector.playableAsset = newTimelineAsset; foreach (TrackAsset newTrackAsset in newTimelineAsset.GetRootTracks()) { foreach (TimelineClip newClip in newTrackAsset.GetClips()) { foreach (FieldInfo fieldInfo in newClip.asset.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { if (fieldInfo.FieldType.IsGenericType && fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(ExposedReference <>)) { // Fetch Old Exposed Name object exposedReference = fieldInfo.GetValue(newClip.asset); PropertyName oldExposedName = (PropertyName)fieldInfo.FieldType .GetField("exposedName") .GetValue(exposedReference); bool isValid; // Fetch Old Exposed Value Object oldExposedValue = playableDirector.GetReferenceValue(oldExposedName, out isValid); if (!isValid) { if (showLogs) { Debug.LogError("Failed to copy exposed references to duplicate timeline. Could not find: " + oldExposedName); } return; } // Replace exposedName on struct PropertyName newExposedName = new PropertyName(UnityEditor.GUID.Generate().ToString()); fieldInfo.FieldType .GetField("exposedName") .SetValue(exposedReference, newExposedName); // Set ExposedReference fieldInfo.SetValue(newClip.asset, exposedReference); // Set Reference on Playable Director playableDirector.SetReferenceValue(newExposedName, oldExposedValue); } } } } }