Search Unity

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:
    206
    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:
    177
    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:
    206
    @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:
    45
    @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:
    45
    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:
    45
    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()