@@ -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 ) ) ) ;
@@ -225,6 +220,12 @@ private static string TryFindDCC(string dccPath, string ext, ExportSettings.DCCT
225
220
public class ExportSettings : ScriptableSingleton < ExportSettings >
226
221
{
227
222
public const string kDefaultSavePath = "." ;
223
+ private static List < string > s_PreferenceList = new List < string > ( ) { kMayaOptionName , kMayaLtOptionName , kMaxOptionName , kBlenderOptionName } ;
224
+ //Any additional names require a space after the name
225
+ public const string kMaxOptionName = "3ds Max " ;
226
+ public const string kMayaOptionName = "Maya " ;
227
+ public const string kMayaLtOptionName = "MayaLT " ;
228
+ public const string kBlenderOptionName = "Blender " ;
228
229
229
230
/// <summary>
230
231
/// The path where all the different versions of Maya are installed
@@ -264,7 +265,7 @@ public static string kDefaultAdskRoot {
264
265
265
266
// List of names in order that they appear in option list
266
267
[ SerializeField ]
267
- private List < string > dccOptionNames ;
268
+ private List < string > dccOptionNames = new List < string > ( ) ;
268
269
// List of paths in order that they appear in the option list
269
270
[ SerializeField ]
270
271
private List < string > dccOptionPaths ;
@@ -283,7 +284,12 @@ protected override void LoadDefaults()
283
284
/// </summary>
284
285
/// <returns>The unique name.</returns>
285
286
/// <param name="name">Name.</param>
286
- private static string GetUniqueName ( string name ) {
287
+ public static string GetUniqueDCCOptionName ( string name ) {
288
+ Debug . Assert ( instance != null ) ;
289
+ if ( name == null )
290
+ {
291
+ return null ;
292
+ }
287
293
if ( ! instance . dccOptionNames . Contains ( name ) ) {
288
294
return name ;
289
295
}
@@ -305,11 +311,129 @@ private static string GetUniqueName(string name){
305
311
do {
306
312
uniqueName = string . Format ( format , index , name ) ;
307
313
index ++ ;
308
- } while ( instance . dccOptionNames . Contains ( name ) ) ;
314
+ } while ( instance . dccOptionNames . Contains ( uniqueName ) ) ;
309
315
310
316
return uniqueName ;
311
317
}
312
318
319
+ public void SetDCCOptionNames ( List < string > newList )
320
+ {
321
+ dccOptionNames = newList ;
322
+ }
323
+
324
+ public void ClearDCCOptionNames ( )
325
+ {
326
+ dccOptionNames . Clear ( ) ;
327
+ }
328
+
329
+ /// <summary>
330
+ ///
331
+ /// Find the latest program available and make that the default choice.
332
+ /// Will always take any Maya version over any 3ds Max version.
333
+ ///
334
+ /// Returns the index of the most recent program in the list of dccOptionNames
335
+ ///
336
+ /// </summary>
337
+ public int GetPreferredDCCApp ( )
338
+ {
339
+ if ( dccOptionNames == null )
340
+ {
341
+ return - 1 ;
342
+ }
343
+
344
+ int newestDCCVersionIndex = - 1 ;
345
+ int newestDCCVersionNumber = - 1 ;
346
+
347
+ for ( int i = 0 ; i < dccOptionNames . Count ; i ++ )
348
+ {
349
+ int versionToCheck = FindDCCVersion ( dccOptionNames [ i ] ) ;
350
+ if ( versionToCheck == - 1 )
351
+ {
352
+ continue ;
353
+ }
354
+ if ( versionToCheck > newestDCCVersionNumber )
355
+ {
356
+ newestDCCVersionIndex = i ;
357
+ newestDCCVersionNumber = versionToCheck ;
358
+ }
359
+ else if ( versionToCheck == newestDCCVersionNumber )
360
+ {
361
+ int selection = ChoosePreferredDCCApp ( newestDCCVersionIndex , i ) ;
362
+ if ( selection == i )
363
+ {
364
+ newestDCCVersionIndex = i ;
365
+ newestDCCVersionNumber = FindDCCVersion ( dccOptionNames [ i ] ) ;
366
+ }
367
+ }
368
+ }
369
+ Debug . Assert ( newestDCCVersionIndex >= - 1 && newestDCCVersionIndex < dccOptionNames . Count ) ;
370
+ return newestDCCVersionIndex ;
371
+ }
372
+ /// <summary>
373
+ /// Takes the index of two program names from dccOptionNames and chooses our preferred one based on the preference list
374
+ /// This happens in case of a tie between two programs with the same release year / version
375
+ /// </summary>
376
+ /// <param name="optionA"></param>
377
+ /// <param name="optionB"></param>
378
+ /// <returns></returns>
379
+ private int ChoosePreferredDCCApp ( int optionA , int optionB )
380
+ {
381
+ Debug . Assert ( optionA >= 0 && optionB >= 0 && optionA < dccOptionNames . Count && optionB < dccOptionNames . Count ) ;
382
+ if ( dccOptionNames . Count == 0 )
383
+ {
384
+ return - 1 ;
385
+ }
386
+ var appA = dccOptionNames [ optionA ] ;
387
+ var appB = dccOptionNames [ optionB ] ;
388
+ if ( appA == null || appB == null || appA . Length <= 0 || appB . Length <= 0 )
389
+ {
390
+ return - 1 ;
391
+ }
392
+
393
+ //We assume that the option names have a
394
+ int scoreA = s_PreferenceList . IndexOf ( appA . Split ( ' ' ) [ 0 ] ) ;
395
+ int scoreB = s_PreferenceList . IndexOf ( appB . Split ( ' ' ) [ 0 ] ) ;
396
+
397
+ return scoreA < scoreB ? optionA : optionB ;
398
+ }
399
+
400
+ /// <summary>
401
+ /// Finds the version based off of the title of the application
402
+ /// </summary>
403
+ /// <param name="path"></param>
404
+ /// <returns> the year/version OR -1 if the year could not be parsed </returns>
405
+ private static int FindDCCVersion ( string AppName )
406
+ {
407
+ if ( AppName == null )
408
+ {
409
+ return - 1 ;
410
+ }
411
+
412
+ int version ;
413
+ string [ ] piecesArray = AppName . Split ( ' ' ) ;
414
+ if ( piecesArray . Length == 0 )
415
+ {
416
+ return - 1 ;
417
+ }
418
+ //Get the number, which is always the last chunk separated by a space.
419
+ string number = piecesArray [ piecesArray . Length - 1 ] ;
420
+
421
+ if ( int . TryParse ( number , out version ) )
422
+ {
423
+ return version ;
424
+ }
425
+ else
426
+ {
427
+ float fVersion ;
428
+ //In case we are looking at a Blender version- the int parse will fail so we'll need to parse it as a float.
429
+ if ( float . TryParse ( number , out fVersion ) )
430
+ {
431
+ return ( int ) fVersion ;
432
+ }
433
+ return - 1 ;
434
+ }
435
+ }
436
+
313
437
/// <summary>
314
438
/// Find Maya and 3DsMax installations at default install path.
315
439
/// Add results to given dictionary.
@@ -347,19 +471,24 @@ private static void FindDCCInstalls() {
347
471
}
348
472
string version = product . Substring ( "maya" . Length ) ;
349
473
dccOptionPath . Add ( GetMayaExePath ( productDir . FullName . Replace ( "\\ " , "/" ) ) ) ;
350
- dccOptionName . Add ( GetUniqueName ( "Maya " + version ) ) ;
474
+ dccOptionName . Add ( GetUniqueDCCOptionName ( kMayaOptionName + version ) ) ;
351
475
}
352
476
353
477
if ( product . StartsWith ( "3ds max" , StringComparison . InvariantCultureIgnoreCase ) ) {
354
478
var exePath = string . Format ( "{0}/{1}" , productDir . FullName . Replace ( "\\ " , "/" ) , "3dsmax.exe" ) ;
355
- if ( IsEarlierThanMax2017 ( exePath ) ) {
479
+
480
+ string version = product . Substring ( "3ds max " . Length ) ;
481
+ var maxOptionName = GetUniqueDCCOptionName ( kMaxOptionName + version ) ;
482
+
483
+ if ( IsEarlierThanMax2017 ( maxOptionName ) ) {
356
484
continue ;
357
485
}
358
- string version = product . Substring ( "3ds max " . Length ) ;
486
+
359
487
dccOptionPath . Add ( exePath ) ;
360
- dccOptionName . Add ( GetUniqueName ( "3ds Max " + version ) ) ;
488
+ dccOptionName . Add ( maxOptionName ) ;
361
489
}
362
490
}
491
+ instance . selectedDCCApp = instance . GetPreferredDCCApp ( ) ;
363
492
}
364
493
365
494
/// <summary>
@@ -406,7 +535,7 @@ public static GUIContent[] GetDCCOptions(){
406
535
var dccPath = instance . dccOptionPaths [ i ] ;
407
536
if ( ! File . Exists ( dccPath ) ) {
408
537
if ( i == instance . selectedDCCApp ) {
409
- instance . selectedDCCApp = 0 ;
538
+ instance . selectedDCCApp = instance . GetPreferredDCCApp ( ) ;
410
539
}
411
540
namesToDelete . Add ( instance . dccOptionNames [ i ] ) ;
412
541
pathsToDelete . Add ( dccPath ) ;
@@ -463,11 +592,20 @@ public static void AddDCCOption(string newOption, DCCType dcc){
463
592
Debug . LogError ( string . Format ( "Unity Integration does not support Maya LT: \" {0}\" " , newOption ) ) ;
464
593
return ;
465
594
}
466
- optionName = GetUniqueName ( "Maya " + version ) ;
595
+ optionName = GetUniqueDCCOptionName ( "Maya " + version ) ;
467
596
break ;
468
597
case DCCType . Max :
469
598
optionName = GetMaxOptionName ( newOption ) ;
470
- break ;
599
+ if ( ExportSettings . IsEarlierThanMax2017 ( optionName ) )
600
+ {
601
+ Debug . LogError ( "Earlier than 3ds Max 2017 is not supported" ) ;
602
+ UnityEditor . EditorUtility . DisplayDialog (
603
+ "Error adding 3D Application" ,
604
+ "Unity Integration only supports 3ds Max 2017 or later" ,
605
+ "Ok" ) ;
606
+ return ;
607
+ }
608
+ break ;
471
609
default :
472
610
throw new System . NotImplementedException ( ) ;
473
611
}
@@ -506,14 +644,12 @@ static string AskMayaVersion(string exePath) {
506
644
/// <returns>The 3DsMax dropdown option label.</returns>
507
645
/// <param name="exePath">Exe path.</param>
508
646
public static string GetMaxOptionName ( string exePath ) {
509
- return GetUniqueName ( Path . GetFileName ( Path . GetDirectoryName ( exePath ) ) ) ;
647
+ return GetUniqueDCCOptionName ( Path . GetFileName ( Path . GetDirectoryName ( exePath ) ) ) ;
510
648
}
511
649
512
- public static bool IsEarlierThanMax2017 ( string exePath ) {
513
- var name = Path . GetFileName ( Path . GetDirectoryName ( exePath ) ) . ToLower ( ) ;
514
- name = name . Replace ( "3ds max" , "" ) . Trim ( ) ;
515
- int version ;
516
- return int . TryParse ( name , out version ) && version < 2017 ;
650
+ public static bool IsEarlierThanMax2017 ( string AppName ) {
651
+ int version = FindDCCVersion ( AppName ) ;
652
+ return version != - 1 && version < 2017 ;
517
653
}
518
654
519
655
public static string GetSelectedDCCPath ( )
0 commit comments