//---------------------------------------------------------------------------------------------------------------------- protected override void DrawPreviewImageV(ref PreviewDrawInfo drawInfo, TimelineClip clip, StreamingImageSequencePlayableAsset sisAsset) { int imageIndex = sisAsset.LocalTimeToImageIndex(clip, drawInfo.LocalTime); string imagePath = sisAsset.GetImageFilePath(imageIndex); PreviewUtility.DrawPreviewImage(ref drawInfo, imagePath); }
//---------------------------------------------------------------------------------------------------------------------- protected override void DrawPreviewImageV(ref PreviewDrawInfo drawInfo, TimelineClip clip, ImageFolderPlayableAsset <SISClipData> playableAsset) { StreamingImageSequencePlayableAsset sisAsset = playableAsset as StreamingImageSequencePlayableAsset; Assert.IsNotNull(sisAsset); int imageIndex = sisAsset.LocalTimeToImageIndex(clip, drawInfo.LocalTime); string imagePath = sisAsset.GetImageFilePath(imageIndex); PreviewUtility.DrawPreviewImage(ref drawInfo, imagePath); }
//---------------------------------------------------------------------------------------------------------------------- internal static void DrawPreviewImage(ref PreviewDrawInfo drawInfo, string imagePath) { if (!File.Exists(imagePath)) { return; } Texture2D tex = null; if (imagePath.IsRegularAssetPath()) { tex = AssetDatabase.LoadAssetAtPath <Texture2D>(imagePath); } else { ImageLoader.GetImageDataInto(imagePath, StreamingImageSequenceConstants.IMAGE_TYPE_PREVIEW , out ImageData readResult); switch (readResult.ReadStatus) { case StreamingImageSequenceConstants.READ_STATUS_LOADING: break; case StreamingImageSequenceConstants.READ_STATUS_SUCCESS: { tex = PreviewTextureFactory.GetOrCreate(imagePath, ref readResult); break; } default: { ImageLoader.RequestLoadPreviewImage(imagePath, (int)drawInfo.DrawRect.width, (int)drawInfo.DrawRect.height); break; } } } if (null == tex) { return; } if (PlayerSettings.colorSpace == ColorSpace.Linear) { Material mat = GetOrCreateLinearToGammaMaterial(); Graphics.DrawTexture(drawInfo.DrawRect, tex, mat); } else { Graphics.DrawTexture(drawInfo.DrawRect, tex); } }
//---------------------------------------------------------------------------------------------------------------------- protected override void DrawPreviewImageV(ref PreviewDrawInfo drawInfo, TimelineClip clip, RenderCachePlayableAsset renderCachePlayableAsset) { double normalizedLocalTime = drawInfo.LocalTime / clip.duration; int numImages = renderCachePlayableAsset.GetNumImages(); Assert.IsTrue(numImages > 0); //Can't round up, because if the time for the next frame hasn't been reached, then we should stick int index = Mathf.FloorToInt(numImages * (float)normalizedLocalTime); index = Mathf.Clamp(index, 0, numImages - 1); //Draw string imagePath = renderCachePlayableAsset.GetImageFilePath(index); PreviewUtility.DrawPreviewImage(ref drawInfo, imagePath); }
//---------------------------------------------------------------------------------------------------------------------- protected abstract void DrawPreviewImageV(ref PreviewDrawInfo drawInfo, TimelineClip clip, ImageFolderPlayableAsset <T> playableAsset);
internal static void EnumeratePreviewImages(ref PreviewClipInfo clipInfo, Action <PreviewDrawInfo> drawPreviewFunc) { double visibleLocalStartTime = clipInfo.VisibleLocalStartTime; double visibleLocalEndTime = clipInfo.VisibleLocalEndTime; Rect visibleRect = clipInfo.VisibleRect; //[Note-sin: 2020-12-16] Only support fixed height atm. Dynamic heights will make it more a lot more complex to: //- calculate the position/width/height of each image and if they should be shrunk in one dimension //- allocate memory for preview images const int FIXED_HEIGHT = 25; visibleRect.y = (visibleRect.height - FIXED_HEIGHT) + 1; visibleRect.height = FIXED_HEIGHT; double visibleDuration = visibleLocalEndTime - visibleLocalStartTime; double scaledFramePerSecond = clipInfo.FramePerSecond / clipInfo.TimeScale; double scaledClipDuration = clipInfo.Duration * clipInfo.TimeScale; //Calculate rect for one image. float dimensionRatio = clipInfo.ImageDimensionRatio; int widthPerPreviewImage = (int)(dimensionRatio * visibleRect.height); int heightPerPreviewImage = (int)visibleRect.height; //Calculate the time first visible frame int firstFrame = (int )Math.Floor((float)(visibleLocalStartTime * scaledFramePerSecond)); double firstFrameTime = firstFrame / scaledFramePerSecond; int numAllPreviewImages = 0; { //Calculate the width if we are showing the whole clip //Eq: (visibleWidth / visibleDuration = fullClipWidth / fullDuration) float fullClipWidth = Mathf.Ceil((float)(visibleRect.width * scaledClipDuration / visibleDuration)); //Calculate the number of preview images available for this clip, at least 1 (incl. the invisible ones) numAllPreviewImages = Mathf.Max(Mathf.FloorToInt(fullClipWidth / widthPerPreviewImage), 1); //All frames for the clip (including the invisible ones) int numAllFrames = Mathf.RoundToInt((float)(clipInfo.Duration * clipInfo.FramePerSecond)); numAllPreviewImages = Mathf.Min(numAllPreviewImages, numAllFrames); } if (numAllPreviewImages <= 0) { return; } double localTimeCounter = scaledClipDuration / numAllPreviewImages; //Base the firstFrameTime on localTimeCounter, which was calculated using full clip length and fullWidth, //so that they transition smoothly when we slide the slider in Timeline window firstFrameTime = Mathf.Floor((float)firstFrameTime / (float )localTimeCounter) * localTimeCounter; double firstFrameRectX = FindFrameXPos(firstFrameTime, visibleLocalStartTime, visibleDuration, visibleRect.x, visibleRect.width); //Loop to render all preview Images, ignoring those outside the visible Rect float startVisibleRectX = visibleRect.x - widthPerPreviewImage; //for rendering preview images that are partly visible PreviewDrawInfo drawInfo = new PreviewDrawInfo() { DrawRect = new Rect() { x = (float)firstFrameRectX, y = visibleRect.y, width = widthPerPreviewImage, height = heightPerPreviewImage, }, LocalTime = firstFrameTime, }; //minor optimization by executing FindFrameXPos() less double secondFrameRectX = (float)FindFrameXPos(drawInfo.LocalTime + localTimeCounter, visibleLocalStartTime, visibleDuration, visibleRect.x, visibleRect.width); float xCounter = (float)(secondFrameRectX - firstFrameRectX); //Shouldn't happen, but xCounter can be minus when moving the horizontal slider ? if (xCounter <= 0) { return; } float endVisibleRectX = (visibleRect.x + visibleRect.width) - (xCounter * 0.5f); while (drawInfo.DrawRect.x < (endVisibleRectX)) { //drawInfo.DrawRect.x = (float) FindFrameXPos(drawInfo.LocalTime, visibleLocalStartTime, visibleDuration, visibleRect.x, visibleRect.width); if (drawInfo.DrawRect.x >= startVisibleRectX) { drawPreviewFunc(drawInfo); } drawInfo.DrawRect.x += xCounter; drawInfo.LocalTime += localTimeCounter; } #if DEBUG_PREVIEW_IMAGES Debug.Log($"Width: {visibleRect.width} numAllPreviewImages: {numPreviewImagesToDraw}, " + $"firstFrameRectX: {firstFrameRectX}, firstFrameTime: {firstFrameTime}, " + $"VisibleRect: {visibleRect}, xCounter: {xCounter}, " + $"VisibleLocalStartTime: {visibleLocalStartTime}, VisibleLocalEndTime: {visibleLocalEndTime}, " + $"widthPerPreviewImage: {widthPerPreviewImage}, DimensionRatio: {dimensionRatio}, " + $"ClipTimeScale: {clipInfo.TimeScale}, ClipIn: {clipInfo.ClipIn}"); #endif }