static bool IsValidClip(TimelineClip clip, PlayableDirector director)
 {
     return(clip != null &&
            clip.GetParentTrack() != null &&
            (clip.asset as AnimationPlayableAsset) != null &&
            clip.GetParentTrack().clips.Any(x => x.start > clip.start) &&
            TimelineUtility.GetSceneGameObject(director, clip.GetParentTrack()) != null);
 }
Ejemplo n.º 2
0
 public void AddClip(TimelineClip clip, bool includeAsset)
 {
     if (clip != null && clip.GetParentTrack() != null)
     {
         s_ObjectsToUndo.Add(clip.GetParentTrack());
     }
     if (includeAsset && clip != null && clip.asset != null)
     {
         s_ObjectsToUndo.Add(clip.asset);
     }
 }
Ejemplo n.º 3
0
        public IEnumerator CreatePlayableAsset()
        {
            PlayableDirector director = EditorUtilityTest.NewSceneWithDirector();
            TimelineClip     clip     = EditorUtilityTest.CreateTestSISTimelineClip(director);
            StreamingImageSequencePlayableAsset sisAsset = clip.asset as StreamingImageSequencePlayableAsset;

            Assert.IsNotNull(sisAsset);

            //Test the track immediately
            StreamingImageSequenceTrack track = clip.GetParentTrack() as StreamingImageSequenceTrack;

            Assert.IsNotNull(track);
            Assert.IsNotNull(track.GetActivePlayableAsset());

            yield return(null);

            int numImages = sisAsset.GetNumImages();

            Assert.IsTrue(numImages > 0);



            //Test that there should be no active PlayableAsset at the time above what exists in the track.
            director.time = clip.start + clip.duration + 1;
            yield return(null);

            Assert.IsNull(track.GetActivePlayableAsset());


            EditorUtilityTest.DestroyTestTimelineAssets(clip);
            yield return(null);
        }
Ejemplo n.º 4
0
        static TimelineClip DuplicateClip(TimelineClip clip, IExposedPropertyTable sourceTable, IExposedPropertyTable destTable, PlayableAsset newOwner)
        {
            var newClip = Clone(clip, sourceTable, destTable, newOwner);

            var track = clip.GetParentTrack();

            if (track != null)
            {
                newClip.SetParentTrack_Internal(track);
                track.AddClip(newClip);
            }

            var editor = CustomTimelineEditorCache.GetClipEditor(clip);

            try
            {
                editor.OnCreate(newClip, track, clip);
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }

            return(newClip);
        }
Ejemplo n.º 5
0
        public IEnumerator ShowFrameMarkers()
        {
            PlayableDirector director = EditorUtilityTest.NewSceneWithDirector();
            TimelineClip     clip     = EditorUtilityTest.CreateTestSISTimelineClip(director);
            StreamingImageSequencePlayableAsset sisAsset = clip.asset as StreamingImageSequencePlayableAsset;

            Assert.IsNotNull(sisAsset);
            yield return(null);

            //Show
            SISClipData clipData = sisAsset.GetBoundClipData();

            TrackAsset trackAsset = clip.GetParentTrack();

            clipData.RequestFrameMarkers(true, true);
            TimelineEditor.Refresh(RefreshReason.ContentsModified);
            yield return(null);

            Assert.AreEqual(TimelineUtility.CalculateNumFrames(clip), trackAsset.GetMarkerCount());
            yield return(null);


            //Undo showing FrameMarkers
            EditorUtilityTest.UndoAndRefreshTimelineEditor(); yield return(null);

            Assert.False(clipData.AreFrameMarkersRequested());
            Assert.AreEqual(0, trackAsset.GetMarkerCount());


            EditorUtilityTest.DestroyTestTimelineAssets(clip);
            yield return(null);
        }
                public void ClampMasterClipToChildClips(TimelineClip masterClip)
                {
                    if (masterClip != null)
                    {
                        double startTime = double.MaxValue;
                        double endTime   = double.MinValue;
                        bool   hasClips  = false;

                        foreach (TrackAsset child in masterClip.GetParentTrack().GetChildTracks())
                        {
                            foreach (TimelineClip clip in child.GetClips())
                            {
                                double clipStart    = clip.hasPreExtrapolation ? clip.extrapolatedStart : clip.start;
                                double clipDuration = clip.hasPreExtrapolation || clip.hasPostExtrapolation ? clip.extrapolatedDuration : clip.duration;

                                startTime = Math.Min(startTime, clipStart);
                                endTime   = Math.Max(endTime, clipStart + clipDuration);
                                hasClips  = true;
                            }
                        }

                        if (hasClips)
                        {
                            masterClip.start    = startTime;
                            masterClip.duration = endTime - startTime;
                        }
                    }
                }
Ejemplo n.º 7
0
//----------------------------------------------------------------------------------------------------------------------
    public override void ProcessFrame(Playable playable, FrameData info, object playerData) {
        
        base.ProcessFrame(playable, info, playerData); // Calls ProcessActiveClipV()

#if UNITY_EDITOR            
        if (!Application.isPlaying) {
            return;
        }
#endif            
        
        //Preload images here only in play mode
        double directorTime = GetPlayableDirector().time;
        
        IEnumerable<KeyValuePair<TimelineClip, StreamingImageSequencePlayableAsset>> clipAssets = GetClipAssets();
        foreach (KeyValuePair<TimelineClip, StreamingImageSequencePlayableAsset> kv in clipAssets) {
            TimelineClip clip = kv.Key;
            StreamingImageSequencePlayableAsset sisAsset = kv.Value;

            int numImages  = sisAsset.GetNumImages();
            if (numImages <= 0|| null == clip.GetParentTrack())
                continue;

            double startTime = clip.start;
            double endTime = clip.end;
            double loadStartOffsetTime = 1.0f + numImages * 0.1f;

            //Start to preload images before the clip is active
            if ( directorTime>= startTime - loadStartOffsetTime && directorTime < endTime) {
                sisAsset.ContinuePreloadingImages();                    
            }

        }

    }
//----------------------------------------------------------------------------------------------------------------------
        internal static int CalculateNumFrames(TimelineClip clip)
        {
            double fps       = clip.GetParentTrack().timelineAsset.editorSettings.GetFPS();
            int    numFrames = Mathf.RoundToInt((float)(clip.duration * fps));

            return(numFrames);
        }
        /// <summary>
        /// The color drawn under the clip. By default, the color is the same as the track color.
        /// </summary>
        /// <param name="clip">The clip being drawn.</param>
        /// <returns>Returns the highlight color of the clip being drawn.</returns>
        public Color GetDefaultHighlightColor(TimelineClip clip)
        {
            if (clip == null)
            {
                return(Color.white);
            }

            return(TrackResourceCache.GetTrackColor(clip.GetParentTrack()));
        }
//----------------------------------------------------------------------------------------------------------------------

        internal static void ResizeSISTimelineClip(TimelineClip clip, double duration)
        {
#if UNITY_EDITOR
            Undo.RegisterCompleteObjectUndo(clip.GetParentTrack(), "StreamingImageSequence: Set Duration");
#endif
            clip.duration = duration;

            TimelineEditor.Refresh(RefreshReason.ContentsModified);
        }
Ejemplo n.º 11
0
//----------------------------------------------------------------------------------------------------------------------

        void CreateMarker()
        {
            TimelineClip clipOwner  = m_clipDataOwner.GetOwner();
            TrackAsset   trackAsset = clipOwner?.GetParentTrack();

            Assert.IsNotNull(trackAsset);
            Assert.IsNull(m_marker);

            m_marker = trackAsset.CreateMarker <FrameMarker>(m_localTime);
        }
Ejemplo n.º 12
0
//----------------------------------------------------------------------------------------------------------------------

        /// <inheritdoc/>
        public override void DrawBackground(TimelineClip clip, ClipBackgroundRegion region)
        {
            base.DrawBackground(clip, region);

            Rect rect = region.position;

            if (rect.width <= SISEditorConstants.MIN_PREVIEW_REGION_WIDTH)
            {
                return;
            }

            ImageFolderPlayableAsset <T> curAsset = clip.asset as ImageFolderPlayableAsset <T>;

            if (null == curAsset)
            {
                return;
            }

            DrawBackgroundTexture(rect, curAsset.GetTimelineBGColor());

            int numImages = curAsset.GetNumImages();

            if (numImages <= 0)
            {
                return;
            }

            if (Event.current.type == EventType.Repaint)
            {
                PreviewClipInfo clipInfo = new PreviewClipInfo()
                {
                    Duration              = clip.duration,
                    TimeScale             = clip.timeScale,
                    ClipIn                = clip.clipIn,
                    FramePerSecond        = clip.GetParentTrack().timelineAsset.editorSettings.GetFPS(),
                    ImageDimensionRatio   = curAsset.GetOrUpdateDimensionRatio(),
                    VisibleLocalStartTime = region.startTime,
                    VisibleLocalEndTime   = region.endTime,
                    VisibleRect           = rect,
                };

                PreviewUtility.EnumeratePreviewImages(ref clipInfo, (PreviewDrawInfo drawInfo) => {
                    DrawPreviewImageV(ref drawInfo, clip, curAsset);
                });

                //For hiding frame marker automatically
                PlayableFrameClipData clipData = curAsset.GetBoundClipData();
                if (null != clipData)
                {
                    clipData.UpdateTimelineWidthPerFrame(rect.width, region.endTime - region.startTime,
                                                         clipInfo.FramePerSecond, clipInfo.TimeScale);
                }
            }
        }
Ejemplo n.º 13
0
 protected override void OnCreateClip(TimelineClip clip)
 {
     clip.start = 0;
     //Clip starts with some preset duration, we want it to stretch the full length but that preset duration ruins the timeline length.
     clip.duration = float.Epsilon;
     //Now we can ask for the correct timeline length before the clip came
     clip.duration = clip.GetParentTrack().parent.duration;
     if (clip.duration <= float.Epsilon)
     {
         clip.duration = 1;
     }
 }
Ejemplo n.º 14
0
        public static TimelineClip GetPreviousClip(TimelineClip clip)
        {
            TimelineClip previousClip = null;

            foreach (var c in clip.GetParentTrack().clips)
            {
                if (c.start < clip.start && (previousClip == null || c.start >= previousClip.start))
                {
                    previousClip = c;
                }
            }
            return(previousClip);
        }
//----------------------------------------------------------------------------------------------------------------------
        internal static void DestroyTestTimelineAssets(TimelineClip clip)
        {
            TrackAsset    movieTrack    = clip.GetParentTrack();
            TimelineAsset timelineAsset = movieTrack.timelineAsset;

            string tempTimelineAssetPath = AssetDatabase.GetAssetPath(timelineAsset);

            Assert.False(string.IsNullOrEmpty(tempTimelineAssetPath));

            timelineAsset.DeleteTrack(movieTrack);
            ObjectUtility.Destroy(timelineAsset);
            AssetDatabase.DeleteAsset(tempTimelineAssetPath);
        }
Ejemplo n.º 16
0
        public IEnumerator ResizePlayableAsset()
        {
            PlayableDirector director = EditorUtilityTest.NewSceneWithDirector();
            TimelineClip     clip     = EditorUtilityTest.CreateTestSISTimelineClip(director);
            StreamingImageSequencePlayableAsset sisAsset = clip.asset as StreamingImageSequencePlayableAsset;

            Assert.IsNotNull(sisAsset);
            yield return(null);

            SISClipData clipData = sisAsset.GetBoundClipData();

            Assert.IsNotNull(clipData);

            clipData.RequestFrameMarkers(true, true);
            Undo.IncrementCurrentGroup(); //the base of undo is here. FrameMarkerVisibility is still true after undo
            TimelineEditor.Refresh(RefreshReason.ContentsModified);
            yield return(null);

            //Original length
            TrackAsset trackAsset = clip.GetParentTrack();

            Assert.AreEqual(TimelineUtility.CalculateNumFrames(clip), trackAsset.GetMarkerCount());
            double origClipDuration = clip.duration;

            //Resize longer
            EditorUtilityTest.ResizeSISTimelineClip(clip, origClipDuration + 3.0f); yield return(null);

            Assert.AreEqual(TimelineUtility.CalculateNumFrames(clip), trackAsset.GetMarkerCount());

            //Undo
            EditorUtilityTest.UndoAndRefreshTimelineEditor(); yield return(null);

            Assert.AreEqual(origClipDuration, clip.duration);
            Assert.AreEqual(TimelineUtility.CalculateNumFrames(clip), trackAsset.GetMarkerCount());

            //Resize shorter
            EditorUtilityTest.ResizeSISTimelineClip(clip, Mathf.Max(0.1f, ((float)(origClipDuration) - 3.0f))); yield return(null);

            Assert.AreEqual(TimelineUtility.CalculateNumFrames(clip), trackAsset.GetMarkerCount());

            //Undo
            EditorUtilityTest.UndoAndRefreshTimelineEditor(); yield return(null);

            Assert.AreEqual(origClipDuration, clip.duration);
            Assert.AreEqual(TimelineUtility.CalculateNumFrames(clip), trackAsset.GetMarkerCount());


            EditorUtilityTest.DestroyTestTimelineAssets(clip);
            yield return(null);
        }
            public void UpdatePlayableLookup(TimelineClip clip, GameObject go, Playable p)
            {
                if (clip == null || go == null || !p.IsValid())
                {
                    return;
                }

                if (clip.curves != null)
                {
                    m_AnimationClipToTimelineClip[clip.curves] = clip;
                }

                UpdatePlayableLookup(clip.GetParentTrack().timelineAsset, clip, go, p);
            }
Ejemplo n.º 18
0
        public static TimelineClip Clone(TimelineClip clip, IExposedPropertyTable sourceTable, IExposedPropertyTable destTable, double time, PlayableAsset newOwner = null)
        {
            if (newOwner == null)
            {
                newOwner = clip.GetParentTrack();
            }

            TimelineClip newClip = DuplicateClip(clip, sourceTable, destTable, newOwner);

            newClip.start = time;
            var track = newClip.GetParentTrack();

            track.SortClips();
            return(newClip);
        }
//----------------------------------------------------------------------------------------------------------------------

        //Resize PlayableFrames and used the previous values
        internal void RefreshPlayableFrames()
        {
            TimelineClip clipOwner = GetOwner();


            //Clip doesn't have parent. Might be because the clip is being moved
            if (null == clipOwner.GetParentTrack())
            {
                return;
            }

            int numIdealNumPlayableFrames = TimelineUtility.CalculateNumFrames(clipOwner);

            //Change the size of m_playableFrames and reinitialize if necessary
            int prevNumPlayableFrames = m_playableFrames.Count;

            if (numIdealNumPlayableFrames != prevNumPlayableFrames)
            {
                //Change the size of m_playableFrames and reinitialize if necessary
                List <bool> prevUsedFrames = new List <bool>(prevNumPlayableFrames);
                foreach (SISPlayableFrame frame in m_playableFrames)
                {
                    prevUsedFrames.Add(null == frame || frame.IsUsed()); //if frame ==null, just regard as used.
                }

                UpdatePlayableFramesSize(numIdealNumPlayableFrames);

                //Reinitialize
                if (prevNumPlayableFrames > 0)
                {
                    for (int i = 0; i < numIdealNumPlayableFrames; ++i)
                    {
                        int prevIndex = (int)(((float)(i) / numIdealNumPlayableFrames) * prevNumPlayableFrames);
                        m_playableFrames[i].SetUsed(prevUsedFrames[prevIndex]);
                    }
                }
            }

            //Refresh all markers
            double timePerFrame      = TimelineUtility.CalculateTimePerFrame(clipOwner);
            int    numPlayableFrames = m_playableFrames.Count;

            for (int i = 0; i < numPlayableFrames; ++i)
            {
                m_playableFrames[i].SetIndexAndLocalTime(i, i * timePerFrame);
                m_playableFrames[i].Refresh(m_frameMarkersVisibility);
            }
        }
Ejemplo n.º 20
0
//----------------------------------------------------------------------------------------------------------------------
    protected override void ProcessActiveClipV(StreamingImageSequencePlayableAsset asset,
        double directorTime, TimelineClip activeClip) 
    {
        int numImages  = asset.GetNumImages();
        if (numImages <=0 || null == activeClip.GetParentTrack())
            return;
        
        int index = asset.GlobalTimeToImageIndex(activeClip, directorTime);
        asset.RequestLoadImage(index);
        Texture2D tex = asset.GetTexture();
        if (tex.IsNullRef()) {
            tex = RuntimeTextures.GetTransparentTexture();
        }

        m_sisRenderer.UpdateTexture(tex);
    }
        /// <inheritdoc/>
        public override ClipDrawOptions GetClipOptions(TimelineClip clip)
        {
            var clipOptions = base.GetClipOptions(clip);
            var asset       = clip.asset as AnimationPlayableAsset;

            if (asset != null)
            {
                clipOptions.errorText = GetErrorText(asset, clip.GetParentTrack() as AnimationTrack, clipOptions.errorText);
            }

            if (clip.recordable)
            {
                clipOptions.highlightColor = DirectorStyles.Instance.customSkin.colorAnimationRecorded;
            }

            return(clipOptions);
        }
        public IEnumerator CreatePlayableAsset()
        {
            PlayableDirector         director = EditorUtilityTest.NewSceneWithDirector();
            TimelineClip             clip     = EditorUtilityTest.CreateTestRenderCacheTimelineClip(director);
            RenderCachePlayableAsset renderCachePlayableAsset = clip.asset as RenderCachePlayableAsset;

            Assert.IsNotNull(renderCachePlayableAsset);

            //Test the track immediately
            RenderCacheTrack track = clip.GetParentTrack() as RenderCacheTrack;

            Assert.IsNotNull(track);
            yield return(null);

            EditorUtilityTest.DestroyTestTimelineAssets(clip);
            yield return(null);
        }
Ejemplo n.º 23
0
        public IEnumerator ResetFrameMarkers()
        {
            PlayableDirector director = EditorUtilityTest.NewSceneWithDirector();
            TimelineClip     clip     = EditorUtilityTest.CreateTestSISTimelineClip(director);
            StreamingImageSequencePlayableAsset sisAsset = clip.asset as StreamingImageSequencePlayableAsset;

            Assert.IsNotNull(sisAsset);
            yield return(null);

            SISClipData clipData = sisAsset.GetBoundClipData();

            Assert.IsNotNull(clipData);
            clipData.RequestFrameMarkers(true);
            yield return(null);

            //Change image to false
            StreamingImageSequenceTrack track = clip.GetParentTrack() as StreamingImageSequenceTrack;

            Assert.IsNotNull(track);
            foreach (var m in track.GetMarkers())
            {
                FrameMarker marker = m as FrameMarker;
                Assert.IsNotNull(marker);
                marker.SetFrameUsed(false);

                UnityEngine.Assertions.Assert.IsFalse(marker.IsFrameUsed());
            }
            yield return(null);

            sisAsset.ResetPlayableFrames();
            yield return(null);

            //Check if all markers have been reset to used
            foreach (var m in track.GetMarkers())
            {
                FrameMarker marker = m as FrameMarker;
                Assert.IsNotNull(marker);
                UnityEngine.Assertions.Assert.IsTrue(marker.IsFrameUsed());
            }
            yield return(null);


            EditorUtilityTest.DestroyTestTimelineAssets(clip);
            yield return(null);
        }
Ejemplo n.º 24
0
        static MatchTargetFields GetMatchFields(TimelineClip clip)
        {
            var track = clip.GetParentTrack() as AnimationTrack;

            if (track == null)
            {
                return(MatchTargetFieldConstants.None);
            }

            var asset  = clip.asset as AnimationPlayableAsset;
            var fields = track.matchTargetFields;

            if (asset != null && !asset.useTrackMatchFields)
            {
                fields = asset.matchTargetFields;
            }
            return(fields);
        }
Ejemplo n.º 25
0
//----------------------------------------------------------------------------------------------------------------------


        private void DrawCaptureSelectedFramesGUI(TimelineClip timelineClip, PlayableFrameClipData clipData)
        {
            TrackAsset track = timelineClip.GetParentTrack();

            GUILayout.BeginHorizontal();
            bool markerVisibility = InspectorUtility.DrawFrameMarkersGUI(m_asset);

            GUILayout.FlexibleSpace();
            EditorGUI.BeginDisabledGroup(!markerVisibility);
            if (GUILayout.Button("Capture All", GUILayout.Width(80)))
            {
                Undo.RegisterCompleteObjectUndo(track, "Capturing all frames");
                clipData.SetAllPlayableFramesProperty(PlayableFramePropertyID.USED, true);
            }
            if (GUILayout.Button("Reset", GUILayout.Width(50)))
            {
                Undo.RegisterCompleteObjectUndo(track, "Capturing no frames");
                clipData.SetAllPlayableFramesProperty(PlayableFramePropertyID.USED, false);
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Initializes and returns an instance of SequenceContext.
        /// </summary>
        /// <param name="director">The PlayableDirector associated with the context. Must be a valid PlayableDirector reference. </param>
        /// <param name="clip">The TimelineClip reference that controls the sequence. Specify <see langword="null"/> to specify that the sequence is the root. If non-null, the clip must be part of a valid <see cref="TimelineAsset"/>.</param>
        /// <exception cref="System.ArgumentNullException"> <paramref name="director"/> is null.</exception>
        /// <exception cref="System.ArgumentException"> The <paramref name="clip"/> is not part of a <see cref="TrackAsset"/>.</exception>
        /// <exception cref="System.ArgumentException"> The <paramref name="clip"/> is part of a track but not part of a <see cref="TimelineAsset"/>.</exception>
        public SequenceContext(PlayableDirector director, TimelineClip clip)
        {
            if (director == null)
            {
                throw new ArgumentNullException(nameof(director));
            }

            var parentTrack = clip?.GetParentTrack();

            if (clip != null && parentTrack == null)
            {
                throw new ArgumentException("The provided clip must be part of a track", nameof(clip));
            }

            if (clip != null && parentTrack.timelineAsset == null)
            {
                throw new ArgumentException("The provided clip must be part of a Timeline.", nameof(clip));
            }

            this.director = director;
            this.clip     = clip;
            m_Valid       = true;
        }
Ejemplo n.º 27
0
//----------------------------------------------------------------------------------------------------------------------


        private void DrawLockFramesGUI(TimelineClip timelineClip, PlayableFrameClipData clipData)
        {
            TrackAsset track = timelineClip.GetParentTrack();

            using (new EditorGUILayout.HorizontalScope()) {
                EditorGUILayout.PrefixLabel("Lock Frames");

                bool lockMode = GUILayout.Toggle(m_lockMode, EditorTextures.GetLockTexture(), "Button",
                                                 GUILayout.Height(20f), GUILayout.Width(30f));
                if (lockMode != m_lockMode) //lock state changed
                {
                    if (lockMode)
                    {
                        LockSISData(clipData);
                    }
                    else
                    {
                        UnlockSISData();
                    }
                }

                GUILayout.FlexibleSpace();
                EditorGUI.BeginDisabledGroup(!m_lockMode);
                if (GUILayout.Button("Lock All", GUILayout.Width(80)))
                {
                    Undo.RegisterCompleteObjectUndo(track, "Locking all frames");
                    clipData.SetAllPlayableFramesProperty(PlayableFramePropertyID.LOCKED, true);
                }
                if (GUILayout.Button("Reset", GUILayout.Width(50)))
                {
                    Undo.RegisterCompleteObjectUndo(track, "Locking no frames");
                    clipData.SetAllPlayableFramesProperty(PlayableFramePropertyID.LOCKED, false);
                }
                EditorGUI.EndDisabledGroup();
            }
        }
Ejemplo n.º 28
0
//----------------------------------------------------------------------------------------------------------------------

    /// <summary>
    /// StreamingImageSequencePlayableAsset GUI Drawing
    /// </summary>
    public override void OnInspectorGUI() {
        if (null == m_asset)
            return;
        

        using (new EditorGUILayout.VerticalScope (GUI.skin.box))  {

            m_resolutionFoldout = EditorGUILayout.Foldout(m_resolutionFoldout, "Resolution");
            if (m_resolutionFoldout) {
                ImageDimensionInt res = m_asset.GetResolution();
                EditorGUILayout.LabelField("Width",  $"{res.Width } px");
                EditorGUILayout.LabelField("Height",  $"{res.Height } px");
            }
            GUILayout.Space(4f);
        }
        
        GUILayout.Space(4f);

        using (new EditorGUILayout.VerticalScope(GUI.skin.box))
        {
            GUILayout.Label("Folder", "BoldLabel");
            GUILayout.Space(4f);
            DrawFolderGUI();
        }
        GUILayout.Space(4f);

        using (new EditorGUILayout.VerticalScope(GUI.skin.box)) {
            int numImages = m_asset.GetNumImages();

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("Images: " + numImages, "BoldLabel");            
            if (GUILayout.Button("Reload", GUILayout.Width(50))) {
                m_asset.Reload();
            }
            EditorGUILayout.EndHorizontal();
            
            using (new EditorGUI.DisabledScope(0 == numImages)) {
                if (0 == numImages)
                    EditorGUILayout.IntField("FPS", 0);
                else {
                    TimelineClip clip = m_asset.GetBoundClipData()?.GetOwner();
                    //There is no assigned clip if the playableAsset is not loaded in TimelineWindow
                    if (null != clip) {                         
                                                
                        EditorGUIDrawerUtility.DrawUndoableGUI(clip.GetParentTrack(), "Change FPS", 
                            /*guiFunc=*/ ()=> {
                                float fps = SISPlayableAssetUtility.CalculateFPS(m_asset);
                                float val = EditorGUILayout.FloatField("FPS", fps); 
                                return Mathf.Max(0.1f, val);
                            }, 
                            /*updateFunc=*/ (float newFPS) => {
                                SISPlayableAssetUtility.SetFPS(m_asset, newFPS);                                
                            }
                        );
                    }                    
                }
            }
            
            GUILayout.Space(4f);
            m_imageListFoldout = EditorGUILayout.Foldout(m_imageListFoldout, "Images");
            if (m_imageListFoldout) {
                DoImageGUI();
            }
        }

        if (null == TimelineEditor.selectedClip) 
            return;
        
        GUILayout.Space(15);
        //Frame markers
        if (TimelineEditor.selectedClip.asset == m_asset) {
            using (new EditorGUILayout.HorizontalScope()) {
                InspectorUtility.DrawFrameMarkersGUI(m_asset);
                if (GUILayout.Button("Reset", GUILayout.Width(50f))) {
                    m_asset.ResetPlayableFrames();
                }
            }
        }
        GUILayout.Space(15);
        
        using (new EditorGUILayout.VerticalScope(GUI.skin.box)) {
            EditorGUILayout.LabelField("Background Colors");
            ++EditorGUI.indentLevel;
            
            EditorGUIDrawerUtility.DrawUndoableGUI(m_asset, "Change BG Color", 
                /*guiFunc=*/ ()=> EditorGUILayout.ColorField("In Timeline Window", m_asset.GetTimelineBGColor()), 
                /*updateFunc=*/ (Color newColor) => {                               
                    m_asset.SetTimelineBGColor(newColor);                                
                }
            );
            
            --EditorGUI.indentLevel;
            GUILayout.Space(15);
        }

        
        if (GUILayout.Button("Reset Curve (Not Undoable)")) {
            //AnimationUtility.SetEditorCurve(), which is called below, doesn't seem to be undoable
            EditorCurveBinding curveBinding = StreamingImageSequencePlayableAsset.GetTimeCurveBinding();                 
            ExtendedClipEditorUtility.ResetClipDataCurve(m_asset, curveBinding);
        }
    }
        public IEnumerator UpdateRenderCachePNGInStreamingAssets()
        {
            PlayableDirector         director                 = EditorUtilityTest.NewSceneWithDirector();
            TimelineClip             clip                     = EditorUtilityTest.CreateTestRenderCacheTimelineClip(director);
            TimelineAsset            timelineAsset            = director.playableAsset as TimelineAsset;
            RenderCachePlayableAsset renderCachePlayableAsset = clip.asset as RenderCachePlayableAsset;
            RenderCacheTrack         track                    = clip.GetParentTrack() as RenderCacheTrack;

            Assert.IsNotNull(timelineAsset);
            Assert.IsNotNull(renderCachePlayableAsset);
            Assert.IsNotNull(track);
            Assert.IsNotNull(Camera.main);
            yield return(null);

            clip.duration = (1.0f / timelineAsset.editorSettings.GetFPS());
            const string OUTPUT_FOLDER = "Asset/StreamingAssets/RenderCachePNGForTestRunner";

            Directory.CreateDirectory(OUTPUT_FOLDER);
            renderCachePlayableAsset.SetFolder(OUTPUT_FOLDER);

            GameObject           cameraRenderCapturerGO = new GameObject();
            CameraRenderCapturer cameraRenderCapturer   = cameraRenderCapturerGO.AddComponent <CameraRenderCapturer>();

            cameraRenderCapturer.SetCamera(Camera.main);
            director.SetGenericBinding(track, cameraRenderCapturer);
            yield return(null);

            //Update RenderCache
            EditorCoroutineUtility.StartCoroutineOwnerless(
                RenderCachePlayableAssetInspector.UpdateRenderCacheCoroutine(director, renderCachePlayableAsset)
                );

            //A hack to wait until the coroutine is finished
            const float TIMEOUT_SEC = 3.0f;

            Assert.IsTrue(Directory.Exists(OUTPUT_FOLDER));
            float prevTime = Time.realtimeSinceStartup;

            while (Time.realtimeSinceStartup - prevTime < TIMEOUT_SEC)
            {
                yield return(null);
            }

            string imageFilePath = renderCachePlayableAsset.GetImageFilePath(0);

            Assert.IsTrue(File.Exists(imageFilePath));
            ImageLoader.RequestLoadFullImage(imageFilePath);

            //Another hack to wait until the load is finished
            prevTime = Time.realtimeSinceStartup;
            while (Time.realtimeSinceStartup - prevTime < TIMEOUT_SEC)
            {
                yield return(null);
            }

            ImageLoader.GetImageDataInto(imageFilePath, StreamingImageSequenceConstants.IMAGE_TYPE_FULL, out ImageData imageData);
            Assert.AreEqual(StreamingImageSequenceConstants.READ_STATUS_SUCCESS, imageData.ReadStatus);
            yield return(null);

            //cleanup
            StreamingImageSequencePlugin.UnloadAllImages();
            bool folderDeleted = FileUtility.DeleteFilesAndFolders(OUTPUT_FOLDER);

            Assert.IsTrue(folderDeleted);
            EditorUtilityTest.DestroyTestTimelineAssets(clip);
            yield return(null);
        }
 public int GetChannel()
 {
     return(((LegacyAnimatorTrack)_clip.GetParentTrack())._animationChannel);
 }