Example #1
0
        /// <summary>
        /// Capture the contents of RenderTexture into file
        /// </summary>
        /// <param name="outputFilePath">The path of the file</param>
        /// <param name="outputFormat">The output file format</param>
        public void CaptureToFile(string outputFilePath, RenderCacheOutputFormat outputFormat = RenderCacheOutputFormat.PNG)
        {
            RenderTexture prevRenderTexture = RenderTexture.active;

            RenderTexture rt = UpdateRenderTextureV();

            RenderTexture.active = rt;

            TextureFormat textureFormat = TextureFormat.RGBA32;

            if (RenderCacheOutputFormat.EXR == outputFormat)
            {
                textureFormat = TextureFormat.RGBAFloat;
            }

            Texture2D tempTex = new Texture2D(rt.width, rt.height, textureFormat, false);

            tempTex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0, false);
            tempTex.Apply();

            try {
                byte[] encodedData = null;
                switch (outputFormat)
                {
                case RenderCacheOutputFormat.EXR: encodedData = tempTex.EncodeToEXR(); break;

                default:                          encodedData = tempTex.EncodeToPNG(); break;
                }

                File.WriteAllBytes(outputFilePath, encodedData);
            } catch (Exception e) {
                Debug.LogError($"[SIS] Can't write to file: {outputFilePath}." + Environment.NewLine
                               + $"Error: {e.ToString()}");
            }

            //Cleanup
            ObjectUtility.Destroy(tempTex);
            RenderTexture.active = prevRenderTexture;
        }
 internal void SetOutputFormat(RenderCacheOutputFormat outputFormat)
 {
     m_outputFormat = outputFormat;
 }
Example #3
0
//----------------------------------------------------------------------------------------------------------------------
        internal static IEnumerator UpdateRenderCacheCoroutine(PlayableDirector director, RenderCachePlayableAsset renderCachePlayableAsset)
        {
            Assert.IsNotNull(director);
            Assert.IsNotNull(renderCachePlayableAsset);

            PlayableFrameClipData clipData = renderCachePlayableAsset.GetBoundClipData();

            if (null == clipData)
            {
                EditorUtility.DisplayDialog("Streaming Image Sequence",
                                            "RenderCachePlayableAsset is not ready",
                                            "Ok");
                yield break;
            }

            TrackAsset         track          = renderCachePlayableAsset.GetBoundClipData().GetOwner().GetParentTrack();
            BaseRenderCapturer renderCapturer = director.GetGenericBinding(track) as BaseRenderCapturer;

            if (null == renderCapturer)
            {
                EditorUtility.DisplayDialog("Streaming Image Sequence",
                                            "Please bind an appropriate RenderCapturer component to the track.",
                                            "Ok");
                yield break;
            }

            //Check output folder
            string outputFolder = renderCachePlayableAsset.GetFolder();

            if (string.IsNullOrEmpty(outputFolder) || !Directory.Exists(outputFolder))
            {
                EditorUtility.DisplayDialog("Streaming Image Sequence",
                                            "Invalid output folder",
                                            "Ok");
                yield break;
            }

            //Check if we can capture
            bool canCapture = renderCapturer.CanCaptureV();

            if (!canCapture)
            {
                EditorUtility.DisplayDialog("Streaming Image Sequence",
                                            renderCapturer.GetLastErrorMessage(),
                                            "Ok");
                yield break;
            }

            //begin capture
            IEnumerator beginCapture = renderCapturer.BeginCaptureV();

            while (beginCapture.MoveNext())
            {
                yield return(beginCapture.Current);
            }

            //Show progress in game view
            Texture capturerTex = renderCapturer.GetInternalTexture();
            RenderCachePlayableAssetEditorConfig editorConfig = renderCachePlayableAsset.GetEditorConfig();
            BaseTextureBlitter blitter         = CreateBlitter(capturerTex);
            Material           blitToScreenMat = renderCapturer.GetOrCreateBlitToScreenEditorMaterialV();

            if (!blitToScreenMat.IsNullRef())
            {
                blitToScreenMat.SetColor(m_bgColorProperty, editorConfig.GetUpdateBGColor());
                blitter.SetBlitMaterial(blitToScreenMat);
            }

            GameObject blitterGO = blitter.gameObject;



            TimelineClip timelineClip = clipData.GetOwner();
            double       timePerFrame = 1.0f / track.timelineAsset.editorSettings.GetFPS();

            //initial calculation of loop vars
            bool captureAllFrames = editorConfig.GetCaptureAllFrames();
            int  fileCounter      = 0;
            int  numFiles         = (int)Math.Ceiling(timelineClip.duration / timePerFrame) + 1;
            int  numDigits        = MathUtility.GetNumDigits(numFiles);

            if (!captureAllFrames)
            {
                fileCounter = editorConfig.GetCaptureStartFrame();
                numFiles    = (editorConfig.GetCaptureEndFrame() - fileCounter) + 1;
                if (numFiles <= 0)
                {
                    EditorUtility.DisplayDialog("Streaming Image Sequence", "Invalid Start/End Frame Settings", "Ok");
                    yield break;
                }
            }
            int captureStartFrame = fileCounter;

            string prefix = $"{timelineClip.displayName}_";
            List <WatchedFileInfo> imageFiles = new List <WatchedFileInfo>(numFiles);

            //Store old files that has the same pattern
            string[]         existingFiles = Directory.GetFiles(outputFolder, $"*.png");
            HashSet <string> filesToDelete = new HashSet <string>(existingFiles);

            RenderCacheOutputFormat outputFormat = renderCachePlayableAsset.GetOutputFormat();
            string outputExt = null;

            switch (outputFormat)
            {
            case RenderCacheOutputFormat.EXR: outputExt = "exr"; break;

            default:                          outputExt = "png"; break;;
            }

            bool cancelled = false;

            while (!cancelled)
            {
                //Always recalculate from start to avoid floating point errors
                double directorTime = timelineClip.start + (fileCounter * timePerFrame);
                if (directorTime > timelineClip.end)
                {
                    break;
                }

                if (!captureAllFrames && fileCounter > editorConfig.GetCaptureEndFrame())
                {
                    break;
                }

                string fileName       = $"{prefix}{fileCounter.ToString($"D{numDigits}")}.{outputExt}";
                string outputFilePath = Path.Combine(outputFolder, fileName);

                SISPlayableFrame playableFrame = clipData.GetPlayableFrame(fileCounter);
                bool             captureFrame  = (!clipData.AreFrameMarkersRequested() || //if markers are not requested, capture
                                                  !File.Exists(outputFilePath) || //if file doesn't exist, capture
                                                  (null != playableFrame && playableFrame.IsUsed() && !playableFrame.IsLocked())
                                                  );

                if (filesToDelete.Contains(outputFilePath))
                {
                    filesToDelete.Remove(outputFilePath);
                }


                if (captureFrame)
                {
                    SetDirectorTime(director, directorTime);

                    //Need at least two frames in order to wait for the TimelineWindow to be updated ?
                    yield return(null);

                    yield return(null);

                    yield return(null);

                    //Unload texture because it may be overwritten
                    StreamingImageSequencePlugin.UnloadImageAndNotify(outputFilePath);
                    renderCapturer.CaptureToFile(outputFilePath, outputFormat);
                }
                Assert.IsTrue(File.Exists(outputFilePath));
                FileInfo fileInfo = new FileInfo(outputFilePath);

                imageFiles.Add(new WatchedFileInfo(fileName, fileInfo.Length));

                ++fileCounter;
                cancelled = EditorUtility.DisplayCancelableProgressBar(
                    "StreamingImageSequence", "Caching render results", ((float)(fileCounter - captureStartFrame) / numFiles));
            }

            if (!cancelled)
            {
                //Delete old files
                if (AssetDatabase.IsValidFolder(outputFolder))
                {
                    foreach (string oldFile in filesToDelete)
                    {
                        AssetDatabase.DeleteAsset(oldFile);
                    }
                }
                else
                {
                    foreach (string oldFile in filesToDelete)
                    {
                        File.Delete(oldFile);
                    }
                }
            }

            //Notify
            FolderContentsChangedNotifier.GetInstance().Notify(outputFolder);

            //Cleanup
            EditorUtility.ClearProgressBar();
            renderCapturer.EndCaptureV();
            ObjectUtility.Destroy(blitterGO);
            AssetDatabase.Refresh();
            renderCachePlayableAsset.Reload();;



            yield return(null);
        }