3
3
using UnityEngine . TestTools ;
4
4
using NUnit . Framework ;
5
5
using System . Collections . Generic ;
6
+ using System . Linq ;
6
7
7
8
namespace FbxExporters . UnitTests
8
9
{
@@ -12,6 +13,8 @@ public class FbxPrefabTest : ExporterTestBase
12
13
FbxPrefab . FbxRepresentation m_originalRep ;
13
14
14
15
GameObject m_source ; // the fbx model
16
+ FbxPrefab . FbxRepresentation m_originalHistory ;
17
+
15
18
GameObject m_autoPrefab ; // prefab that auto-updates
16
19
GameObject m_manualPrefab ; // prefab that doesn't auto-update
17
20
@@ -49,61 +52,87 @@ void OnUpdate(FbxPrefab prefabInstance, IEnumerable<GameObject> updated)
49
52
}
50
53
}
51
54
55
+ static KeyValuePair < string , FbxPrefab . FbxRepresentation > StackItem (
56
+ string name , FbxPrefab . FbxRepresentation rep )
57
+ {
58
+ return new KeyValuePair < string , FbxPrefab . FbxRepresentation > ( name , rep ) ;
59
+ }
60
+
52
61
public static void AssertAreIdentical (
53
62
FbxPrefab . FbxRepresentation a ,
54
63
FbxPrefab . FbxRepresentation b ) {
55
64
// A bit of a laborious comparison scheme. This is due to the
56
65
// round-trip through FBX causing tiny errors in the transforms.
57
- var astack = new List < FbxPrefab . FbxRepresentation > ( ) ;
58
- astack . Add ( a ) ;
59
- var bstack = new List < FbxPrefab . FbxRepresentation > ( ) ;
60
- bstack . Add ( b ) ;
66
+ var astack = new List < KeyValuePair < string , FbxPrefab . FbxRepresentation > > ( ) ;
67
+ astack . Add ( StackItem ( "(root)" , a ) ) ;
68
+ var bstack = new List < KeyValuePair < string , FbxPrefab . FbxRepresentation > > ( ) ;
69
+ bstack . Add ( StackItem ( "(root)" , b ) ) ;
61
70
62
71
var aDummy = new GameObject ( "aDummy" ) . transform ;
63
72
var bDummy = new GameObject ( "bDummy" ) . transform ;
64
73
while ( astack . Count > 0 ) {
65
74
Assert . AreEqual ( astack . Count , bstack . Count ) ; // should never fail
66
- a = astack [ astack . Count - 1 ] ; astack . RemoveAt ( astack . Count - 1 ) ;
67
- b = bstack [ bstack . Count - 1 ] ; bstack . RemoveAt ( bstack . Count - 1 ) ;
75
+ var aKvp = astack [ astack . Count - 1 ] ; astack . RemoveAt ( astack . Count - 1 ) ;
76
+ var bKvp = bstack [ bstack . Count - 1 ] ; bstack . RemoveAt ( bstack . Count - 1 ) ;
77
+
78
+ var aName = aKvp . Key ;
79
+ var bName = bKvp . Key ;
80
+ Assert . AreEqual ( aName , bName ) ;
81
+
82
+ a = aKvp . Value ;
83
+ b = bKvp . Value ;
68
84
69
85
// Verify that they have the same children (by name).
70
86
var achildren = a . ChildNames ;
71
87
var bchildren = b . ChildNames ;
72
- Assert . That ( achildren , Is . EquivalentTo ( bchildren ) ) ;
88
+ Assert . That ( bchildren , Is . EquivalentTo ( achildren ) , aName + " children" ) ;
73
89
74
- // Add the children to each stack.
90
+ // Add the children to each stack. It's important to get the
91
+ // same order for both stacks.
75
92
foreach ( var child in achildren ) {
76
- astack . Add ( a . GetChild ( child ) ) ;
77
- bstack . Add ( b . GetChild ( child ) ) ;
93
+ astack . Add ( StackItem ( child , a . GetChild ( child ) ) ) ;
94
+ bstack . Add ( StackItem ( child , b . GetChild ( child ) ) ) ;
78
95
}
79
96
80
97
// Verify that they have the same components.
81
98
var atypes = a . ComponentTypes ;
82
99
var btypes = b . ComponentTypes ;
83
- Assert . That ( atypes , Is . EquivalentTo ( btypes ) ) ;
100
+
101
+ Assert . That ( btypes , Is . EquivalentTo ( atypes ) , aName + " component types" ) ;
84
102
85
103
foreach ( var t in atypes ) {
86
104
var avalues = a . GetComponentValues ( t ) ;
87
105
var bvalues = b . GetComponentValues ( t ) ;
88
- Assert . AreEqual ( avalues . Count , bvalues . Count ) ;
89
-
90
- if ( t != "UnityEngine.Transform" ) {
91
- Assert . AreEqual ( avalues , bvalues ) ;
92
- } else {
106
+ Assert . AreEqual ( avalues . Count , bvalues . Count , aName + " component multiplicity" ) ;
107
+
108
+ //
109
+ // TODO: test that the values match up.
110
+ // Exceptions:
111
+ // - Transforms we expect small changes.
112
+ // - MeshFilter and MeshRenderer we expect guids to change
113
+ //
114
+ if ( t == "UnityEngine.MeshFilter" ) {
115
+ // TODO: test that everything but the guid matches
116
+ } else if ( t == "UnityEngine.MeshRenderer" ) {
117
+ // TODO: test that everything but the guid matches
118
+ } else if ( t == "UnityEngine.Transform" ) {
93
119
// Verify that the transforms are nearly (but don't require bitwise) equal.
94
120
EditorJsonUtility . FromJsonOverwrite ( avalues [ 0 ] , aDummy ) ;
95
121
EditorJsonUtility . FromJsonOverwrite ( bvalues [ 0 ] , bDummy ) ;
96
122
var dist = Vector3 . Distance ( aDummy . localPosition , bDummy . localPosition ) ;
97
- Assert . That ( dist , Is . LessThan ( 1e-6 ) , ( ) => string . Format ( "position {0} vs {1} dist {2}" ,
98
- aDummy . localPosition , bDummy . localPosition , dist ) ) ;
123
+ Assert . That ( dist , Is . LessThan ( 1e-6 ) , ( ) => string . Format ( "{3}: position {0} vs {1} dist {2}" ,
124
+ aDummy . localPosition , bDummy . localPosition , dist , aName ) ) ;
99
125
100
126
dist = Vector3 . Distance ( aDummy . localScale , bDummy . localScale ) ;
101
- Assert . That ( dist , Is . LessThan ( 1e-6 ) , ( ) => string . Format ( "scale {0} vs {1} dist {2}" ,
102
- aDummy . localScale , bDummy . localScale , dist ) ) ;
127
+ Assert . That ( dist , Is . LessThan ( 1e-6 ) , ( ) => string . Format ( "{3}: scale {0} vs {1} dist {2}" ,
128
+ aDummy . localScale , bDummy . localScale , dist , aName ) ) ;
103
129
104
130
dist = Quaternion . Angle ( aDummy . localRotation , bDummy . localRotation ) ;
105
- Assert . That ( dist , Is . LessThan ( 1e-6 ) , ( ) => string . Format ( "rotation {0} vs {1} angle {2}" ,
106
- aDummy . localRotation . eulerAngles , bDummy . localRotation . eulerAngles , dist ) ) ;
131
+ Assert . That ( dist , Is . LessThan ( 1e-6 ) , ( ) => string . Format ( "{3}: rotation {0} vs {1} angle {2}" ,
132
+ aDummy . localRotation . eulerAngles , bDummy . localRotation . eulerAngles , dist , aName ) ) ;
133
+ } else {
134
+ // Default: test that the components are precisely identical.
135
+ Assert . AreEqual ( avalues , bvalues , string . Format ( "{0}: type {1}" , aName , t ) ) ;
107
136
}
108
137
}
109
138
}
@@ -126,6 +155,7 @@ public void Init() {
126
155
var fbxAsset = FbxExporters . Editor . ModelExporter . ExportObject (
127
156
GetRandomFbxFilePath ( ) , m_original ) ;
128
157
m_source = AssetDatabase . LoadMainAssetAtPath ( fbxAsset ) as GameObject ;
158
+ m_originalHistory = Rep ( m_source ) ;
129
159
Assert . IsTrue ( m_source ) ;
130
160
131
161
// Create an FbxPrefab linked to the Fbx file. Make it auto-update.
@@ -161,12 +191,19 @@ FbxPrefab.FbxRepresentation History(GameObject go) {
161
191
162
192
GameObject ModifySourceFbx ( )
163
193
{
164
- // Modify the source fbx file :
194
+ // Generate this change :
165
195
// - delete parent1
196
+ // - move parent2
166
197
// - add parent3
167
- var newModel = PrefabUtility . InstantiatePrefab ( m_source ) as GameObject ;
198
+ // Simulate that we're doing this in Maya, so parent3 doesn't come
199
+ // with a collider.
200
+ var newModel = CreateHierarchy ( ) ;
168
201
GameObject . DestroyImmediate ( newModel . transform . Find ( "Parent1" ) . gameObject ) ;
169
- CreateGameObject ( "Parent3" , newModel . transform ) ;
202
+ var parent3 = CreateGameObject ( "Parent3" , newModel . transform ) ;
203
+ Object . DestroyImmediate ( parent3 . GetComponent < BoxCollider > ( ) ) ;
204
+
205
+ var parent2 = newModel . transform . Find ( "Parent2" ) ;
206
+ parent2 . localPosition += new Vector3 ( 1 , 2 , 3 ) ;
170
207
171
208
// Export it to clobber the old FBX file.
172
209
// Sleep one second first to make sure the timestamp differs
@@ -183,47 +220,48 @@ GameObject ModifySourceFbx()
183
220
184
221
[ Test ]
185
222
public void BasicTest ( ) {
186
- // Check the history is good at the start
223
+ // Verify we start in the right place.
187
224
AssertAreIdentical ( m_originalRep , Rep ( m_manualPrefab ) ) ;
188
225
AssertAreIdentical ( m_originalRep , Rep ( m_autoPrefab ) ) ;
189
- AssertAreIdentical ( m_originalRep , History ( m_manualPrefab ) ) ;
190
- AssertAreIdentical ( m_originalRep , History ( m_autoPrefab ) ) ;
226
+
227
+ // Verify history is as we expect. It differs from the originalRep
228
+ // in that it doesn't have box colliders.
229
+ AssertAreIdentical ( m_originalHistory , History ( m_manualPrefab ) ) ;
230
+ AssertAreIdentical ( m_originalHistory , History ( m_autoPrefab ) ) ;
191
231
192
232
FbxPrefab . FbxRepresentation newHierarchy ;
233
+ FbxPrefab . FbxRepresentation newHistory ;
193
234
using ( var updateSet = new UpdateListener ( m_autoPrefab ) ) {
194
235
Debug . Log ( "Testing auto update" ) ;
195
236
newHierarchy = Rep ( ModifySourceFbx ( ) ) ;
237
+ newHistory = Rep ( m_source ) ;
196
238
AssertAreDifferent ( m_originalRep , newHierarchy ) ;
197
239
198
- // Make sure the fbx source changed.
199
- AssertAreDifferent ( m_originalRep , Rep ( m_source ) ) ;
200
- AssertAreIdentical ( newHierarchy , Rep ( m_source ) ) ;
240
+ // Make sure the fbx source changed (testing the test).
241
+ AssertAreDifferent ( m_originalHistory , Rep ( m_source ) ) ;
201
242
202
- // Make sure the auto-update prefab changed.
203
- AssertAreIdentical ( newHierarchy , Rep ( m_autoPrefab ) ) ;
204
- AssertAreIdentical ( newHierarchy , History ( m_autoPrefab ) ) ;
205
-
206
- // Make sure the manual-update prefab didn't.
243
+ // Make sure the manual-update prefab didn't change.
207
244
AssertAreIdentical ( m_originalRep , Rep ( m_manualPrefab ) ) ;
208
- AssertAreIdentical ( m_originalRep , History ( m_manualPrefab ) ) ;
245
+ AssertAreIdentical ( m_originalHistory , History ( m_manualPrefab ) ) ;
209
246
210
- // Make sure we got the right changes.
247
+ // Make sure we got the right changes. Parent2 got its
248
+ // transform changed, Parent3 was created.
211
249
Assert . AreEqual ( 1 , updateSet . NumUpdates ) ;
212
250
Assert . That ( updateSet . Updated , Is . EquivalentTo ( new string [ ] {
213
- // TODO: UNI-24579 - we should only be seeing Parent3 here,
214
- // the other two are for transform changes, but
215
- // they shouldn't have changed at all
216
- "Parent2" , "Parent3" , "Child3"
251
+ "Parent2" , "Parent3"
217
252
}
218
253
) ) ;
254
+
255
+ // Make sure the auto-update prefab changed.
256
+ AssertAreIdentical ( newHierarchy , Rep ( m_autoPrefab ) ) ;
219
257
}
220
258
221
259
// Manual update, make sure it updated.
222
260
Debug . Log ( "Testing manual update" ) ;
223
261
var manualPrefabComponent = m_manualPrefab . GetComponent < FbxPrefab > ( ) ;
224
262
manualPrefabComponent . SyncPrefab ( ) ;
225
263
AssertAreIdentical ( newHierarchy , Rep ( m_manualPrefab ) ) ;
226
- AssertAreIdentical ( newHierarchy , History ( m_manualPrefab ) ) ;
264
+ AssertAreIdentical ( newHistory , History ( m_manualPrefab ) ) ;
227
265
228
266
// Check some corner cases.
229
267
Assert . AreEqual ( m_source , manualPrefabComponent . GetFbxAsset ( ) ) ;
@@ -245,10 +283,10 @@ public void BasicTest() {
245
283
Assert . That ( ( ) => manualPrefabComponent . SetSourceModel ( null ) , Throws . Nothing ) ;
246
284
Assert . IsNull ( manualPrefabComponent . GetFbxAsset ( ) ) ;
247
285
AssertAreIdentical ( newHierarchy , Rep ( m_manualPrefab ) ) ;
248
- AssertAreIdentical ( newHierarchy , History ( m_manualPrefab ) ) ;
286
+ AssertAreIdentical ( newHistory , History ( m_manualPrefab ) ) ;
249
287
Assert . That ( ( ) => manualPrefabComponent . SyncPrefab ( ) , Throws . Nothing ) ;
250
288
AssertAreIdentical ( newHierarchy , Rep ( m_manualPrefab ) ) ;
251
- AssertAreIdentical ( newHierarchy , History ( m_manualPrefab ) ) ;
289
+ AssertAreIdentical ( newHistory , History ( m_manualPrefab ) ) ;
252
290
253
291
// Switch to some other model, which looks like the original model
254
292
// (but is a totally different file). This will cause an update
@@ -259,24 +297,41 @@ public void BasicTest() {
259
297
Assert . IsTrue ( newSource ) ;
260
298
Debug . Log ( "Testing SetSourceModel relink" ) ;
261
299
manualPrefabComponent . SetSourceModel ( newSource ) ;
262
- AssertAreIdentical ( m_originalRep , Rep ( m_manualPrefab ) ) ;
263
- AssertAreIdentical ( m_originalRep , History ( m_manualPrefab ) ) ;
300
+
301
+ // Generate the answer we expect: the original but Parent1 and
302
+ // hierarchy are without collider. That's because we deleted them,
303
+ // and got them back. Parent2 should be back to the origin.
304
+ var expectedHierarchy = GameObject . Instantiate ( m_original ) ;
305
+ var parent1 = expectedHierarchy . transform . Find ( "Parent1" ) ;
306
+ foreach ( var collider in parent1 . GetComponentsInChildren < BoxCollider > ( ) ) {
307
+ Object . DestroyImmediate ( collider ) ;
308
+ }
309
+ var expectedRep = Rep ( expectedHierarchy ) ;
310
+ var expectedHistory = m_originalHistory ;
311
+
312
+ AssertAreIdentical ( expectedHistory , History ( m_manualPrefab ) ) ;
313
+ AssertAreIdentical ( expectedRep , Rep ( m_manualPrefab ) ) ;
264
314
}
265
315
266
316
[ Test ]
267
317
public void ManualToAuto ( ) {
268
318
// Check what happens when we go from manual to auto-update.
319
+ Debug . Log ( "ManualToAuto: modifying source" ) ;
269
320
var newHierarchy = Rep ( ModifySourceFbx ( ) ) ;
321
+ var newHistory = Rep ( m_source ) ;
322
+
270
323
AssertAreIdentical ( m_originalRep , Rep ( m_manualPrefab ) ) ;
271
- AssertAreIdentical ( m_originalRep , History ( m_manualPrefab ) ) ;
324
+ AssertAreIdentical ( m_originalHistory , History ( m_manualPrefab ) ) ;
272
325
326
+ Debug . Log ( "ManualToAuto: setting manual to manual" ) ;
273
327
m_manualPrefab . GetComponent < FbxPrefab > ( ) . SetAutoUpdate ( false ) ;
274
328
AssertAreIdentical ( m_originalRep , Rep ( m_manualPrefab ) ) ;
275
- AssertAreIdentical ( m_originalRep , History ( m_manualPrefab ) ) ;
329
+ AssertAreIdentical ( m_originalHistory , History ( m_manualPrefab ) ) ;
276
330
331
+ Debug . Log ( "ManualToAuto: setting manual to auto" ) ;
277
332
m_manualPrefab . GetComponent < FbxPrefab > ( ) . SetAutoUpdate ( true ) ;
278
333
AssertAreIdentical ( newHierarchy , Rep ( m_manualPrefab ) ) ;
279
- AssertAreIdentical ( newHierarchy , History ( m_manualPrefab ) ) ;
334
+ AssertAreIdentical ( newHistory , History ( m_manualPrefab ) ) ;
280
335
}
281
336
}
282
337
0 commit comments