Search Unity

  1. How can our website serve you better? Give us your feedback. Take our survey and let us know.
    Dismiss Notice

Timeline editor customization

Discussion in 'Timeline' started by Sangemdoko, Jan 10, 2020.

  1. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Hi, I would like to customize the markers and clip styles in the timeline editor for an asset I am making.

    For now I know that I can create new markers with custom styles using the Attribute:
    [CustomStyle("Mystyle")]
    And that allows me to set the Width, Height and background-color properties. Other properties like color, background-color or -unity-background-image-color-tint do not do anything.

    I would like something more flexible where I could dynamically change the marker image/style depending on its state (which could be set in the inspector). For example, the Signal Emitter marker has a special icon when no signals are attached.

    In my setup, I have to create a new Marker class for each state just so that I can have different icons for each. It would be a lot nicer If I could have a single custom marker that changes visual and functionality depending on its state.

    Any advice is welcome.
     
  2. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    158
    You can draw an overlay on top of a marker by using a MarkerEditor:
    Code (CSharp):
    1. public class MyMarker : Marker { }
    2.  
    3. //Make sure to put this class in its own file in an Editor directory, so that it is not included in a build
    4. [CustomTimelineEditor(typeof(MyMarker))]
    5. public class MyMarkerEditor : MarkerEditor
    6. {
    7.     public override void DrawOverlay(IMarker marker, MarkerUIStates uiState, MarkerOverlayRegion region)
    8.     {
    9.         EditorGUI.DrawRect(region.markerRegion, Color.cyan);
    10.     }
    11. }
    Without MyMarkerEditor: upload_2020-1-10_11-5-21.png With MyMarkerEditor: upload_2020-1-10_11-3-53.png

    You can also do the same with clips.
     
  3. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Thank you, That'll help a lot!

    Are there any plans to convert the Timeline editor to UIElements anytime soon? Just curious
     
  4. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    158
    No, there aren't any plans right now to convert the Timeline window to UIElements.
     
  5. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Thanks.

    So I made the change to have a single Marker type with different states.
    But now I have a new problem. When I copy paste some markers they set to the default state instead of keeping the state of the copied marker. By state I mean I have a property field on my marker which I can change in the inspector.

    In my workflow there is a ton of copy-pasting because I use a lot of markers, having to set each marker manually after they are copied would be a deal-breaker.

    Any advice, maybe there's an editor function that I can override for copy-pasting? ... I'll be very sad if I have to change everything back since it took me an entire day to make that change.
     
  6. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Ok so I should have read the documentation better, there's a function to override copy:

    Code (CSharp):
    1.  public override void OnCreate(IMarker marker, IMarker clonedFrom)
    2.         {
    3.             base.OnCreate(marker, clonedFrom);
    4.         }
    But in the end I won't use the state stuff, I was overcomplicated things for nothing...
    Thank you for the help though, I'll still use the MarkerEditor code for better customization
     
  7. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Ok I have a new question.

    When you have two or more markers in the same space, the default marker adds a little "+" icon on top of the marker.

    My overlay hides that little "+" icon. The thing is that I do not know how to get the information that two markers are overlapping so that I can add my own little "+".

    Any tricks you can give me is very appreciated!
     
  8. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    158
    Unfortunately, the overlay is drawn on top of the markers, which includes the little + icon. The best you can do is to check the other markers on the track, and display a + icon if two markers are ''close'' (their time is approximately equal). This is what we do internally.
     
  9. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Thanks! I didn't think of that.
    I'll do the same then
     
  10. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    For some reason the + icon just started appearing without me writing the code for it. I wonder if the script execution order changed. For now it works so great!
    Since I tested the marker editor and got the results I wanted I'm now trying it the clip editor. But I feel like what I'd like to do is simply not possible. I'd like to draw an icon at the start and end position of the clip. The thing is that the icons get cut in half. It seems like I cannot draw outside the clip region...which to be fair makes sense.
    Is there a way to draw outside that region?
    If not, it's not a deal breaker I feel like I can still get the point across. If need be I could always shift the icons inside... but I'd prefer the center to be exactly on start and end.
    Here is how my custom stuff looks like so far, I'll just need to swap out the icons and I'm good to go.
    upload_2020-1-17_17-37-51.png
     
  11. HopeErin

    HopeErin

    Joined:
    Sep 12, 2019
    Posts:
    7
    Hey! I'm trying to do something simpler but similar (just add a red visual highlight to certain clips), could you share how you got this working on the clip?
     
  12. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Sure, you need to create a new PlayableAsset class and create an editor for it. You can look at the documentation for more detail.
    https://docs.unity3d.com/Packages/com.unity.timeline@1.2/api/UnityEditor.Timeline.ClipEditor.html
    In case in can help you, here is my editor code for the editor clip above:


    Code (CSharp):
    1. [CustomTimelineEditor(typeof(BeatClipAsset))]
    2.     public class BeatAssetClipEditor : ClipEditor
    3.     {
    4.         public override void OnCreate(TimelineClip clip, TrackAsset track, TimelineClip clonedFrom)
    5.         {
    6.             base.OnCreate(clip, track, clonedFrom);
    7.  
    8.             var otherAsset = clonedFrom?.asset;
    9.  
    10.             (clip.asset as BeatClipAsset).Copy(otherAsset);
    11.         }
    12.  
    13.         public override void OnClipChanged(TimelineClip clip)
    14.         {
    15.             base.OnClipChanged(clip);
    16.         }
    17.  
    18.         public override void DrawBackground(TimelineClip clip, ClipBackgroundRegion region)
    19.         {
    20.             base.DrawBackground(clip, region);
    21.            
    22.             var beatAsset = clip.asset as BeatClipAsset;
    23.             var iconSize = new Vector2(18,18);
    24.            
    25.             var startRegion = new Rect(
    26.                 region.position.position.x-iconSize.x/2,
    27.                 region.position.position.y,
    28.                 iconSize.x,
    29.                 iconSize.y);
    30.             var endRegion = new Rect(
    31.                 region.position.position.x+region.position.width-iconSize.x/2,
    32.                 region.position.position.y,
    33.                 iconSize.x,
    34.                 iconSize.y);
    35.             var backgroundRegion = new Rect(
    36.                 region.position.position.x,
    37.                 region.position.position.y+iconSize.y/4,
    38.                 region.position.width,
    39.                 iconSize.y/2);
    40.  
    41.             var startTexture = (Texture)AssetDatabase.LoadAssetAtPath (beatAsset.EditorStartIconPath, typeof(Texture));
    42.             if (startTexture == null) {
    43.                 startTexture = (Texture) AssetDatabase.LoadAssetAtPath(BeatUtility.s_OnBeatIconPath, typeof(Texture));
    44.             }
    45.            
    46.             var endTexture = (Texture)AssetDatabase.LoadAssetAtPath (beatAsset.EditorEndIconPath, typeof(Texture));
    47.             if (endTexture == null) {
    48.                 endTexture = (Texture) AssetDatabase.LoadAssetAtPath(BeatUtility.s_OnBeatIconPath, typeof(Texture));
    49.             }
    50.  
    51.             var color = beatAsset.EditorColorPath;
    52.  
    53.             EditorGUI.DrawRect(backgroundRegion, color);
    54.            
    55.             Color previousGuiColor = GUI.color;
    56.             GUI.color = Color.clear;
    57.  
    58.             EditorGUI.DrawTextureTransparent(startRegion, startTexture);
    59.             EditorGUI.DrawTextureTransparent(endRegion, endTexture);
    60.            
    61.             GUI.color = previousGuiColor;
    62.            
    63.         }
    64.     }
    Best of luck
     
    io-games and HopeErin like this.
  13. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    So after almost a year I'm back on this project.

    I have one issue with the clip custom editor. When I move the timeline cursor the clips are trimmed as they go off view. The issue is that my code depends on the clip background region to draw the icons on the sides. So as I move the timeline along the icons move along the clip instead of staying at the start, center and end of the clip.
    @julienb I was wondering if you had any hidden trick I could use. I know it should be possible since the text/name of the clip stays in the center always. I can't seem to find the source code for this though.

    I attached below a gif showing the issue.

    Bug_Editor_Clip_Icon_19_02_2021.gif

    PS: Also is there a way to hide the clip name? It kinds of hide the icons

    Thank you for your time
     
  14. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    158
    I took a good look at our code and unfortunately, I did not find a way to achieve what you want with the current API. Internally, we have the information about the complete clip rect (so we can position the label at the center) but this is not provided in the public API.

    Regarding the clip name, you cannot hide it (unless you clear the name of the clip itself, which is kind of ugly I'll agree).

    I'll add those two things (non-clipped rect + hide display name) to our list of feature requests.
     
  15. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    139
    Thank you, that's really appreciated.

    When the clip name is empty it writes "(Empty)" on the clip. So for now as a workaround I automatically set the name to "." which is the character that is the least noticeable.
     
  16. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    489
    Sangemdoko likes this.
  17. SpiderJones

    SpiderJones

    Joined:
    Mar 29, 2014
    Posts:
    188
    Hi, I'm following this -> https://docs.unity.cn/Packages/com.unity.timeline@1.5/manual/smpl_custom_annotation.html

    There seems to be some issues with the example code.


    This ->

    Code (CSharp):
    1. const float k_LineOverlayWidth = 6.0f;
    2. float markerRegionCenter = markerRegion.xMin + (markerRegion.width - k_LineOverlayWidth) / 2.0f;
    3. Rect lineRect = new Rect(markerRegionCenter,
    4.     timelineRegion.y,
    5.     k_LineOverlayWidth,
    6.     timelineRegion.height);
    7.  

    should be this ->

    Code (CSharp):
    1. const float k_LineOverlayWidth = 6.0f;
    2.                 float markerRegionCenter = region.markerRegion.xMin + (region.markerRegion.width - k_LineOverlayWidth) / 2.0f;
    3.                 Rect lineRect = new Rect(markerRegionCenter,
    4.                     region.timelineRegion.y,
    5.                     k_LineOverlayWidth,
    6.                     region.timelineRegion.height);

    And I assume that code needs to go into the "DrawOverlay" method.

    Code (CSharp):
    1. public override void DrawOverlay(IMarker marker, MarkerUIStates uiState, MarkerOverlayRegion region)
    2. {
    3.     var annotation = marker as AnnotationMarker;
    4.     if (annotation != null)
    5.     {
    6.         //Draw overlay code...
    7.     }
    8. }

    But the code still seems incomplete. How do I draw the "lineRect"?

    Thanks!
     
  18. SpiderJones

    SpiderJones

    Joined:
    Mar 29, 2014
    Posts:
    188
    never mind. thanks to this post I figured it out.

    Need to add this ->
    EditorGUI.DrawRect(lineRect, annotation.color);

    Code (CSharp):
    1. public override void DrawOverlay(IMarker marker, MarkerUIStates uiState, MarkerOverlayRegion region)
    2.         {
    3.             var annotation = marker as TimelineAnnotationMarker;
    4.             if (annotation != null)
    5.             {
    6.                 const float k_LineOverlayWidth = 1.0f;
    7.                 float markerRegionCenter = region.markerRegion.xMin + (region.markerRegion.width - k_LineOverlayWidth) / 2.0f;
    8.                 Rect lineRect = new Rect(markerRegionCenter,
    9.                     region.timelineRegion.y,
    10.                     k_LineOverlayWidth,
    11.                     region.timelineRegion.height);
    12.                 EditorGUI.DrawRect(lineRect, annotation.color);
    13.             }
    14.            
    15.             base.DrawOverlay(marker, uiState, region);
    16.         }
     
  19. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    489
    You can also directly embed the sample in your project folder from the Package Manager
    upload_2021-6-17_15-37-8.png

    The full code is available there
     
    SpiderJones likes this.
unityunity