@@ -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,8 +483,7 @@ 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 ) ) ;
@@ -568,6 +573,28 @@ public static void CurveTest(AnimationCurve animCurveImported, AnimationCurve an
568
573
Assert . That ( actualValueKeys , Is . EqualTo ( importedValueKeys ) , string . Format ( "{0} key value doesn't match" , message ) ) ;
569
574
}
570
575
576
+
577
+ public static Dictionary < string , AnimationClip > GetClipsFromFbx ( string path , bool setLegacy = false ) {
578
+ //acquire imported object from exported file
579
+ Object [ ] goAssetImported = AssetDatabase . LoadAllAssetsAtPath ( path ) ;
580
+ Assert . That ( goAssetImported , Is . Not . Null ) ;
581
+
582
+ // TODO : configure object so that it imports w Legacy Animation
583
+
584
+ var animClips = new Dictionary < string , AnimationClip > ( ) ;
585
+ foreach ( Object o in goAssetImported ) {
586
+ var animClipImported = o as AnimationClip ;
587
+ if ( animClipImported && ! animClipImported . name . StartsWith ( "__preview__" ) ) {
588
+ // TODO : configure import settings so we don't need to force legacy
589
+ animClipImported . legacy = setLegacy ;
590
+ animClips . Add ( animClipImported . name , animClipImported ) ;
591
+ }
592
+ }
593
+ Assert . That ( animClips , Is . Not . Empty , "expected imported clips" ) ;
594
+
595
+ return animClips ;
596
+ }
597
+
571
598
public static AnimationClip GetClipFromFbx ( string path ) {
572
599
//acquire imported object from exported file
573
600
Object [ ] goAssetImported = AssetDatabase . LoadAllAssetsAtPath ( path ) ;
@@ -578,7 +605,7 @@ public static AnimationClip GetClipFromFbx(string path){
578
605
AnimationClip animClipImported = null ;
579
606
foreach ( Object o in goAssetImported ) {
580
607
animClipImported = o as AnimationClip ;
581
- if ( animClipImported ) break ;
608
+ if ( animClipImported && ! animClipImported . name . StartsWith ( "__preview__" ) ) break ;
582
609
}
583
610
Assert . That ( animClipImported , Is . Not . Null , "expected imported clip" ) ;
584
611
@@ -638,8 +665,6 @@ public void LegacySkinnedMeshAnimTest (string fbxPath)
638
665
AnimTester . CurveTest ( animCurveImported , animCurveOrig , curveBinding . propertyName ) ;
639
666
}
640
667
}
641
-
642
-
643
668
}
644
669
645
670
[ Test , TestCaseSource ( typeof ( AnimationTestDataClass ) , "TransformIndependantComponentTestCases" ) ]
@@ -764,5 +789,114 @@ public int ComponentAnimTest (System.Type componentType)
764
789
var tester = new AnimTester { keyData = keyData , testName = testName , path = GetRandomFbxFilePath ( ) } ;
765
790
return tester . DoIt ( ) <= propertyNames . Length ? 1 : 0 ;
766
791
}
792
+
793
+ [ Test , TestCaseSource ( typeof ( AnimationTestDataClass ) , "AnimOnlyTestCaases" ) ]
794
+ public void AnimOnlyExportTest ( string prefabPath )
795
+ {
796
+ prefabPath = FindPathInUnitTests ( prefabPath ) ;
797
+ Assert . That ( prefabPath , Is . Not . Null ) ;
798
+
799
+ // add prefab to scene
800
+ GameObject originalObj = AssetDatabase . LoadMainAssetAtPath ( "Assets/" + prefabPath ) as GameObject ;
801
+ Assert . IsNotNull ( originalObj ) ;
802
+ GameObject originalGO = GameObject . Instantiate ( originalObj ) ;
803
+ Assert . IsTrue ( originalGO ) ;
804
+
805
+ // get clips
806
+ var animator = originalGO . GetComponentInChildren < Animator > ( ) ;
807
+ Assert . That ( animator , Is . Not . Null ) ;
808
+
809
+ var controller = animator . runtimeAnimatorController ;
810
+ Assert . That ( controller , Is . Not . Null ) ;
811
+
812
+ var animClips = controller . animationClips ;
813
+ Assert . That ( animClips , Is . Not . Null ) ;
814
+
815
+ // get the set of GameObject transforms to be exported with the clip
816
+ var animatedObjects = GetAnimatedGameObjects ( animClips , animator . gameObject ) ;
817
+
818
+ // export fbx
819
+ // get GameObject
820
+ string filename = GetRandomFbxFilePath ( ) ;
821
+ var exportedFilePath = ModelExporter . ExportObject ( filename , originalGO , animOnly : true ) ;
822
+ Assert . That ( exportedFilePath , Is . EqualTo ( filename ) ) ;
823
+
824
+ GameObject fbxObj = AssetDatabase . LoadMainAssetAtPath ( filename ) as GameObject ;
825
+ Assert . IsTrue ( fbxObj ) ;
826
+
827
+ // compare hierarchy matches animated objects
828
+ var s = new Stack < Transform > ( ) ;
829
+
830
+ // don't check the root since it probably won't have the same name anyway
831
+ foreach ( Transform child in fbxObj . transform ) {
832
+ s . Push ( child ) ;
833
+ }
834
+ while ( s . Count > 0 ) {
835
+ var transform = s . Pop ( ) ;
836
+
837
+ Assert . That ( animatedObjects . Contains ( transform . name ) ) ;
838
+ animatedObjects . Remove ( transform . name ) ;
839
+
840
+ foreach ( Transform child in transform ) {
841
+ s . Push ( child ) ;
842
+ }
843
+ }
844
+
845
+ // compare clips
846
+ var fbxAnimClips = AnimTester . GetClipsFromFbx ( filename ) ;
847
+ Assert . That ( fbxAnimClips . Count , Is . EqualTo ( animClips . Count ( ) ) ) ;
848
+
849
+ foreach ( var clip in animClips ) {
850
+ Assert . That ( fbxAnimClips . ContainsKey ( clip . name ) ) ;
851
+
852
+ var fbxClip = fbxAnimClips [ clip . name ] ;
853
+
854
+ AnimTester . ClipPropertyTest ( clip , fbxClip ) ;
855
+
856
+ foreach ( EditorCurveBinding curveBinding in AnimationUtility . GetCurveBindings ( clip ) ) {
857
+ foreach ( EditorCurveBinding impCurveBinding in AnimationUtility . GetCurveBindings ( fbxClip ) ) {
858
+
859
+ // only compare if the path and property names match
860
+ if ( curveBinding . path != impCurveBinding . path || curveBinding . propertyName != impCurveBinding . propertyName ) {
861
+ continue ;
862
+ }
863
+
864
+ AnimationCurve animCurveOrig = AnimationUtility . GetEditorCurve ( clip , curveBinding ) ;
865
+ Assert . That ( animCurveOrig , Is . Not . Null ) ;
866
+
867
+ AnimationCurve animCurveImported = AnimationUtility . GetEditorCurve ( fbxClip , impCurveBinding ) ;
868
+ Assert . That ( animCurveImported , Is . Not . Null ) ;
869
+
870
+ AnimTester . CurveTest ( animCurveImported , animCurveOrig , curveBinding . propertyName ) ;
871
+ }
872
+ }
873
+ }
874
+ }
875
+
876
+ private HashSet < string > GetAnimatedGameObjects ( AnimationClip [ ] animClips , GameObject animatorObject ) {
877
+ var animatedObjects = new HashSet < string > ( ) ;
878
+ foreach ( var clip in animClips ) {
879
+ foreach ( EditorCurveBinding uniCurveBinding in AnimationUtility . GetCurveBindings ( clip ) ) {
880
+ Object uniObj = AnimationUtility . GetAnimatedObject ( animatorObject , uniCurveBinding ) ;
881
+ if ( ! uniObj ) {
882
+ continue ;
883
+ }
884
+
885
+ GameObject unityGo = ModelExporter . GetGameObject ( uniObj ) ;
886
+ if ( ! unityGo ) {
887
+ continue ;
888
+ }
889
+
890
+ // also it's parents up until but excluding the root (the root will have a different name)
891
+ var parent = unityGo . transform ;
892
+ while ( parent != null && parent . parent != null ) {
893
+ animatedObjects . Add ( parent . name ) ;
894
+ parent = parent . parent ;
895
+ }
896
+
897
+ }
898
+ }
899
+ return animatedObjects ;
900
+ }
767
901
}
768
902
}
0 commit comments