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); }
//---------------------------------------------------------------------------------------------------------------------- /// <inheritdoc/> public override void OnCreate(TimelineClip clip, TrackAsset track, TimelineClip clonedFrom) { StreamingImageSequencePlayableAsset asset = clip.asset as StreamingImageSequencePlayableAsset; if (null == asset) { Debug.LogError("Asset is not a StreamingImageSequencePlayableAsset: " + clip.asset); return; } StreamingImageSequenceTrack sisTrack = track as StreamingImageSequenceTrack; Assert.IsNotNull(sisTrack); //This callback occurs before the clip is assigned to the track, but we need the track for creating curves. clip.parentTrack = track; //If we have a default asset, and clonedFrom is NULL, which means this is created by user interaction, //such as Folder D&D UnityEditor.DefaultAsset timelineDefaultAsset = asset.GetTimelineDefaultAsset(); if (null != timelineDefaultAsset && null == clonedFrom) { InitializeAssetFromDefaultAsset(asset, timelineDefaultAsset); } //If the clip already has curves (because of cloning, etc), then we don't set anything if (null == clip.curves) { if (asset.HasImages()) { clip.duration = asset.GetImageFileNames().Count * 0.125; // 8fps (standard limited animation) clip.displayName = Path.GetFileName(asset.GetFolder()); } clip.CreateCurves("Curves: " + clip.displayName); } TimelineClipSISData sisData = null; asset.InitTimelineClipCurve(clip); if (null == clonedFrom) { sisData = new TimelineClipSISData(clip); asset.BindTimelineClipSISData(sisData); return; } //Duplicate/Split process StreamingImageSequencePlayableAsset clonedFromAsset = clonedFrom.asset as StreamingImageSequencePlayableAsset; Assert.IsNotNull(clonedFromAsset); TimelineClipSISData otherSISData = clonedFromAsset.GetBoundTimelineClipSISData(); sisData = new TimelineClipSISData(clip, otherSISData); asset.BindTimelineClipSISData(sisData); clip.displayName = clonedFrom.displayName + " (Cloned)"; }
//---------------------------------------------------------------------------------------------------------------------- internal static TimelineClip CreateTestSISTimelineClip(PlayableDirector director) { string tempTimelineAssetPath = AssetDatabase.GenerateUniqueAssetPath("Assets/TempSISTimelineForTestRunner.playable"); //Create timeline asset TimelineAsset timelineAsset = ScriptableObject.CreateInstance <TimelineAsset>(); director.playableAsset = timelineAsset; AssetDatabase.CreateAsset(timelineAsset, tempTimelineAssetPath); //Create empty asset StreamingImageSequenceTrack sisTrack = timelineAsset.CreateTrack <StreamingImageSequenceTrack>(null, "SIS Track"); TimelineClip clip = sisTrack.CreateDefaultClip(); StreamingImageSequencePlayableAsset sisAsset = clip.asset as StreamingImageSequencePlayableAsset; Assert.IsNotNull(sisAsset); //Select gameObject and open Timeline Window. This will trigger the TimelineWindow's update etc. EditorApplication.ExecuteMenuItem("Window/Sequencing/Timeline"); // Selection.activeTransform = director.gameObject.transform; // TimelineEditor.selectedClip = sisAsset.GetBoundTimelineClip(); Selection.activeObject = director; string fullPath = Path.GetFullPath(SRC_IMAGE_PATH); ImageSequenceImporter.ImportImages(fullPath, sisAsset, false); return(clip); }
public void Import() { EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); string fullPath = "Packages/com.unity.streaming-image-sequence/Tests/Data/AeConvert.jstimeline"; Assert.IsTrue(File.Exists(fullPath)); string destFolder = "TestRunner"; JstimelineImporter.ImportTimeline(fullPath, destFolder); //Check if the generated director is valid PlayableDirector[] directors = Object.FindObjectsOfType <PlayableDirector>(); Assert.AreEqual(1, directors.Length); PlayableDirector pd = directors[0]; TimelineAsset timelineAsset = pd.playableAsset as TimelineAsset; Assert.IsNotNull(timelineAsset); Assert.AreEqual(timelineAsset.outputTrackCount, 1); foreach (TrackAsset trackAsset in timelineAsset.GetOutputTracks()) { StreamingImageSequenceTrack imageSequenceTrack = trackAsset as StreamingImageSequenceTrack; Assert.IsNotNull(imageSequenceTrack); foreach (TimelineClip clip in imageSequenceTrack.GetClips()) { Assert.IsNotNull(clip.asset); StreamingImageSequencePlayableAsset playableAsset = clip.asset as StreamingImageSequencePlayableAsset; Assert.IsNotNull(playableAsset); Assert.AreEqual(10, playableAsset.GetImageFileNames().Count); } //Make sure a StreamingImageSequenceRenderer is bound to the trackAsset StreamingImageSequenceRenderer r = pd.GetGenericBinding(trackAsset) as StreamingImageSequenceRenderer; Assert.IsNotNull(r); } //Delete created assets string destAssetsFolder = "Assets/" + destFolder; string[] createdAssets = AssetDatabase.FindAssets("", new[] { destAssetsFolder }); Assert.Greater(createdAssets.Length, 0); foreach (string guid in createdAssets) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); AssetDatabase.DeleteAsset(assetPath); } Directory.Delete(destAssetsFolder); }
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); }
//--------------------------------------------------------------------------------------------------------------------- /// <summary> /// Import a timeline file exported from DCC tools into the scene in the Timeline object /// </summary> /// <param name="jsTimelinePath">The path of the file</param> /// <param name="destFolder">The dest folder of the imported files</param> public static void ImportTimeline(string jsTimelinePath, string destFolder = "") { // prepare asset name, paths, etc string assetName = Path.GetFileNameWithoutExtension(jsTimelinePath); string timelineFolder = Path.GetDirectoryName(jsTimelinePath); if (string.IsNullOrEmpty(timelineFolder)) { Debug.LogError("Can't get directory name for: " + jsTimelinePath); return; } timelineFolder = Path.Combine(timelineFolder, destFolder, assetName).Replace("\\", "/"); //Check if we are exporting from external asset if (!timelineFolder.StartsWith("Assets/")) { timelineFolder = Path.Combine("Assets", destFolder, assetName); } Directory.CreateDirectory(timelineFolder); string strJson = File.ReadAllText(jsTimelinePath); TimelineParam container = JsonUtility.FromJson <TimelineParam>(strJson); string assetFolder = container.assetFolder; if (string.IsNullOrEmpty(assetFolder)) { assetFolder = Path.GetDirectoryName(jsTimelinePath); } //delete existing objects in the scene that is pointing to the Director string timelinePath = Path.Combine(timelineFolder, assetName + "_Timeline.playable").Replace("\\", "/"); PlayableDirector director = RemovePlayableFromDirectorsInScene(timelinePath); if (null == director) { GameObject directorGo = new GameObject(assetName); director = directorGo.AddComponent <PlayableDirector>(); } //Create timeline asset TimelineAsset asset = ScriptableObject.CreateInstance <TimelineAsset>(); AssetEditorUtility.OverwriteAsset(asset, timelinePath); director.playableAsset = asset; string strHome = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); int numTracks = container.Tracks.Length; for (int index = numTracks - 1; index >= 0; index--) { var track = container.Tracks[index]; string strFootagePath = track.Footage; // remove '~' if necessary if (strFootagePath.StartsWith("~")) { strFootagePath = strHome + strFootagePath.Substring(1); } if (!Path.IsPathRooted(strFootagePath)) { strFootagePath = Path.Combine(assetFolder, strFootagePath); } string strFootageName = Path.GetFileNameWithoutExtension(strFootagePath); string strJsonFootage = File.ReadAllText(strFootagePath); AEFootageInfo footageInfo = JsonUtility.FromJson <AEFootageInfo>(strJsonFootage); int numImages = footageInfo.Pictures.Count; if (numImages > 0) { List <string> originalImagePaths = new List <string>(footageInfo.Pictures); for (int xx = 0; xx < numImages; ++xx) { string fileName = footageInfo.Pictures[xx]; // replace '~' with the path to home (for Linux environment if (fileName.StartsWith("~")) { fileName = strHome + fileName.Substring(1); } footageInfo.Pictures[xx] = Path.GetFileName(fileName); } string destFootageFolder = Application.streamingAssetsPath; destFootageFolder = Path.Combine(destFootageFolder, strFootageName).Replace("\\", "/"); Directory.CreateDirectory(destFootageFolder); //make sure the directory exists footageInfo.Folder = AssetUtility.NormalizeAssetPath(destFootageFolder); for (int i = 0; i < numImages; ++i) { string destFilePath = Path.Combine(destFootageFolder, footageInfo.Pictures[i]); if (File.Exists(destFilePath)) { File.Delete(destFilePath); } string srcFilePath = Path.GetFullPath(Path.Combine(assetFolder, originalImagePaths[i])).Replace("\\", "/"); FileUtil.CopyFileOrDirectory(srcFilePath, destFilePath); } } //Convert to WatchedFileInfo List <WatchedFileInfo> imageFiles = WatchedFileInfo.CreateList(footageInfo.Folder, footageInfo.Pictures); StreamingImageSequencePlayableAsset sisAsset = ScriptableObject.CreateInstance <StreamingImageSequencePlayableAsset>(); sisAsset.InitFolder(footageInfo.Folder, imageFiles, footageInfo.Resolution); string playableAssetPath = Path.Combine(timelineFolder, strFootageName + "_StreamingImageSequence.playable"); AssetEditorUtility.OverwriteAsset(sisAsset, playableAssetPath); StreamingImageSequenceTrack movieTrack = asset.CreateTrack <StreamingImageSequenceTrack>(null, strFootageName); TimelineClip clip = movieTrack.CreateDefaultClip(); clip.asset = sisAsset; clip.start = track.Start; clip.duration = track.Duration; clip.CreateCurves("Curves: " + clip.displayName); TimelineClipSISData sisData = new TimelineClipSISData(clip); sisAsset.InitTimelineClipCurve(clip); sisAsset.BindTimelineClipSISData(sisData); if (Object.FindObjectOfType(typeof(UnityEngine.EventSystems.EventSystem)) == null) { var es = new GameObject(); es.AddComponent <UnityEngine.EventSystems.EventSystem>(); es.AddComponent <UnityEngine.EventSystems.StandaloneInputModule>(); es.name = "EventSystem"; } GameObject canvasObj = null; Canvas canvas = Object.FindObjectOfType(typeof(Canvas)) as Canvas; if (canvas != null) { canvasObj = canvas.gameObject; } else { canvasObj = UIUtility.CreateCanvas().gameObject; } Transform directorT = director.gameObject.transform; directorT.SetParent(canvasObj.transform); directorT.localPosition = new Vector3(0.0f, 0.0f, 0.0f); GameObject imageGo = null; Transform imageT = directorT.Find(strFootageName); if (null == imageT) { imageGo = new GameObject(strFootageName); imageT = imageGo.transform; } else { imageGo = imageT.gameObject; } Image image = imageGo.GetOrAddComponent <Image>(); StreamingImageSequenceRenderer renderer = imageGo.GetOrAddComponent <StreamingImageSequenceRenderer>(); RectTransform rectTransform = imageGo.GetComponent <RectTransform>(); rectTransform.SetParent(directorT); rectTransform.localPosition = new Vector3(0.0f, 0.0f, 0.0f); rectTransform.sizeDelta = new Vector2(footageInfo.Resolution.Width, footageInfo.Resolution.Height); director.SetGenericBinding(movieTrack, renderer); EditorUtility.SetDirty(director); } //cause crash if this is called inside of OnImportAsset() UnityEditor.EditorApplication.delayCall += () => { AssetDatabase.Refresh(); if (null != director) { Selection.activeGameObject = director.gameObject; } }; }
public IEnumerator UncheckFrameMarkers() { PlayableDirector director = EditorUtilityTest.NewSceneWithDirector(); TimelineClip clip = EditorUtilityTest.CreateTestTimelineClip(director); StreamingImageSequencePlayableAsset sisAsset = clip.asset as StreamingImageSequencePlayableAsset; Assert.IsNotNull(sisAsset); TimelineClipSISData timelineClipSISData = sisAsset.GetBoundTimelineClipSISData(); timelineClipSISData.RequestFrameMarkers(true); yield return(null); double timePerFrame = TimelineUtility.CalculateTimePerFrame(clip); int numImages = sisAsset.GetImageFileNames().Count; clip.timeScale = 3.75f; //use scaling EditorUtilityTest.ResizeSISTimelineClip(clip, (timePerFrame * numImages)); yield return(null); int numFrames = TimelineUtility.CalculateNumFrames(clip); Assert.AreEqual(numImages, numFrames); //Reset: make sure that the curve is a simple straight line from 0 to 1 StreamingImageSequencePlayableAsset.ResetTimelineClipCurve(clip); yield return(null); sisAsset.ResetPlayableFrames(); yield return(null); StreamingImageSequenceTrack track = clip.parentTrack as StreamingImageSequenceTrack; Assert.IsNotNull(track); List <FrameMarker> frameMarkers = new List <FrameMarker>(); int i = 0; foreach (var m in track.GetMarkers()) { FrameMarker marker = m as FrameMarker; Assert.IsNotNull(marker); frameMarkers.Add(marker); int imageIndex = sisAsset.GlobalTimeToImageIndex(clip, marker.time); Assert.AreEqual(i, imageIndex); ++i; } //Uncheck and see if the unchecked images became ignored frameMarkers[4].SetFrameUsed(false); frameMarkers[5].SetFrameUsed(false); Assert.AreEqual(3, sisAsset.GlobalTimeToImageIndex(clip, frameMarkers[4].time)); Assert.AreEqual(3, sisAsset.GlobalTimeToImageIndex(clip, frameMarkers[5].time)); frameMarkers[7].SetFrameUsed(false); frameMarkers[8].SetFrameUsed(false); Assert.AreEqual(6, sisAsset.GlobalTimeToImageIndex(clip, frameMarkers[7].time)); Assert.AreEqual(6, sisAsset.GlobalTimeToImageIndex(clip, frameMarkers[8].time)); EditorUtilityTest.DestroyTestTimelineAssets(clip); yield return(null); }