@@ -232,7 +232,10 @@ public void TestExporterCallbacks()
232
232
{
233
233
var tree = CreateHierarchy ( ) ;
234
234
var tester = new CallbackTester ( tree . transform , GetRandomFbxFilePath ( ) ) ;
235
- var n = tree . GetComponentsInChildren < Transform > ( ) . Length ;
235
+ var nbTransforms = tree . GetComponentsInChildren < Transform > ( ) . Length ;
236
+ // UT-3419: because cubes are duplicates, there are less model callbacks than transforms
237
+ // 1 for the root and 1 for the cube model all the gameobjects share
238
+ var nbMeshCallbacks = 2 ;
236
239
237
240
// No callbacks registered => no calls.
238
241
tester . Verify ( 0 , 0 ) ;
@@ -241,34 +244,34 @@ public void TestExporterCallbacks()
241
244
ModelExporter . RegisterMeshCallback < FbxPrefab > ( tester . CallbackForFbxPrefab ) ;
242
245
243
246
// No fbprefab => no component calls, but every object called.
244
- tester . Verify ( 0 , n ) ;
247
+ tester . Verify ( 0 , nbMeshCallbacks ) ;
245
248
246
249
// Add a fbxprefab, check every object called and the prefab called.
247
250
tree . transform . Find ( "Parent1" ) . gameObject . AddComponent < FbxPrefab > ( ) ;
248
- tester . Verify ( 1 , n ) ;
251
+ tester . Verify ( 1 , nbTransforms ) ;
249
252
250
253
// Make the object report it's replacing everything => no component calls.
251
- tester . Verify ( 0 , n , objectResult : true ) ;
254
+ tester . Verify ( 0 , nbTransforms , objectResult : true ) ;
252
255
253
256
// Make sure we can't register for a component twice, but we can
254
257
// for an object. Register twice for an object means two calls per
255
258
// object.
256
259
Assert . That ( ( ) => ModelExporter . RegisterMeshCallback < FbxPrefab > ( tester . CallbackForFbxPrefab ) ,
257
260
Throws . Exception ) ;
258
261
ModelExporter . RegisterMeshObjectCallback ( tester . CallbackForObject ) ;
259
- tester . Verify ( 1 , 2 * n ) ;
262
+ tester . Verify ( 1 , 2 * nbTransforms ) ;
260
263
261
264
// Register twice but return true => only one call per object.
262
- tester . Verify ( 0 , n , objectResult : true ) ;
265
+ tester . Verify ( 0 , nbTransforms , objectResult : true ) ;
263
266
264
267
// Unregister once => only one call per object, and no more for the prefab.
265
268
ModelExporter . UnRegisterMeshCallback < FbxPrefab > ( ) ;
266
269
ModelExporter . UnRegisterMeshObjectCallback ( tester . CallbackForObject ) ;
267
- tester . Verify ( 0 , n ) ;
270
+ tester . Verify ( 0 , nbMeshCallbacks ) ;
268
271
269
272
// Legal to unregister if already unregistered.
270
273
ModelExporter . UnRegisterMeshCallback < FbxPrefab > ( ) ;
271
- tester . Verify ( 0 , n ) ;
274
+ tester . Verify ( 0 , nbMeshCallbacks ) ;
272
275
273
276
// Register same callback twice gets back to original state.
274
277
ModelExporter . UnRegisterMeshObjectCallback ( tester . CallbackForObject ) ;
@@ -302,11 +305,12 @@ public void TestExporterCallbacks()
302
305
ModelExporter . ExportObject ( filename , tree ) ;
303
306
ModelExporter . UnRegisterMeshCallback < FbxPrefab > ( ) ;
304
307
308
+ // UT-3419 Parent1 and Parent2 are instances the same mesh, so they should point to the same mesh
305
309
asset = AssetDatabase . LoadMainAssetAtPath ( filename ) as GameObject ;
306
310
assetMesh = asset . transform . Find ( "Parent1" ) . GetComponent < MeshFilter > ( ) . sharedMesh ;
307
311
Assert . AreEqual ( sphereMesh . triangles . Length , assetMesh . triangles . Length ) ;
308
312
assetMesh = asset . transform . Find ( "Parent2" ) . GetComponent < MeshFilter > ( ) . sharedMesh ;
309
- Assert . AreEqual ( cubeMesh . triangles . Length , assetMesh . triangles . Length ) ;
313
+ Assert . AreEqual ( sphereMesh . triangles . Length , assetMesh . triangles . Length ) ;
310
314
311
315
// Try again, but this time pick on Parent2 by name (different just
312
316
// to make sure we don't pass if the previous pass didn't
@@ -325,11 +329,12 @@ public void TestExporterCallbacks()
325
329
ModelExporter . ExportObject ( filename , tree ) ;
326
330
ModelExporter . UnRegisterMeshObjectCallback ( callback ) ;
327
331
332
+ // UT-3419 Parent1 and Parent2 are instances the same mesh, so they should point to the same mesh
328
333
asset = AssetDatabase . LoadMainAssetAtPath ( filename ) as GameObject ;
329
334
assetMesh = asset . transform . Find ( "Parent1" ) . GetComponent < MeshFilter > ( ) . sharedMesh ;
330
335
Assert . AreEqual ( cubeMesh . triangles . Length , assetMesh . triangles . Length ) ;
331
336
assetMesh = asset . transform . Find ( "Parent2" ) . GetComponent < MeshFilter > ( ) . sharedMesh ;
332
- Assert . AreEqual ( sphereMesh . triangles . Length , assetMesh . triangles . Length ) ;
337
+ Assert . AreEqual ( cubeMesh . triangles . Length , assetMesh . triangles . Length ) ;
333
338
}
334
339
335
340
[ Test ]
@@ -1079,5 +1084,25 @@ public void TestPreserveImportSettings()
1079
1084
newGuid = AssetDatabase . AssetPathToGUID ( filename ) ;
1080
1085
Assert . AreEqual ( originalGuid , newGuid ) ;
1081
1086
}
1087
+
1088
+ // UT-3419 Test that identical models export as instances
1089
+ [ Test ]
1090
+ public void TestInstanceExport ( )
1091
+ {
1092
+ // create root with 2 identical children
1093
+ var filename = GetRandomFbxFilePath ( ) ;
1094
+ GameObject root = new GameObject ( "root" ) ;
1095
+ GameObject child1 = CreateGameObject ( "child1" , root . transform ) ;
1096
+ GameObject child2 = CreateGameObject ( "child2" , root . transform ) ;
1097
+
1098
+ // check export was successful
1099
+ var result = ModelExporter . ExportObject ( filename , root ) ;
1100
+ Assert . That ( result , Is . Not . Null ) ;
1101
+ Assert . AreEqual ( filename , result ) ;
1102
+
1103
+ // check that both children reference the same mesh
1104
+ GameObject fbxObj = AssetDatabase . LoadMainAssetAtPath ( filename ) as GameObject ;
1105
+ Assert . AreEqual ( fbxObj . transform . GetChild ( 0 ) . GetComponent < MeshFilter > ( ) . sharedMesh . name , fbxObj . transform . GetChild ( 1 ) . GetComponent < MeshFilter > ( ) . sharedMesh . name ) ;
1106
+ }
1082
1107
}
1083
1108
}
0 commit comments