using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; namespace UnityEditor.Timeline { /// /// Description of the on-screen area where a clip is drawn /// public struct ClipBackgroundRegion { /// /// The rectangle where the background of the clip is drawn. /// /// /// The rectangle is clipped to the screen. The rectangle does not include clip borders. /// public Rect position { get; private set; } /// /// The start time of the region, relative to the clip. /// public double startTime { get; private set; } /// /// The end time of the region, relative to the clip. /// public double endTime { get; private set; } /// /// Constructor /// /// /// /// public ClipBackgroundRegion(Rect _position, double _startTime, double _endTime) { position = _position; startTime = _startTime; endTime = _endTime; } public override bool Equals(object obj) { if (!(obj is ClipBackgroundRegion)) return false; return Equals((ClipBackgroundRegion)obj); } public bool Equals(ClipBackgroundRegion other) { return position.Equals(other.position) && startTime == other.startTime && endTime == other.endTime; } public override int GetHashCode() { return HashUtility.CombineHash( position.GetHashCode(), startTime.GetHashCode(), endTime.GetHashCode() ); } public static bool operator==(ClipBackgroundRegion region1, ClipBackgroundRegion region2) { return region1.Equals(region2); } public static bool operator!=(ClipBackgroundRegion region1, ClipBackgroundRegion region2) { return !region1.Equals(region2); } } /// /// The user-defined options for drawing a clip. /// public struct ClipDrawOptions { private IEnumerable m_Icons; /// /// Text that indicates if the clip should display an error. /// /// /// If the error text is not empty or null, then the clip displays a warning. The error text is used as the tooltip. /// public string errorText { get; set; } /// /// The tooltip to show for the clip. /// public string tooltip { get; set; } /// /// The color drawn under the clip. By default, the color is the same as the track color. /// public Color highlightColor { get; set; } /// /// Icons to display on the clip. /// public IEnumerable icons { get { return m_Icons ?? System.Linq.Enumerable.Empty(); } set { m_Icons = value;} } public override bool Equals(object obj) { if (!(obj is ClipDrawOptions)) return false; return Equals((ClipDrawOptions)obj); } public bool Equals(ClipDrawOptions other) { return errorText == other.errorText && tooltip == other.tooltip && highlightColor == other.highlightColor && System.Linq.Enumerable.SequenceEqual(icons, other.icons); } public override int GetHashCode() { return HashUtility.CombineHash( errorText != null ? errorText.GetHashCode() : 0, tooltip != null ? tooltip.GetHashCode() : 0, highlightColor.GetHashCode(), icons != null ? icons.GetHashCode() : 0 ); } public static bool operator==(ClipDrawOptions options1, ClipDrawOptions options2) { return options1.Equals(options2); } public static bool operator!=(ClipDrawOptions options1, ClipDrawOptions options2) { return !options1.Equals(options2); } } /// /// Use this class to customize clip types in the TimelineEditor. /// public class ClipEditor { static readonly string k_NoPlayableAssetError = LocalizationDatabase.GetLocalizedString("This clip does not contain a valid playable asset"); static readonly string k_ScriptLoadError = LocalizationDatabase.GetLocalizedString("The associated script can not be loaded"); internal readonly bool supportsSubTimelines; /// /// Default constructor /// public ClipEditor() { supportsSubTimelines = TypeUtility.HasOverrideMethod(GetType(), nameof(GetSubTimelines)); } /// /// Implement this method to override the default options for drawing a clip. /// /// The clip being drawn. /// The options for drawing a clip. public virtual ClipDrawOptions GetClipOptions(TimelineClip clip) { return new ClipDrawOptions() { errorText = GetErrorText(clip), tooltip = string.Empty, highlightColor = GetDefaultHighlightColor(clip), icons = System.Linq.Enumerable.Empty() }; } /// /// Override this method to draw a background for a clip . /// /// The clip being drawn. /// The on-screen area where the clip is drawn. public virtual void DrawBackground(TimelineClip clip, ClipBackgroundRegion region) { } /// /// Called when a clip is created. /// /// The newly created clip. /// The track that the clip is assigned to. /// The source that the clip was copied from. This can be set to null if the clip is not a copy. /// /// The callback occurs before the clip is assigned to the track. /// public virtual void OnCreate(TimelineClip clip, TrackAsset track, TimelineClip clonedFrom) { } /// /// Gets the error text for the specified clip. /// /// The clip being drawn. /// Returns the error text to be displayed as the tool tip for the clip. If there is no error to be displayed, this method returns string.Empty. public string GetErrorText(TimelineClip clip) { if (clip == null || clip.asset == null) return k_NoPlayableAssetError; var playableAsset = clip.asset as ScriptableObject; if (playableAsset == null || MonoScript.FromScriptableObject(playableAsset) == null) return k_ScriptLoadError; return string.Empty; } /// /// The color drawn under the clip. By default, the color is the same as the track color. /// /// The clip being drawn. /// Returns the highlight color of the clip being drawn. public Color GetDefaultHighlightColor(TimelineClip clip) { if (clip == null) return Color.white; return TrackResourceCache.GetTrackColor(clip.parentTrack); } /// /// Called when a clip is changed by the Editor. /// /// The clip that changed. public virtual void OnClipChanged(TimelineClip clip) { } /// /// Gets the sub-timelines for a specific clip. Implement this method if your clip supports playing nested timelines. /// /// The clip with the ControlPlayableAsset. /// The playable director driving the Timeline Clip. This may not be the same as TimelineEditor.inspectedDirector. /// Specify the sub-timelines to control. public virtual void GetSubTimelines(TimelineClip clip, PlayableDirector director, List subTimelines) { } } }