@@ -98,8 +98,9 @@ public override void OnInspectorGUI() {
98
98
var options = ExportSettings . GetDCCOptions ( ) ;
99
99
// make sure we never initially have browse selected
100
100
if ( exportSettings . selectedDCCApp == options . Length - 1 ) {
101
- exportSettings . selectedDCCApp = 0 ;
101
+ exportSettings . selectedDCCApp = exportSettings . GetPreferredDCCApp ( ) ;
102
102
}
103
+
103
104
int oldValue = exportSettings . selectedDCCApp ;
104
105
exportSettings . selectedDCCApp = EditorGUILayout . Popup ( exportSettings . selectedDCCApp , options ) ;
105
106
if ( exportSettings . selectedDCCApp == options . Length - 1 ) {
@@ -135,16 +136,10 @@ public override void OnInspectorGUI() {
135
136
ExportSettings . DCCType foundDCC = ExportSettings . DCCType . Maya ;
136
137
var foundDCCPath = TryFindDCC ( dccPath , ext , ExportSettings . DCCType . Maya ) ;
137
138
if ( foundDCCPath == null && Application . platform == RuntimePlatform . WindowsEditor ) {
138
- if ( ExportSettings . IsEarlierThanMax2017 ( dccPath ) ) {
139
- Debug . LogError ( "Earlier than 3ds Max 2017 is not supported" ) ;
140
- UnityEditor . EditorUtility . DisplayDialog (
141
- "Error adding 3D Application" ,
142
- "Unity Integration only supports 3ds Max 2017 or later" ,
143
- "Ok" ) ;
144
- } else {
145
- foundDCCPath = TryFindDCC ( dccPath , ext , ExportSettings . DCCType . Max ) ;
146
- foundDCC = ExportSettings . DCCType . Max ;
147
- }
139
+
140
+ foundDCCPath = TryFindDCC ( dccPath , ext , ExportSettings . DCCType . Max ) ;
141
+ foundDCC = ExportSettings . DCCType . Max ;
142
+
148
143
}
149
144
if ( foundDCCPath == null ) {
150
145
Debug . LogError ( string . Format ( "Could not find supported 3D application at: \" {0}\" " , Path . GetDirectoryName ( dccPath ) ) ) ;
@@ -231,6 +226,12 @@ private static string TryFindDCC(string dccPath, string ext, ExportSettings.DCCT
231
226
public class ExportSettings : ScriptableSingleton < ExportSettings >
232
227
{
233
228
public const string kDefaultSavePath = "." ;
229
+ private static List < string > s_PreferenceList = new List < string > ( ) { kMayaOptionName , kMayaLtOptionName , kMaxOptionName , kBlenderOptionName } ;
230
+ //Any additional names require a space after the name
231
+ public const string kMaxOptionName = "3ds Max " ;
232
+ public const string kMayaOptionName = "Maya " ;
233
+ public const string kMayaLtOptionName = "MayaLT " ;
234
+ public const string kBlenderOptionName = "Blender " ;
234
235
235
236
/// <summary>
236
237
/// The path where all the different versions of Maya are installed
@@ -271,7 +272,7 @@ public static string kDefaultAdskRoot {
271
272
272
273
// List of names in order that they appear in option list
273
274
[ SerializeField ]
274
- private List < string > dccOptionNames ;
275
+ private List < string > dccOptionNames = new List < string > ( ) ;
275
276
// List of paths in order that they appear in the option list
276
277
[ SerializeField ]
277
278
private List < string > dccOptionPaths ;
@@ -291,7 +292,12 @@ protected override void LoadDefaults()
291
292
/// </summary>
292
293
/// <returns>The unique name.</returns>
293
294
/// <param name="name">Name.</param>
294
- private static string GetUniqueName ( string name ) {
295
+ public static string GetUniqueDCCOptionName ( string name ) {
296
+ Debug . Assert ( instance != null ) ;
297
+ if ( name == null )
298
+ {
299
+ return null ;
300
+ }
295
301
if ( ! instance . dccOptionNames . Contains ( name ) ) {
296
302
return name ;
297
303
}
@@ -313,11 +319,129 @@ private static string GetUniqueName(string name){
313
319
do {
314
320
uniqueName = string . Format ( format , index , name ) ;
315
321
index ++ ;
316
- } while ( instance . dccOptionNames . Contains ( name ) ) ;
322
+ } while ( instance . dccOptionNames . Contains ( uniqueName ) ) ;
317
323
318
324
return uniqueName ;
319
325
}
320
326
327
+ public void SetDCCOptionNames ( List < string > newList )
328
+ {
329
+ dccOptionNames = newList ;
330
+ }
331
+
332
+ public void ClearDCCOptionNames ( )
333
+ {
334
+ dccOptionNames . Clear ( ) ;
335
+ }
336
+
337
+ /// <summary>
338
+ ///
339
+ /// Find the latest program available and make that the default choice.
340
+ /// Will always take any Maya version over any 3ds Max version.
341
+ ///
342
+ /// Returns the index of the most recent program in the list of dccOptionNames
343
+ ///
344
+ /// </summary>
345
+ public int GetPreferredDCCApp ( )
346
+ {
347
+ if ( dccOptionNames == null )
348
+ {
349
+ return - 1 ;
350
+ }
351
+
352
+ int newestDCCVersionIndex = - 1 ;
353
+ int newestDCCVersionNumber = - 1 ;
354
+
355
+ for ( int i = 0 ; i < dccOptionNames . Count ; i ++ )
356
+ {
357
+ int versionToCheck = FindDCCVersion ( dccOptionNames [ i ] ) ;
358
+ if ( versionToCheck == - 1 )
359
+ {
360
+ continue ;
361
+ }
362
+ if ( versionToCheck > newestDCCVersionNumber )
363
+ {
364
+ newestDCCVersionIndex = i ;
365
+ newestDCCVersionNumber = versionToCheck ;
366
+ }
367
+ else if ( versionToCheck == newestDCCVersionNumber )
368
+ {
369
+ int selection = ChoosePreferredDCCApp ( newestDCCVersionIndex , i ) ;
370
+ if ( selection == i )
371
+ {
372
+ newestDCCVersionIndex = i ;
373
+ newestDCCVersionNumber = FindDCCVersion ( dccOptionNames [ i ] ) ;
374
+ }
375
+ }
376
+ }
377
+ Debug . Assert ( newestDCCVersionIndex >= - 1 && newestDCCVersionIndex < dccOptionNames . Count ) ;
378
+ return newestDCCVersionIndex ;
379
+ }
380
+ /// <summary>
381
+ /// Takes the index of two program names from dccOptionNames and chooses our preferred one based on the preference list
382
+ /// This happens in case of a tie between two programs with the same release year / version
383
+ /// </summary>
384
+ /// <param name="optionA"></param>
385
+ /// <param name="optionB"></param>
386
+ /// <returns></returns>
387
+ private int ChoosePreferredDCCApp ( int optionA , int optionB )
388
+ {
389
+ Debug . Assert ( optionA >= 0 && optionB >= 0 && optionA < dccOptionNames . Count && optionB < dccOptionNames . Count ) ;
390
+ if ( dccOptionNames . Count == 0 )
391
+ {
392
+ return - 1 ;
393
+ }
394
+ var appA = dccOptionNames [ optionA ] ;
395
+ var appB = dccOptionNames [ optionB ] ;
396
+ if ( appA == null || appB == null || appA . Length <= 0 || appB . Length <= 0 )
397
+ {
398
+ return - 1 ;
399
+ }
400
+
401
+ //We assume that the option names have a
402
+ int scoreA = s_PreferenceList . IndexOf ( appA . Split ( ' ' ) [ 0 ] ) ;
403
+ int scoreB = s_PreferenceList . IndexOf ( appB . Split ( ' ' ) [ 0 ] ) ;
404
+
405
+ return scoreA < scoreB ? optionA : optionB ;
406
+ }
407
+
408
+ /// <summary>
409
+ /// Finds the version based off of the title of the application
410
+ /// </summary>
411
+ /// <param name="path"></param>
412
+ /// <returns> the year/version OR -1 if the year could not be parsed </returns>
413
+ private static int FindDCCVersion ( string AppName )
414
+ {
415
+ if ( AppName == null )
416
+ {
417
+ return - 1 ;
418
+ }
419
+
420
+ int version ;
421
+ string [ ] piecesArray = AppName . Split ( ' ' ) ;
422
+ if ( piecesArray . Length == 0 )
423
+ {
424
+ return - 1 ;
425
+ }
426
+ //Get the number, which is always the last chunk separated by a space.
427
+ string number = piecesArray [ piecesArray . Length - 1 ] ;
428
+
429
+ if ( int . TryParse ( number , out version ) )
430
+ {
431
+ return version ;
432
+ }
433
+ else
434
+ {
435
+ float fVersion ;
436
+ //In case we are looking at a Blender version- the int parse will fail so we'll need to parse it as a float.
437
+ if ( float . TryParse ( number , out fVersion ) )
438
+ {
439
+ return ( int ) fVersion ;
440
+ }
441
+ return - 1 ;
442
+ }
443
+ }
444
+
321
445
/// <summary>
322
446
/// Find Maya and 3DsMax installations at default install path.
323
447
/// Add results to given dictionary.
@@ -355,19 +479,24 @@ private static void FindDCCInstalls() {
355
479
}
356
480
string version = product . Substring ( "maya" . Length ) ;
357
481
dccOptionPath . Add ( GetMayaExePath ( productDir . FullName . Replace ( "\\ " , "/" ) ) ) ;
358
- dccOptionName . Add ( GetUniqueName ( "Maya " + version ) ) ;
482
+ dccOptionName . Add ( GetUniqueDCCOptionName ( kMayaOptionName + version ) ) ;
359
483
}
360
484
361
485
if ( product . StartsWith ( "3ds max" , StringComparison . InvariantCultureIgnoreCase ) ) {
362
486
var exePath = string . Format ( "{0}/{1}" , productDir . FullName . Replace ( "\\ " , "/" ) , "3dsmax.exe" ) ;
363
- if ( IsEarlierThanMax2017 ( exePath ) ) {
487
+
488
+ string version = product . Substring ( "3ds max " . Length ) ;
489
+ var maxOptionName = GetUniqueDCCOptionName ( kMaxOptionName + version ) ;
490
+
491
+ if ( IsEarlierThanMax2017 ( maxOptionName ) ) {
364
492
continue ;
365
493
}
366
- string version = product . Substring ( "3ds max " . Length ) ;
494
+
367
495
dccOptionPath . Add ( exePath ) ;
368
- dccOptionName . Add ( GetUniqueName ( "3ds Max " + version ) ) ;
496
+ dccOptionName . Add ( maxOptionName ) ;
369
497
}
370
498
}
499
+ instance . selectedDCCApp = instance . GetPreferredDCCApp ( ) ;
371
500
}
372
501
373
502
/// <summary>
@@ -414,7 +543,7 @@ public static GUIContent[] GetDCCOptions(){
414
543
var dccPath = instance . dccOptionPaths [ i ] ;
415
544
if ( ! File . Exists ( dccPath ) ) {
416
545
if ( i == instance . selectedDCCApp ) {
417
- instance . selectedDCCApp = 0 ;
546
+ instance . selectedDCCApp = instance . GetPreferredDCCApp ( ) ;
418
547
}
419
548
namesToDelete . Add ( instance . dccOptionNames [ i ] ) ;
420
549
pathsToDelete . Add ( dccPath ) ;
@@ -471,11 +600,20 @@ public static void AddDCCOption(string newOption, DCCType dcc){
471
600
Debug . LogError ( string . Format ( "Unity Integration does not support Maya LT: \" {0}\" " , newOption ) ) ;
472
601
return ;
473
602
}
474
- optionName = GetUniqueName ( "Maya " + version ) ;
603
+ optionName = GetUniqueDCCOptionName ( "Maya " + version ) ;
475
604
break ;
476
605
case DCCType . Max :
477
606
optionName = GetMaxOptionName ( newOption ) ;
478
- break ;
607
+ if ( ExportSettings . IsEarlierThanMax2017 ( optionName ) )
608
+ {
609
+ Debug . LogError ( "Earlier than 3ds Max 2017 is not supported" ) ;
610
+ UnityEditor . EditorUtility . DisplayDialog (
611
+ "Error adding 3D Application" ,
612
+ "Unity Integration only supports 3ds Max 2017 or later" ,
613
+ "Ok" ) ;
614
+ return ;
615
+ }
616
+ break ;
479
617
default :
480
618
throw new System . NotImplementedException ( ) ;
481
619
}
@@ -514,14 +652,12 @@ static string AskMayaVersion(string exePath) {
514
652
/// <returns>The 3DsMax dropdown option label.</returns>
515
653
/// <param name="exePath">Exe path.</param>
516
654
public static string GetMaxOptionName ( string exePath ) {
517
- return GetUniqueName ( Path . GetFileName ( Path . GetDirectoryName ( exePath ) ) ) ;
655
+ return GetUniqueDCCOptionName ( Path . GetFileName ( Path . GetDirectoryName ( exePath ) ) ) ;
518
656
}
519
657
520
- public static bool IsEarlierThanMax2017 ( string exePath ) {
521
- var name = Path . GetFileName ( Path . GetDirectoryName ( exePath ) ) . ToLower ( ) ;
522
- name = name . Replace ( "3ds max" , "" ) . Trim ( ) ;
523
- int version ;
524
- return int . TryParse ( name , out version ) && version < 2017 ;
658
+ public static bool IsEarlierThanMax2017 ( string AppName ) {
659
+ int version = FindDCCVersion ( AppName ) ;
660
+ return version != - 1 && version < 2017 ;
525
661
}
526
662
527
663
public static string GetSelectedDCCPath ( )
0 commit comments