Skip to content

Commit 930662b

Browse files
authored
Merge pull request #309 from Unity-Technologies/Uni-35304-UnitTestsForExportingTimelineClip
Uni 35304 unit tests for exporting timeline clip
2 parents 47d0050 + b53ea2e commit 930662b

12 files changed

+855
-46
lines changed

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public class ModelExporter : System.IDisposable
8383
// being called only once regardless of what is selected.
8484
const string MenuItemName = "GameObject/Export Model...";
8585

86-
const string ClipMenuItemName = "GameObject/Export All Timeline Clips...";
86+
const string ClipMenuItemName = "GameObject/Export All Recorded Animation Clips...";
8787
const string TimelineClipMenuItemName = "GameObject/Export Selected Timeline Clip...";
8888

8989
const string AnimOnlyMenuItemName = "GameObject/Export Animation Only...";
@@ -2945,45 +2945,62 @@ private void ReplaceFile ()
29452945
}
29462946

29472947
/// <summary>
2948-
/// Add an option "Export selected Timeline clip" in the contextual GameObject menu.
2948+
/// GameObject/Export Selected Timeline Clip...
29492949
/// </summary>
2950-
[MenuItem(TimelineClipMenuItemName, false, 31)]
2950+
/// <param name="command"></param>
2951+
[MenuItem(TimelineClipMenuItemName, false, 31)]
29512952
static void OnClipContextClick(MenuCommand command)
29522953
{
2953-
var selectedObjects = Selection.objects;
2954-
foreach (var obj in selectedObjects)
2954+
// Now that we know we have stuff to export, get the user-desired path.
2955+
string directory = string.IsNullOrEmpty(LastFilePath)
2956+
? Application.dataPath
2957+
: System.IO.Path.GetDirectoryName(LastFilePath);
2958+
2959+
string title = "Select the folder in which the animation files from the timeline will be exported";
2960+
string folderPath = EditorUtility.SaveFolderPanel(title, directory, "");
2961+
2962+
if (string.IsNullOrEmpty(folderPath))
29552963
{
2956-
if (obj.GetType().Name.Contains("EditorClip"))
2957-
{
2958-
var timeLineClip = GetPropertyFromObject<TimelineClip> (obj, "clip");
2964+
return;
2965+
}
2966+
Debug.Log(folderPath);
29592967

2960-
var selClipItem = GetPropertyFromObject<object>(obj, "item");
2961-
var editorClipAnimationTrack = GetPropertyFromObject<AnimationTrack> (selClipItem, "parentTrack");
2968+
Object[] selectedObjects = Selection.objects;
29622969

2963-
GameObject animationTrackGObject = UnityEditor.Timeline.TimelineEditor.playableDirector.GetGenericBinding (editorClipAnimationTrack) as GameObject;
2970+
foreach (Object editorClipSelected in selectedObjects)
2971+
{
2972+
ExportSingleEditorClip(editorClipSelected, folderPath);
2973+
}
2974+
}
29642975

2965-
string filePath = GetExportFilePath (animationTrackGObject.name + "@" + timeLineClip.animationClip.name);
2966-
if (string.IsNullOrEmpty (filePath)) {
2967-
continue;
2968-
}
2976+
public static void ExportSingleEditorClip(Object editorClipSelected, string folderPath)
2977+
{
2978+
if (editorClipSelected.GetType().Name.Contains("EditorClip"))
2979+
{
2980+
object selClip = editorClipSelected.GetType().GetProperty("clip").GetValue(editorClipSelected, null);
2981+
UnityEngine.Timeline.TimelineClip timeLineClip = selClip as UnityEngine.Timeline.TimelineClip;
29692982

2970-
UnityEngine.Object[] myArray = new UnityEngine.Object[] { animationTrackGObject, timeLineClip.animationClip };
2983+
object selClipItem = editorClipSelected.GetType().GetProperty("item").GetValue(editorClipSelected, null);
2984+
object selClipItemParentTrack = selClipItem.GetType().GetProperty("parentTrack").GetValue(selClipItem, null);
2985+
AnimationTrack editorClipAnimationTrack = selClipItemParentTrack as AnimationTrack;
2986+
GameObject animationTrackGObject = UnityEditor.Timeline.TimelineEditor.playableDirector.GetGenericBinding (editorClipAnimationTrack) as GameObject;
29712987

2972-
ExportObjects (filePath, myArray, AnimationExportType.timelineAnimationClip);
2973-
return;
2974-
}
2975-
}
2988+
ExportSingleTimelineClip(timeLineClip, folderPath, animationTrackGObject);
2989+
}
29762990
}
29772991

2978-
private static T GetPropertyFromObject<T>(object obj, string propertyName) where T : class {
2979-
return obj.GetType ().GetProperty (propertyName).GetValue (obj, null) as T;
2992+
public static void ExportSingleTimelineClip(TimelineClip timelineClipSelected, string folderPath, GameObject animationTrackGObject)
2993+
{
2994+
string filePath = folderPath + "/" + animationTrackGObject.name + "@" + timelineClipSelected.animationClip.name + ".fbx";
2995+
UnityEngine.Object[] myArray = new UnityEngine.Object[] { animationTrackGObject, timelineClipSelected.animationClip };
2996+
ExportObjects(filePath, myArray, AnimationExportType.timelineAnimationClip);
29802997
}
29812998

29822999
/// <summary>
2983-
/// Add an option "Export all Timeline clips" in the contextual GameObject menu.
3000+
/// Add an option " GameObject/Export All Recorded Animation Clips..." in the contextual GameObject menu.
29843001
/// </summary>
29853002
[MenuItem(ClipMenuItemName, false, 31)]
2986-
static void OnGameObjectWithTimelineContextClick(MenuCommand command)
3003+
public static void OnPlayableDirectorGameObjectContextClick(MenuCommand command)
29873004
{
29883005
// Now that we know we have stuff to export, get the user-desired path.
29893006
string directory = string.IsNullOrEmpty(LastFilePath)
@@ -3008,31 +3025,38 @@ static void OnGameObjectWithTimelineContextClick(MenuCommand command)
30083025
else
30093026
{
30103027
// We were invoked from the right-click menu, so use the context of the context menu.
3011-
var selected = command.context as GameObject;
3028+
GameObject selected = command.context as GameObject;
30123029
if (selected)
30133030
{
30143031
selection = new GameObject[] { selected };
30153032
}
30163033
}
30173034

3018-
foreach (GameObject obj in selection)
3035+
foreach (GameObject objectWithPlayableDirector in selection)
30193036
{
3020-
PlayableDirector pd = obj.GetComponent<PlayableDirector>();
3021-
if (pd != null)
3022-
{
3023-
foreach (PlayableBinding output in pd.playableAsset.outputs)
3024-
{
3025-
AnimationTrack at = output.sourceObject as AnimationTrack;
3037+
ExportAllTimelineClips(objectWithPlayableDirector,folderPath);
3038+
}
3039+
}
30263040

3027-
GameObject atObject = pd.GetGenericBinding(output.sourceObject) as GameObject;
3028-
// One file by animation clip
3029-
foreach (TimelineClip timeLineClip in at.GetClips()) {
3030-
string filePath = string.Format(AnimFbxFileFormat, folderPath, atObject.name, timeLineClip.animationClip.name);
3031-
UnityEngine.Object[] myArray = new UnityEngine.Object[] { atObject, timeLineClip.animationClip };
3032-
ExportObjects (filePath, myArray, AnimationExportType.timelineAnimationClip);
3041+
public static void ExportAllTimelineClips(GameObject objectWithPlayableDirector, string folderPath)
3042+
{
3043+
Debug.Log(objectWithPlayableDirector.GetType().BaseType.ToString() + ":" + objectWithPlayableDirector.name);
30333044

3034-
}
3035-
}
3045+
PlayableDirector pd = objectWithPlayableDirector.GetComponent<PlayableDirector>();
3046+
if (pd != null)
3047+
{
3048+
foreach (PlayableBinding output in pd.playableAsset.outputs)
3049+
{
3050+
AnimationTrack at = output.sourceObject as AnimationTrack;
3051+
3052+
GameObject atObject = pd.GetGenericBinding(output.sourceObject) as GameObject;
3053+
// One file by animation clip
3054+
foreach(TimelineClip timeLineClip in at.GetClips())
3055+
{
3056+
string filePath = folderPath + "/" + atObject.name + "@" + timeLineClip.animationClip.name + ".fbx";
3057+
UnityEngine.Object[] myArray = new UnityEngine.Object[] { atObject, timeLineClip.animationClip };
3058+
ExportObjects(filePath, myArray, AnimationExportType.timelineAnimationClip);
3059+
}
30363060
}
30373061
}
30383062
}
@@ -3581,7 +3605,6 @@ private static string GetExportFilePath(string filenameSuggestion = ""){
35813605

35823606
private static void OnExport (AnimationExportType exportType = AnimationExportType.all)
35833607
{
3584-
35853608
// Now that we know we have stuff to export, get the user-desired path.
35863609
GameObject [] selectedGOs = Selection.GetFiltered<GameObject> (SelectionMode.TopLevel);
35873610
string filename = null;
@@ -3610,6 +3633,7 @@ private static void OnExport (AnimationExportType exportType = AnimationExportTy
36103633
/// Export a list of (Game) objects to FBX file.
36113634
/// Use the SaveFile panel to allow user to enter a file name.
36123635
/// <summary>
3636+
//public static string ExportObjects (string filePath, UnityEngine.Object[] objects = null, AnimationExportType exportType = AnimationExportType.all /*, bool animOnly = false*/)
36133637
public static string ExportObjects (
36143638
string filePath,
36153639
UnityEngine.Object[] objects = null,
@@ -3666,6 +3690,7 @@ public static string ExportObjects (
36663690
return null;
36673691
}
36683692

3693+
//public static string ExportObject (string filePath, UnityEngine.Object root, AnimationExportType exportType = AnimationExportType.all /*, bool animOnly = false*/)
36693694
public static string ExportObject (
36703695
string filePath, UnityEngine.Object root,
36713696
AnimationExportType exportType = AnimationExportType.all,
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using UnityEngine;
2+
using UnityEditor;
3+
using NUnit.Framework;
4+
using FbxExporters.Editor;
5+
using UnityEngine.Timeline;
6+
using UnityEngine.Playables;
7+
using UnityEditor.SceneManagement;
8+
9+
namespace FbxExporters.UnitTests
10+
{
11+
public class ExportTimelineClipTest : ExporterTestBase
12+
{
13+
private static string m_testScenePath = "Scene/TestScene.unity";
14+
15+
[SetUp]
16+
public override void Init()
17+
{
18+
base.Init ();
19+
string testScenePath = FindPathInUnitTests (m_testScenePath);
20+
Assert.That (testScenePath, Is.Not.Null);
21+
EditorSceneManager.OpenScene("Assets/" + testScenePath);
22+
}
23+
24+
[Test]
25+
public void ExportSingleTimelineClipTest()
26+
{
27+
GameObject myCube = GameObject.Find("CubeSpecial");
28+
string folderPath = GetRandomFileNamePath(extName: "");
29+
30+
PlayableDirector pd = myCube.GetComponent<PlayableDirector> ();
31+
if (pd != null) {
32+
foreach (PlayableBinding output in pd.playableAsset.outputs) {
33+
AnimationTrack at = output.sourceObject as AnimationTrack;
34+
35+
GameObject atObject = pd.GetGenericBinding (output.sourceObject) as GameObject;
36+
// One file by animation clip
37+
foreach (TimelineClip timeLineClip in at.GetClips()) {
38+
ModelExporter.ExportSingleTimelineClip (timeLineClip, folderPath, atObject);
39+
FileAssert.Exists (string.Format("{0}/{1}@{2}", folderPath, atObject.name, "Recorded.fbx"));
40+
}
41+
}
42+
}
43+
}
44+
45+
[Test]
46+
public void ExportAllTimelineClipTest()
47+
{
48+
GameObject myCube = GameObject.Find("CubeSpecial");
49+
Selection.objects = new UnityEngine.GameObject[] { myCube };
50+
string folderPath = GetRandomFileNamePath(extName: "");
51+
52+
foreach(GameObject obj in Selection.objects)
53+
{
54+
ModelExporter.ExportAllTimelineClips(obj, folderPath);
55+
FileAssert.Exists(string.Format("{0}/{1}@{2}", folderPath, obj.name, "Recorded.fbx"));
56+
}
57+
}
58+
}
59+
}

Assets/FbxExporters/Editor/UnitTests/ExportTimelineClipTest.cs.meta

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/FbxExporters/Editor/UnitTests/ExporterTestBase.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ void DeleteOnNextUpdate()
194194
[TearDown]
195195
public virtual void Term ()
196196
{
197+
// Put back the initial setting for the auto-updater toggle
198+
FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled = isAutoUpdaterOn;
199+
197200
if (string.IsNullOrEmpty(_testDirectory)) {
198201
return;
199202
}
@@ -213,7 +216,6 @@ public virtual void Init()
213216
FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled = true;
214217
}
215218

216-
217219
/// <summary>
218220
/// Exports the Objects in selected.
219221
/// </summary>

Assets/FbxExporters/Editor/UnitTests/FbxAnimationTest.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,9 @@ public void AnimOnlyExportTest(string prefabPath)
834834

835835
// export fbx
836836
// get GameObject
837-
string filename = ExportToFbx(originalGO, true);
837+
string filename = GetRandomFbxFilePath ();
838+
var exportedFilePath = ModelExporter.ExportObject (filename, originalGO, ModelExporter.AnimationExportType.componentAnimation);
839+
Assert.That (exportedFilePath, Is.EqualTo (filename));
838840

839841
GameObject fbxObj = AssetDatabase.LoadMainAssetAtPath (filename) as GameObject;
840842
Assert.IsTrue (fbxObj);

Assets/FbxExporters/Editor/UnitTests/FbxCameraTests.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/FbxExporters/Editor/UnitTests/FbxPrefabAutoUpdaterTest.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,11 @@ public void TestNameMapping()
159159
// In FbxPrefab Component of Cube, add SphereFBX/Sphere name mapping
160160
FbxPrefab fbxPrefabScript = cubePrefabInstance.transform.GetComponent<FbxPrefab>();
161161

162-
163162
FbxPrefab.StringPair stringpair = new FbxPrefab.StringPair();
164163
stringpair.FBXObjectName = "SphereFBX";
165164
stringpair.UnityObjectName = "Sphere";
166165
fbxPrefabScript.NameMapping.Add(stringpair);
167166

168-
169167
FbxPrefabAutoUpdater.FbxPrefabUtility fbxPrefabUtility = new FbxPrefabAutoUpdater.FbxPrefabUtility(fbxPrefabScript);
170168

171169
Assert.IsTrue(fbxPrefabUtility.GetUnityObjectName("SphereFBX") == stringpair.UnityObjectName);
@@ -329,7 +327,7 @@ public void RemappingTest()
329327

330328

331329
[TearDown]
332-
public void stopTest()
330+
public void StopTest()
333331
{
334332
// Put back the initial setting for the auto-updater toggle
335333
FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled = isAutoUpdaterOn;

Assets/FbxExporters/Editor/UnitTests/Scene.meta

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)