Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How can I resolve an ExposedReference from within a Marker?

Discussion in 'Timeline' started by Jamez0r, Jan 22, 2021.

  1. Jamez0r

    Jamez0r

    Joined:
    Jul 29, 2019
    Posts:
    199
    Hello, I'm trying to figure out how to resolve an ExposedReference from within a Marker.

    I've seen in several places how to do it for a PlayableAsset (a clip?):

    Code (CSharp):
    1. public ExposedReference<Transform> exposedTransform;
    2.      
    3.         public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    4.         {
    5.             var playable = ScriptPlayable<AddBloodBehaviour>.Create(graph);
    6.             actualTransform = exposedTransform.Resolve(graph.GetResolver());
    7.             return playable;
    8.         }
    How could I resolve this exposedTransform if I was using a Marker? I don't know how to access the 'graph' from the Marker itself. I see that it has "parent" which is the TrackAsset, and the "timelineAsset" from there, but I'm not sure if there is a way to get to the "graph" from there so I can use graph.GetResolver().

    And just to clarify, I know how to set up the INotificationReceiver and resolve the ExposedReference on that. I just don't know how to do it on the Marker itself.

    My end goal is to be able to add an ExposedReference<MySpecialComponent> to a Marker, and then also display the inspector for MySpecialComponent so that I can modify it while I have the Marker selected. Is this possible?

    Thanks for any help!
     
  2. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    174
    To resolve an exposed reference from an Editor (inspector) class, you can cast the Selection's active context as a PlayableDirector. When a Timeline clip/marker is selected, Timeline automatically puts the PlayableDirector as a context object. This will let you resolve the exposed reference in your Marker object.

    Code (CSharp):
    1. public class TestMarker : Marker
    2. {
    3.     public ExposedReference<Light> light;
    4. }
    5.  
    6. [CustomEditor(typeof(TestMarker))]
    7. public class TestMarkerInspector : Editor
    8. {
    9.     public override void OnInspectorGUI()
    10.     {
    11.         base.OnInspectorGUI();
    12.  
    13.         //when a Timeline clip/marker is selected, the director is added as a context object
    14.         var directorContext = Selection.activeContext as PlayableDirector;
    15.         var inspectedMarker = target as TestMarker;
    16.  
    17.         if (directorContext != null && inspectedMarker != null)
    18.         {
    19.             PropertyName referenceExposedName = inspectedMarker.light.exposedName;
    20.             Light lightReference = directorContext.GetReferenceValue(referenceExposedName, out bool isValid) as Light;
    21.  
    22.             if (isValid && lightReference != null)
    23.             {
    24.                 Editor inspector = CreateEditor(lightReference);
    25.                 inspector.OnInspectorGUI();
    26.             }
    27.         }
    28.     }
    29. }
    Now I can display the Light's inspector embedded in the custom Marker inspector: upload_2021-1-25_10-26-26.png
     
    Yuchen_Chang and dimmduh1 like this.
  3. Jamez0r

    Jamez0r

    Joined:
    Jul 29, 2019
    Posts:
    199
    @julienb Thank you, this worked perfectly. This was the last thing I needed to figure out for my Timeline implementation (knock on wood), so I seriously appreciate the explanation and the example!
     
    julienb likes this.
  4. fxlange

    fxlange

    Joined:
    Dec 20, 2016
    Posts:
    41
    @julienb I tried your suggestion in 2021.1 and 2021.2 but my
    Selection.activeContex
    is always null. I'm currently trying this for a custom inspector for a timeline clip (not a marker as in your example) but you mentioned that it would work for clips (
    ITimelineClipAsset
    ) as well, right?

    Is this documented somewhere or do you know a different way to resolve exposed references? My current workaround is to set properties during CreatePlayable where I have access to the graph but this happens after
    ClipEditor::OnClipChanged
    and it's not very stable.

    I'm trying to set the duration of a clip based on an exposed reference.

    @Jamez0r Is this approach still working for you?
     
    Last edited: Nov 15, 2021
  5. fxlange

    fxlange

    Joined:
    Dec 20, 2016
    Posts:
    41
    I just tried it with a CustomMarker and it works. Just can't get it working for clips :/
     
  6. fxlange

    fxlange

    Joined:
    Dec 20, 2016
    Posts:
    41
    Okay, finally found it.
    UnityEditor.Timeline.TimelineEditor.inspectedDirector


    Class TimelineEditor | Timeline | 1.6.3 (unity3d.com)

    From there you can get the graph and resolver via
    TimelineEditor.inspectedDirector.playableGraph.GetResolver()
    .

    Took me two days to find but now that I know it exists it all makes sense :)
     
    Jamez0r likes this.
  7. amatiasq

    amatiasq

    Joined:
    Jun 8, 2017
    Posts:
    3
    Correct me if I'm wrong but isn't this true?

    Code (CSharp):
    1. TimelineEditor.inspectedDirector == TimelineEditor.inspectedDirector.playableGraph.GetResolver()