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