@@ -93,6 +93,12 @@ public static IEnumerable BlendShapeTestCases {
93
93
yield return "Models/blendshape_with_skinning.fbx" ;
94
94
}
95
95
}
96
+
97
+ public static IEnumerable AnimOnlyTestCaases {
98
+ get {
99
+ yield return new TestCaseData ( "Models/DefaultMale/DefaultMale.prefab" ) ;
100
+ }
101
+ }
96
102
}
97
103
98
104
[ TestFixture ]
@@ -477,14 +483,42 @@ public int Main (KeyData keyData, string testName, string path)
477
483
478
484
public static void ClipPropertyTest ( AnimationClip animClipExpected , AnimationClip animClipActual )
479
485
{
480
- // TODO: figure out why we get __preview__ on Windows
481
- Assert . That ( animClipActual . name , Is . EqualTo ( animClipExpected . name ) . Or . EqualTo ( "__preview__" + animClipExpected . name ) ) ;
486
+ Assert . That ( animClipActual . name , Is . EqualTo ( animClipExpected . name ) . Or . EqualTo ( animClipExpected . name ) ) ;
482
487
Assert . That ( animClipActual . legacy , Is . EqualTo ( animClipExpected . legacy ) ) ;
483
488
Assert . That ( animClipActual . isLooping , Is . EqualTo ( animClipExpected . isLooping ) ) ;
484
489
Assert . That ( animClipActual . wrapMode , Is . EqualTo ( animClipExpected . wrapMode ) ) ;
485
490
486
491
// TODO: Uni-34489
487
- Assert . That ( animClipActual . length , Is . EqualTo ( animClipExpected . length ) . Within ( Mathf . Epsilon ) , "animClip length doesn't match" ) ;
492
+ Assert . That ( animClipActual . length , Is . EqualTo ( animClipExpected . length ) . Within ( 0.0001f ) , "animClip length doesn't match" ) ;
493
+ }
494
+
495
+ /// <summary>
496
+ /// Compares the properties and curves of two animation clips.
497
+ /// </summary>
498
+ /// <param name="animClipOriginal">Animation clip original.</param>
499
+ /// <param name="animClipImported">Animation clip imported.</param>
500
+ public static void ClipTest ( AnimationClip animClipOriginal , AnimationClip animClipImported ) {
501
+ // check clip properties match
502
+ AnimTester . ClipPropertyTest ( animClipOriginal , animClipImported ) ;
503
+
504
+ foreach ( EditorCurveBinding curveBinding in AnimationUtility . GetCurveBindings ( animClipOriginal ) ) {
505
+ foreach ( EditorCurveBinding impCurveBinding in AnimationUtility . GetCurveBindings ( animClipImported ) ) {
506
+
507
+ // only compare if the path and property names match
508
+ if ( curveBinding . path != impCurveBinding . path || curveBinding . propertyName != impCurveBinding . propertyName ) {
509
+ continue ;
510
+ }
511
+
512
+ AnimationCurve animCurveOrig = AnimationUtility . GetEditorCurve ( animClipOriginal , curveBinding ) ;
513
+ Assert . That ( animCurveOrig , Is . Not . Null ) ;
514
+
515
+ AnimationCurve animCurveImported = AnimationUtility . GetEditorCurve ( animClipImported , impCurveBinding ) ;
516
+ Assert . That ( animCurveImported , Is . Not . Null ) ;
517
+
518
+ AnimTester . KeyValuesTest ( animCurveImported , animCurveOrig ,
519
+ string . Format ( "path: {0}, property: {1}" , curveBinding . path , curveBinding . propertyName ) ) ;
520
+ }
521
+ }
488
522
}
489
523
490
524
public static void KeysTest ( AnimationCurve expectedAnimCurve , AnimationCurve actualAnimCurve , string message , IComparer < Keyframe > keyComparer = null )
@@ -568,6 +602,28 @@ public static void CurveTest(AnimationCurve animCurveImported, AnimationCurve an
568
602
Assert . That ( actualValueKeys , Is . EqualTo ( importedValueKeys ) , string . Format ( "{0} key value doesn't match" , message ) ) ;
569
603
}
570
604
605
+
606
+ public static Dictionary < string , AnimationClip > GetClipsFromFbx ( string path , bool setLegacy = false ) {
607
+ //acquire imported object from exported file
608
+ Object [ ] goAssetImported = AssetDatabase . LoadAllAssetsAtPath ( path ) ;
609
+ Assert . That ( goAssetImported , Is . Not . Null ) ;
610
+
611
+ // TODO : configure object so that it imports w Legacy Animation
612
+
613
+ var animClips = new Dictionary < string , AnimationClip > ( ) ;
614
+ foreach ( Object o in goAssetImported ) {
615
+ var animClipImported = o as AnimationClip ;
616
+ if ( animClipImported && ! animClipImported . name . StartsWith ( "__preview__" ) ) {
617
+ // TODO : configure import settings so we don't need to force legacy
618
+ animClipImported . legacy = setLegacy ;
619
+ animClips . Add ( animClipImported . name , animClipImported ) ;
620
+ }
621
+ }
622
+ Assert . That ( animClips , Is . Not . Empty , "expected imported clips" ) ;
623
+
624
+ return animClips ;
625
+ }
626
+
571
627
public static AnimationClip GetClipFromFbx ( string path ) {
572
628
//acquire imported object from exported file
573
629
Object [ ] goAssetImported = AssetDatabase . LoadAllAssetsAtPath ( path ) ;
@@ -578,7 +634,7 @@ public static AnimationClip GetClipFromFbx(string path){
578
634
AnimationClip animClipImported = null ;
579
635
foreach ( Object o in goAssetImported ) {
580
636
animClipImported = o as AnimationClip ;
581
- if ( animClipImported ) break ;
637
+ if ( animClipImported && ! animClipImported . name . StartsWith ( "__preview__" ) ) break ;
582
638
}
583
639
Assert . That ( animClipImported , Is . Not . Null , "expected imported clip" ) ;
584
640
@@ -618,28 +674,7 @@ public void LegacySkinnedMeshAnimTest (string fbxPath)
618
674
619
675
var animClipImported = AnimTester . GetClipFromFbx ( filename ) ;
620
676
621
- // check clip properties match
622
- AnimTester . ClipPropertyTest ( animClipOriginal , animClipImported ) ;
623
-
624
- foreach ( EditorCurveBinding curveBinding in AnimationUtility . GetCurveBindings ( animClipOriginal ) ) {
625
- foreach ( EditorCurveBinding impCurveBinding in AnimationUtility . GetCurveBindings ( animClipImported ) ) {
626
-
627
- // only compare if the path and property names match
628
- if ( curveBinding . path != impCurveBinding . path || curveBinding . propertyName != impCurveBinding . propertyName ) {
629
- continue ;
630
- }
631
-
632
- AnimationCurve animCurveOrig = AnimationUtility . GetEditorCurve ( animClipOriginal , curveBinding ) ;
633
- Assert . That ( animCurveOrig , Is . Not . Null ) ;
634
-
635
- AnimationCurve animCurveImported = AnimationUtility . GetEditorCurve ( animClipImported , impCurveBinding ) ;
636
- Assert . That ( animCurveImported , Is . Not . Null ) ;
637
-
638
- AnimTester . CurveTest ( animCurveImported , animCurveOrig , curveBinding . propertyName ) ;
639
- }
640
- }
641
-
642
-
677
+ AnimTester . ClipTest ( animClipOriginal , animClipImported ) ;
643
678
}
644
679
645
680
[ Test , TestCaseSource ( typeof ( AnimationTestDataClass ) , "TransformIndependantComponentTestCases" ) ]
@@ -764,5 +799,94 @@ public int ComponentAnimTest (System.Type componentType)
764
799
var tester = new AnimTester { keyData = keyData , testName = testName , path = GetRandomFbxFilePath ( ) } ;
765
800
return tester . DoIt ( ) <= propertyNames . Length ? 1 : 0 ;
766
801
}
802
+
803
+ [ Test , TestCaseSource ( typeof ( AnimationTestDataClass ) , "AnimOnlyTestCaases" ) ]
804
+ public void AnimOnlyExportTest ( string prefabPath )
805
+ {
806
+ prefabPath = FindPathInUnitTests ( prefabPath ) ;
807
+ Assert . That ( prefabPath , Is . Not . Null ) ;
808
+
809
+ // add prefab to scene
810
+ GameObject originalObj = AssetDatabase . LoadMainAssetAtPath ( "Assets/" + prefabPath ) as GameObject ;
811
+ Assert . IsNotNull ( originalObj ) ;
812
+ GameObject originalGO = GameObject . Instantiate ( originalObj ) ;
813
+ Assert . IsTrue ( originalGO ) ;
814
+
815
+ // get clips
816
+ var animator = originalGO . GetComponentInChildren < Animator > ( ) ;
817
+ Assert . That ( animator , Is . Not . Null ) ;
818
+
819
+ var controller = animator . runtimeAnimatorController ;
820
+ Assert . That ( controller , Is . Not . Null ) ;
821
+
822
+ var animClips = controller . animationClips ;
823
+ Assert . That ( animClips , Is . Not . Null ) ;
824
+
825
+ // get the set of GameObject transforms to be exported with the clip
826
+ var animatedObjects = GetAnimatedGameObjects ( animClips , animator . gameObject ) ;
827
+
828
+ // export fbx
829
+ // get GameObject
830
+ string filename = GetRandomFbxFilePath ( ) ;
831
+ var exportedFilePath = ModelExporter . ExportObject ( filename , originalGO , animOnly : true ) ;
832
+ Assert . That ( exportedFilePath , Is . EqualTo ( filename ) ) ;
833
+
834
+ GameObject fbxObj = AssetDatabase . LoadMainAssetAtPath ( filename ) as GameObject ;
835
+ Assert . IsTrue ( fbxObj ) ;
836
+
837
+ // compare hierarchy matches animated objects
838
+ var s = new Stack < Transform > ( ) ;
839
+
840
+ // don't check the root since it probably won't have the same name anyway
841
+ foreach ( Transform child in fbxObj . transform ) {
842
+ s . Push ( child ) ;
843
+ }
844
+ while ( s . Count > 0 ) {
845
+ var transform = s . Pop ( ) ;
846
+
847
+ Assert . That ( animatedObjects . Contains ( transform . name ) ) ;
848
+ animatedObjects . Remove ( transform . name ) ;
849
+
850
+ foreach ( Transform child in transform ) {
851
+ s . Push ( child ) ;
852
+ }
853
+ }
854
+
855
+ // compare clips
856
+ var fbxAnimClips = AnimTester . GetClipsFromFbx ( filename ) ;
857
+ Assert . That ( fbxAnimClips . Count , Is . EqualTo ( animClips . Count ( ) ) ) ;
858
+
859
+ foreach ( var clip in animClips ) {
860
+ Assert . That ( fbxAnimClips . ContainsKey ( clip . name ) ) ;
861
+ var fbxClip = fbxAnimClips [ clip . name ] ;
862
+ AnimTester . ClipTest ( clip , fbxClip ) ;
863
+ }
864
+ }
865
+
866
+ private HashSet < string > GetAnimatedGameObjects ( AnimationClip [ ] animClips , GameObject animatorObject ) {
867
+ var animatedObjects = new HashSet < string > ( ) ;
868
+ foreach ( var clip in animClips ) {
869
+ foreach ( EditorCurveBinding uniCurveBinding in AnimationUtility . GetCurveBindings ( clip ) ) {
870
+ Object uniObj = AnimationUtility . GetAnimatedObject ( animatorObject , uniCurveBinding ) ;
871
+ if ( ! uniObj ) {
872
+ continue ;
873
+ }
874
+
875
+ GameObject unityGo = ModelExporter . GetGameObject ( uniObj ) ;
876
+ if ( ! unityGo ) {
877
+ continue ;
878
+ }
879
+
880
+ // also it's parents up until but excluding the root (the root will have a different name)
881
+ var parent = unityGo . transform ;
882
+ while ( parent != null && parent . parent != null ) {
883
+ animatedObjects . Add ( parent . name ) ;
884
+ parent = parent . parent ;
885
+ }
886
+
887
+ }
888
+ }
889
+ return animatedObjects ;
890
+ }
767
891
}
768
892
}
0 commit comments