public void Destroy()
        {
            GameObject go = new GameObject();

            Assert.IsNotNull(go);
            ObjectUtility.Destroy(go);
            UnityEngine.Assertions.Assert.IsNull(go);
        }
        public void TransformTest()
        {
            GameObject    go = new GameObject("TransformTest");
            GameBehaviour t  = go.AddComponent <GameBehaviour>();

            Assert.IsNotNull(t.GetTransform());
            ObjectUtility.Destroy(go);
        }
        public IEnumerator Destroy()
        {
            GameObject go = new GameObject();

            Assert.IsNotNull(go);
            ObjectUtility.Destroy(go);
            yield return(null);

            UnityEngine.Assertions.Assert.IsNull(go);
        }
//----------------------------------------------------------------------------------------------------------------------
        internal static void DestroyTestTimelineAssets(TimelineClip clip)
        {
            TrackAsset    movieTrack    = clip.parentTrack;
            TimelineAsset timelineAsset = movieTrack.timelineAsset;

            string tempTimelineAssetPath = AssetDatabase.GetAssetPath(timelineAsset);

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

            timelineAsset.DeleteTrack(movieTrack);
            ObjectUtility.Destroy(timelineAsset);
            AssetDatabase.DeleteAsset(tempTimelineAssetPath);
        }
Example #5
0
    //Delete GameObject if they exist in prevRecords, but not in curRecords
    private static void DeleteInvalidRecordedGameObjects(IDictionary<string, EntityRecord> prevRecords,
        IDictionary<string, EntityRecord> curRecords) 
    {
        foreach (KeyValuePair<string, EntityRecord> kv in prevRecords) {
            string       goPath           = kv.Key;
            EntityRecord prevEntityRecord = kv.Value;

            if (curRecords.ContainsKey(goPath)) 
                continue;
            
            ObjectUtility.Destroy(prevEntityRecord.go);
        }
    }
Example #6
0
//----------------------------------------------------------------------------------------------------------------------    
    private static void DestroyIrrelevantComponents(GameObject obj, EntityType curEntityType) {

        HashSet<Type> componentsToDelete = new HashSet<Type>(m_componentsToDeleteOnReload);

        //Check which component should remain (should not be deleted)
        switch (curEntityType) {
            case EntityType.Camera:
                componentsToDelete.Remove(typeof(Camera));
                break;
            case EntityType.Light:
                componentsToDelete.Remove(typeof(Light));
                break;
            case EntityType.Mesh: {
                componentsToDelete.Remove(typeof(SkinnedMeshRenderer));
                componentsToDelete.Remove(typeof(MeshFilter));
                componentsToDelete.Remove(typeof(MeshRenderer));
                break;
            }                
            case EntityType.Points:
                componentsToDelete.Remove(typeof(PointCache));
                componentsToDelete.Remove(typeof(PointCacheRenderer));
                break;
            default:
                break;
        }
        

        foreach (Type t in componentsToDelete) {
            Component c = obj.GetComponent(t);
            if (null == c)
                continue;
            
            ObjectUtility.Destroy(c);
        }

    }
//----------------------------------------------------------------------------------------------------------------------
        internal static IEnumerator UpdateRenderCacheCoroutine(PlayableDirector director, RenderCachePlayableAsset renderCachePlayableAsset)
        {
            Assert.IsNotNull(director);
            Assert.IsNotNull(renderCachePlayableAsset);

            TimelineClipSISData timelineClipSISData = renderCachePlayableAsset.GetBoundTimelineClipSISData();

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

            TrackAsset         track          = renderCachePlayableAsset.GetBoundTimelineClipSISData().GetOwner().parentTrack;
            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;
            }


            //begin capture
            bool canCapture = renderCapturer.BeginCapture();

            if (!canCapture)
            {
                EditorUtility.DisplayDialog("Streaming Image Sequence",
                                            renderCapturer.GetLastErrorMessage(),
                                            "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;
            }

            Texture capturerTex = renderCapturer.GetInternalTexture();

            //Show progress in game view
            GameObject           progressGo = new GameObject("Blitter");
            LegacyTextureBlitter blitter    = progressGo.AddComponent <LegacyTextureBlitter>();

            blitter.SetTexture(capturerTex);
            blitter.SetCameraDepth(int.MaxValue);

            TimelineClip timelineClip     = timelineClipSISData.GetOwner();
            double       nextDirectorTime = timelineClip.start;
            double       timePerFrame     = 1.0f / track.timelineAsset.editorSettings.fps;

            int fileCounter = 0;
            int numFiles    = (int)Math.Ceiling(timelineClip.duration / timePerFrame) + 1;
            int numDigits   = MathUtility.GetNumDigits(numFiles);

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

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

            bool cancelled = false;

            while (nextDirectorTime <= timelineClip.end && !cancelled)
            {
                string fileName       = $"{prefix}{fileCounter.ToString($"D{numDigits}")}.png";
                string outputFilePath = Path.Combine(outputFolder, fileName);

                SISPlayableFrame playableFrame = timelineClipSISData.GetPlayableFrame(fileCounter);
                bool             captureFrame  = (!timelineClipSISData.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);
                }
                imageFileNames.Add(fileName);

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

                    //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);
                }


                nextDirectorTime += timePerFrame;
                ++fileCounter;

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

            if (!cancelled)
            {
                renderCachePlayableAsset.SetImageFileNames(imageFileNames);

                //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.EndCapture();
            ObjectUtility.Destroy(progressGo);

            AssetDatabase.Refresh();

            yield return(null);
        }
Example #8
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);
        }
Example #9
0
//----------------------------------------------------------------------------------------------------------------------    
    
    internal static void ChangeSceneCacheFile(SceneCachePlayer cachePlayer, string sceneCacheFilePath) {
        string     prefabPath = null;
        GameObject go         = cachePlayer.gameObject;
        //Check if it's possible to reuse the old assetsFolder
        string assetsFolder = cachePlayer.GetAssetsFolder();
        if (string.IsNullOrEmpty(assetsFolder)) {
            MeshSyncProjectSettings projectSettings = MeshSyncProjectSettings.GetOrCreateSettings();        
            string                  scOutputPath    = projectSettings.GetSceneCacheOutputPath();            
            assetsFolder = Path.Combine(scOutputPath, Path.GetFileNameWithoutExtension(sceneCacheFilePath));
        }
        
        bool isPrefabInstance = cachePlayer.gameObject.IsPrefabInstance();        
        //We are directly modifying a prefab
        if (!isPrefabInstance && go.IsPrefab()) {
            prefabPath = AssetDatabase.GetAssetPath(go);
            CreateSceneCachePlayerAndPrefab(sceneCacheFilePath, prefabPath, assetsFolder, out SceneCachePlayer player,
                out GameObject newPrefab);
            Object.DestroyImmediate(player.gameObject);
            return;

        } 
        
        if (isPrefabInstance) {
            GameObject prefab = PrefabUtility.GetCorrespondingObjectFromSource(cachePlayer.gameObject);
            
            //GetCorrespondingObjectFromSource() may return the ".sc" GameObject instead of the prefab
            //due to the SceneCacheImporter
            string assetPath = AssetDatabase.GetAssetPath(prefab);
            if (Path.GetExtension(assetPath).ToLower() == ".prefab") {
                prefabPath = assetPath;
            } else {
                isPrefabInstance = false;
            }            
        } 
        
        cachePlayer.CloseCache();
        
        //[TODO-sin: 2020-9-28] Find out if it is possible to do undo properly
        Undo.RegisterFullObjectHierarchyUndo(cachePlayer.gameObject, "SceneCachePlayer");
        
        Dictionary<string,EntityRecord> prevRecords = new Dictionary<string, EntityRecord>(cachePlayer.GetClientObjects());        
        
        GameObject tempGO = null;
        Dictionary<Transform, Transform> nonPrefabTrans = new Dictionary<Transform, Transform>(); //nonPrefab -> origParent
        if (isPrefabInstance) {
            //Move non-prefab transforms
            tempGO = new GameObject("Temp");
            FindNonPrefabChildren(cachePlayer.transform, ref nonPrefabTrans);
            nonPrefabTrans.Keys.SetParent(tempGO.transform);
            
            PrefabUtility.UnpackPrefabInstance(cachePlayer.gameObject, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);                       
        }


        //remove irrelevant  components of the GameObject if the entity type is different
        void ChangeEntityTypeCB(GameObject updatedGo, TransformData data) {
            string dataPath = data.path;
            if (!prevRecords.ContainsKey(dataPath)) 
                return;

            EntityRecord prevRecord = prevRecords[dataPath];
            if (data.entityType == prevRecord.dataType) 
                return;

            DestroyIrrelevantComponents(updatedGo, data.entityType);
        }


        cachePlayer.onUpdateEntity += ChangeEntityTypeCB;        
        cachePlayer.Init(assetsFolder);
        cachePlayer.OpenCacheInEditor(sceneCacheFilePath);        
        cachePlayer.onUpdateEntity -= ChangeEntityTypeCB;
        
        IDictionary<string,EntityRecord> curRecords = cachePlayer.GetClientObjects();
        DeleteInvalidRecordedGameObjects(prevRecords, curRecords);

        if (!isPrefabInstance) {
            return;
        }
        
        
        cachePlayer.gameObject.SaveAsPrefab(prefabPath); //Save as prefab if it was originally a prefab instance
        
        //Move nonPrefab transforms back
        foreach (KeyValuePair<Transform, Transform> kv in nonPrefabTrans) {
            Transform origParent = kv.Value;
            Transform t          = kv.Key;
            if (null == origParent) {
                ObjectUtility.Destroy(t.gameObject);
            } else {
                t.SetParent(origParent);
            } 
        }
        ObjectUtility.Destroy(tempGO);
        
        
    }