@@ -34,6 +34,8 @@ public class ModelExporter : System.IDisposable
34
34
35
35
const string FileBaseName = "Untitled" ;
36
36
37
+ const string ProgressBarTitle = "Fbx Export" ;
38
+
37
39
/// <summary>
38
40
/// Create instance of example
39
41
/// </summary>
@@ -248,12 +250,23 @@ protected void ExportTransform (UnityEngine.Transform unityTransform, FbxNode fb
248
250
/// <summary>
249
251
/// Unconditionally export components on this game object
250
252
/// </summary>
251
- protected void ExportComponents ( GameObject unityGo , FbxScene fbxScene , FbxNode fbxNodeParent )
253
+ protected int ExportComponents ( GameObject unityGo , FbxScene fbxScene , FbxNode fbxNodeParent , int currentIndex , int objectCount )
252
254
{
255
+ int i = currentIndex ;
256
+
253
257
// create an FbxNode and add it as a child of parent
254
258
FbxNode fbxNode = FbxNode . Create ( fbxScene , unityGo . name ) ;
255
259
NumNodes ++ ;
256
260
261
+ i ++ ;
262
+ if ( EditorUtility . DisplayCancelableProgressBar (
263
+ ProgressBarTitle ,
264
+ string . Format ( "Creating FbxNode {0}/{1}" , i , objectCount ) ,
265
+ ( i / ( float ) objectCount ) * 0.5f ) ) {
266
+ // cancel silently
267
+ return - 1 ;
268
+ }
269
+
257
270
ExportTransform ( unityGo . transform , fbxNode ) ;
258
271
ExportMesh ( GetMeshInfo ( unityGo ) , fbxNode , fbxScene ) ;
259
272
@@ -265,10 +278,27 @@ protected void ExportComponents (GameObject unityGo, FbxScene fbxScene, FbxNode
265
278
// now unityGo through our children and recurse
266
279
foreach ( Transform childT in unityGo . transform )
267
280
{
268
- ExportComponents ( childT . gameObject , fbxScene , fbxNode ) ;
281
+ i = ExportComponents ( childT . gameObject , fbxScene , fbxNode , i , objectCount ) ;
269
282
}
283
+ return i ;
284
+ }
270
285
271
- return ;
286
+ /// <summary>
287
+ /// A count of how many GameObjects we are exporting, to have a rough
288
+ /// idea of how long creating the scene will take.
289
+ /// </summary>
290
+ /// <returns>The object count.</returns>
291
+ /// <param name="exportSet">Export set.</param>
292
+ public int GetGameObjectCount ( IEnumerable < UnityEngine . Object > exportSet )
293
+ {
294
+ int count = 0 ;
295
+ foreach ( var obj in exportSet ) {
296
+ var unityGo = GetGameObject ( obj ) ;
297
+ if ( unityGo ) {
298
+ count += unityGo . transform . hierarchyCount ;
299
+ }
300
+ }
301
+ return count ;
272
302
}
273
303
274
304
/// <summary>
@@ -278,72 +308,129 @@ protected void ExportComponents (GameObject unityGo, FbxScene fbxScene, FbxNode
278
308
public int ExportAll ( IEnumerable < UnityEngine . Object > unityExportSet )
279
309
{
280
310
Verbose = true ;
281
-
282
- // Create the FBX manager
283
- using ( var fbxManager = FbxManager . Create ( ) )
284
- {
285
- // Configure fbx IO settings.
286
- fbxManager . SetIOSettings ( FbxIOSettings . Create ( fbxManager , Globals . IOSROOT ) ) ;
287
-
288
- // Export texture as embedded
289
- fbxManager . GetIOSettings ( ) . SetBoolProp ( Globals . EXP_FBX_EMBEDDED , true ) ;
290
-
291
- // Create the exporter
292
- var fbxExporter = FbxExporter . Create ( fbxManager , "Exporter" ) ;
293
-
294
- // Initialize the exporter.
295
- int fileFormat = fbxManager . GetIOPluginRegistry ( ) . FindWriterIDByDescription ( "FBX ascii (*.fbx)" ) ;
296
- bool status = fbxExporter . Initialize ( LastFilePath , fileFormat , fbxManager . GetIOSettings ( ) ) ;
297
- // Check that initialization of the fbxExporter was successful
298
- if ( ! status )
299
- return 0 ;
300
-
301
- // Set compatibility to 2014
302
- fbxExporter . SetFileExportVersion ( "FBX201400" ) ;
303
-
304
- // Create a scene
305
- var fbxScene = FbxScene . Create ( fbxManager , "Scene" ) ;
306
-
307
- // set up the scene info
308
- FbxDocumentInfo fbxSceneInfo = FbxDocumentInfo . Create ( fbxManager , "SceneInfo" ) ;
309
- fbxSceneInfo . mTitle = Title ;
310
- fbxSceneInfo . mSubject = Subject ;
311
- fbxSceneInfo . mAuthor = "Unity Technologies" ;
312
- fbxSceneInfo . mRevision = "1.0" ;
313
- fbxSceneInfo . mKeywords = Keywords ;
314
- fbxSceneInfo . mComment = Comments ;
315
- fbxScene . SetSceneInfo ( fbxSceneInfo ) ;
316
-
317
- // Set up the axes (Y up, Z forward, X to the right) and units (meters)
318
- var fbxSettings = fbxScene . GetGlobalSettings ( ) ;
319
- fbxSettings . SetSystemUnit ( FbxSystemUnit . m ) ;
320
-
321
- // The Unity axis system has Y up, Z forward, X to the right (left handed system with odd parity).
322
- // The Maya axis system has Y up, Z forward, X to the left (right handed system with odd parity).
323
- // We need to export right-handed for Maya because ConvertScene can't switch handedness:
324
- // https://forums.autodesk.com/t5/fbx-forum/get-confused-with-fbxaxissystem-convertscene/td-p/4265472
325
- fbxSettings . SetAxisSystem ( FbxAxisSystem . MayaYUp ) ;
326
-
327
- // export set of object
328
- FbxNode fbxRootNode = fbxScene . GetRootNode ( ) ;
329
- foreach ( var obj in unityExportSet )
311
+ try {
312
+ // Create the FBX manager
313
+ using ( var fbxManager = FbxManager . Create ( ) )
330
314
{
331
- var unityGo = GetGameObject ( obj ) ;
332
-
333
- if ( unityGo )
315
+ // Configure fbx IO settings.
316
+ fbxManager . SetIOSettings ( FbxIOSettings . Create ( fbxManager , Globals . IOSROOT ) ) ;
317
+
318
+ // Export texture as embedded
319
+ fbxManager . GetIOSettings ( ) . SetBoolProp ( Globals . EXP_FBX_EMBEDDED , true ) ;
320
+
321
+ // Create the exporter
322
+ var fbxExporter = FbxExporter . Create ( fbxManager , "Exporter" ) ;
323
+
324
+ // Initialize the exporter.
325
+ int fileFormat = fbxManager . GetIOPluginRegistry ( ) . FindWriterIDByDescription ( "FBX ascii (*.fbx)" ) ;
326
+ bool status = fbxExporter . Initialize ( LastFilePath , fileFormat , fbxManager . GetIOSettings ( ) ) ;
327
+ // Check that initialization of the fbxExporter was successful
328
+ if ( ! status )
329
+ return 0 ;
330
+
331
+ // Set compatibility to 2014
332
+ fbxExporter . SetFileExportVersion ( "FBX201400" ) ;
333
+
334
+ // Set the progress callback.
335
+ fbxExporter . SetProgressCallback ( ExportProgressCallback ) ;
336
+
337
+ // Create a scene
338
+ var fbxScene = FbxScene . Create ( fbxManager , "Scene" ) ;
339
+
340
+ // set up the scene info
341
+ FbxDocumentInfo fbxSceneInfo = FbxDocumentInfo . Create ( fbxManager , "SceneInfo" ) ;
342
+ fbxSceneInfo . mTitle = Title ;
343
+ fbxSceneInfo . mSubject = Subject ;
344
+ fbxSceneInfo . mAuthor = "Unity Technologies" ;
345
+ fbxSceneInfo . mRevision = "1.0" ;
346
+ fbxSceneInfo . mKeywords = Keywords ;
347
+ fbxSceneInfo . mComment = Comments ;
348
+ fbxScene . SetSceneInfo ( fbxSceneInfo ) ;
349
+
350
+ // Set up the axes (Y up, Z forward, X to the right) and units (meters)
351
+ var fbxSettings = fbxScene . GetGlobalSettings ( ) ;
352
+ fbxSettings . SetSystemUnit ( FbxSystemUnit . m ) ;
353
+
354
+ // The Unity axis system has Y up, Z forward, X to the right (left handed system with odd parity).
355
+ // The Maya axis system has Y up, Z forward, X to the left (right handed system with odd parity).
356
+ // We need to export right-handed for Maya because ConvertScene can't switch handedness:
357
+ // https://forums.autodesk.com/t5/fbx-forum/get-confused-with-fbxaxissystem-convertscene/td-p/4265472
358
+ fbxSettings . SetAxisSystem ( FbxAxisSystem . MayaYUp ) ;
359
+
360
+ // export set of object
361
+ FbxNode fbxRootNode = fbxScene . GetRootNode ( ) ;
362
+ int i = 0 ;
363
+ int count = GetGameObjectCount ( unityExportSet ) ;
364
+ foreach ( var obj in unityExportSet )
334
365
{
335
- this . ExportComponents ( unityGo , fbxScene , fbxRootNode ) ;
366
+ var unityGo = GetGameObject ( obj ) ;
367
+
368
+ if ( unityGo )
369
+ {
370
+ i = this . ExportComponents ( unityGo , fbxScene , fbxRootNode , i , count ) ;
371
+ if ( i < 0 ) {
372
+ Debug . LogWarning ( "Export Cancelled" ) ;
373
+ return 0 ;
374
+ }
375
+ }
336
376
}
377
+
378
+ // Export the scene to the file.
379
+ status = fbxExporter . Export ( fbxScene ) ;
380
+
381
+ // cleanup
382
+ fbxScene . Destroy ( ) ;
383
+ fbxExporter . Destroy ( ) ;
384
+
385
+ if ( exportCancelled ) {
386
+ Debug . LogWarning ( "Export Cancelled" ) ;
387
+ // delete the file that got created
388
+ EditorApplication . update += DeleteFile ;
389
+ return 0 ;
390
+ }
391
+
392
+ return status == true ? NumNodes : 0 ;
337
393
}
394
+ }
395
+ finally {
396
+ // You must clear the progress bar when you're done,
397
+ // otherwise it never goes away and many actions in Unity
398
+ // are blocked (e.g. you can't quit).
399
+ EditorUtility . ClearProgressBar ( ) ;
400
+ }
401
+ }
402
+
403
+ static bool exportCancelled = false ;
338
404
339
- // Export the scene to the file.
340
- status = fbxExporter . Export ( fbxScene ) ;
405
+ static bool ExportProgressCallback ( float percentage , string status ) {
406
+ // Convert from percentage to [0,1].
407
+ // Then convert from that to [0.5,1] because the first half of
408
+ // the progress bar was for creating the scene.
409
+ var progress01 = 0.5f * ( 1f + ( percentage / 100.0f ) ) ;
341
410
342
- // cleanup
343
- fbxScene . Destroy ( ) ;
344
- fbxExporter . Destroy ( ) ;
411
+ bool cancel = EditorUtility . DisplayCancelableProgressBar ( ProgressBarTitle , "Exporting Scene..." , progress01 ) ;
412
+
413
+ if ( cancel ) {
414
+ exportCancelled = true ;
415
+ }
345
416
346
- return status == true ? NumNodes : 0 ;
417
+ // Unity says "true" for "cancel"; FBX wants "true" for "continue"
418
+ return ! cancel ;
419
+ }
420
+
421
+ static void DeleteFile ( )
422
+ {
423
+ if ( File . Exists ( LastFilePath ) ) {
424
+ try {
425
+ File . Delete ( LastFilePath ) ;
426
+ } catch ( IOException ) { }
427
+
428
+ if ( File . Exists ( LastFilePath ) ) {
429
+ Debug . LogWarning ( "Failed to delete file: " + LastFilePath ) ;
430
+ }
431
+ } else {
432
+ EditorApplication . update -= DeleteFile ;
433
+ AssetDatabase . Refresh ( ) ;
347
434
}
348
435
}
349
436
0 commit comments