Skip to content

Commit 2c9e40a

Browse files
authored
Merge pull request #261 from Unity-Technologies/Uni-33058_unitTest_for_VendorLocations
Uni-33058 unit test for vendor locations + mayalocation and vendor location updates
2 parents 4bb2ab4 + 5b8df72 commit 2c9e40a

File tree

2 files changed

+488
-166
lines changed

2 files changed

+488
-166
lines changed

Assets/FbxExporters/Editor/FbxExportSettings.cs

Lines changed: 187 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using UnityEngine;
55
using UnityEditor;
66
using System.Collections.Generic;
7+
using System.Linq;
78

89
namespace FbxExporters.EditorTools {
910

@@ -288,39 +289,135 @@ private static string DefaultIntegrationSavePath {
288289
}
289290
}
290291

291-
/// <summary>
292-
/// The paths where all the different versions of Maya are installed
293-
/// by default. Depends on the platform.
294-
/// </summary>
295-
public static string[] DCCVendorLocations {
296-
get{
297-
var environmentVariable = Environment.GetEnvironmentVariable("UNITY_3DAPP_VENDOR_LOCATIONS");
298-
if (environmentVariable != null)
292+
private static string GetMayaLocationFromEnvironmentVariable(string env)
293+
{
294+
string result = null;
295+
296+
if (string.IsNullOrEmpty(env))
297+
return null;
298+
299+
string location = Environment.GetEnvironmentVariable(env);
300+
301+
if (string.IsNullOrEmpty(location))
302+
return null;
303+
304+
//Remove any extra slashes on the end
305+
//Maya would accept a single slash in either direction, so we should be able to
306+
location = location.Replace("\\", "/");
307+
location = location.TrimEnd('/');
308+
309+
if (!Directory.Exists(location))
310+
return null;
311+
312+
if (Application.platform == RuntimePlatform.WindowsEditor)
313+
{
314+
//If we are on Windows, we need only go up one location to get to the "Autodesk" folder.
315+
result = Directory.GetParent(location).ToString();
316+
}
317+
else if (Application.platform == RuntimePlatform.OSXEditor)
318+
{
319+
//We can assume our path is: /Applications/Autodesk/maya2017/Maya.app/Contents
320+
//So we need to go up three folders.
321+
322+
var appFolder = Directory.GetParent(location);
323+
if (appFolder != null)
299324
{
300-
string[] locations = environmentVariable.Split(';');
301-
List<string> locationsList = new List<string>();
302-
for (int i = 0; i < locations.Length; i++)
325+
var versionFolder = Directory.GetParent(appFolder.ToString());
326+
if (versionFolder != null)
303327
{
304-
if (Directory.Exists(locations[i]))
328+
var autoDeskFolder = Directory.GetParent(versionFolder.ToString());
329+
if (autoDeskFolder != null)
305330
{
306-
locationsList.Add(locations[i]);
331+
result = autoDeskFolder.ToString();
307332
}
308333
}
309-
if (locationsList.Count > 0)
334+
}
335+
}
336+
return result;
337+
}
338+
339+
/// <summary>
340+
/// Returns a set of valid vendor folder paths with no trailing '/'
341+
/// </summary>
342+
private static HashSet<string> GetCustomVendorLocations()
343+
{
344+
HashSet<string> result = new HashSet<string>();
345+
346+
var environmentVariable = Environment.GetEnvironmentVariable("UNITY_FBX_3DAPP_VENDOR_LOCATIONS");
347+
348+
if (!string.IsNullOrEmpty(environmentVariable))
349+
{
350+
string[] locations = environmentVariable.Split(';');
351+
foreach (var location in locations)
352+
{
353+
if (Directory.Exists(location))
354+
{
355+
result.Add(location);
356+
}
357+
}
358+
}
359+
360+
361+
return result;
362+
}
363+
364+
private static HashSet<string> GetDefaultVendorLocations()
365+
{
366+
if (Application.platform == RuntimePlatform.WindowsEditor)
367+
{
368+
HashSet<string> windowsDefaults = new HashSet<string>() { "C:/Program Files/Autodesk", "D:/Program Files/Autodesk" };
369+
HashSet<string> existingDirectories = new HashSet<string>();
370+
foreach (string path in windowsDefaults)
371+
{
372+
if (Directory.Exists(path))
310373
{
311-
return locationsList.ToArray();
374+
existingDirectories.Add(path);
312375
}
313376
}
377+
return existingDirectories;
314378

315-
switch (Application.platform)
379+
}
380+
else if (Application.platform == RuntimePlatform.OSXEditor)
381+
{
382+
HashSet<string> MacOSDefaults = new HashSet<string>() { "/Applications/Autodesk" };
383+
HashSet<string> existingDirectories = new HashSet<string>();
384+
foreach (string path in MacOSDefaults)
316385
{
317-
case RuntimePlatform.WindowsEditor:
318-
return new string[] { "C:/Program Files/Autodesk", "D:/Program Files/Autodesk" };
319-
case RuntimePlatform.OSXEditor:
320-
return new string[] { "/Applications/Autodesk" };
321-
default:
322-
throw new NotImplementedException();
386+
if (Directory.Exists(path))
387+
{
388+
existingDirectories.Add(path);
389+
}
323390
}
391+
return existingDirectories;
392+
}
393+
394+
throw new NotImplementedException();
395+
}
396+
397+
/// <summary>
398+
/// Retrieve available vendor locations.
399+
/// If there is valid alternative vendor locations, do not use defaults
400+
/// always use MAYA_LOCATION when available
401+
/// </summary>
402+
public static string[] DCCVendorLocations
403+
{
404+
get
405+
{
406+
HashSet<string> result = GetCustomVendorLocations();
407+
408+
if (result == null || result.Count < 1)
409+
{
410+
result = GetDefaultVendorLocations();
411+
}
412+
413+
var additionalLocation = GetMayaLocationFromEnvironmentVariable("MAYA_LOCATION");
414+
415+
if (!string.IsNullOrEmpty(additionalLocation))
416+
{
417+
result.Add(additionalLocation);
418+
}
419+
420+
return result.ToArray<string>();
324421
}
325422
}
326423

@@ -420,13 +517,19 @@ public void ClearDCCOptionNames()
420517
dccOptionNames.Clear();
421518
}
422519

520+
public void ClearDCCOptions()
521+
{
522+
SetDCCOptionNames(null);
523+
SetDCCOptionPaths(null);
524+
}
525+
423526
/// <summary>
424527
///
425528
/// Find the latest program available and make that the default choice.
426529
/// Will always take any Maya version over any 3ds Max version.
427530
///
428531
/// Returns the index of the most recent program in the list of dccOptionNames
429-
///
532+
/// Returns -1 on error.
430533
/// </summary>
431534
public int GetPreferredDCCApp()
432535
{
@@ -435,33 +538,36 @@ public int GetPreferredDCCApp()
435538
return -1;
436539
}
437540

438-
int newestDCCVersionIndex = -1;
541+
int result = -1;
439542
int newestDCCVersionNumber = -1;
440543

441544
for (int i = 0; i < dccOptionNames.Count; i++)
442545
{
443546
int versionToCheck = FindDCCVersion(dccOptionNames[i]);
444547
if (versionToCheck == -1)
445548
{
549+
if (dccOptionNames[i]=="MAYA_LOCATION")
550+
return i;
551+
446552
continue;
447553
}
448554
if (versionToCheck > newestDCCVersionNumber)
449555
{
450-
newestDCCVersionIndex = i;
556+
result = i;
451557
newestDCCVersionNumber = versionToCheck;
452558
}
453559
else if (versionToCheck == newestDCCVersionNumber)
454560
{
455-
int selection = ChoosePreferredDCCApp(newestDCCVersionIndex, i);
561+
int selection = ChoosePreferredDCCApp(result, i);
456562
if (selection == i)
457563
{
458-
newestDCCVersionIndex = i;
564+
result = i;
459565
newestDCCVersionNumber = FindDCCVersion(dccOptionNames[i]);
460566
}
461567
}
462568
}
463-
Debug.Assert(newestDCCVersionIndex >= -1 && newestDCCVersionIndex < dccOptionNames.Count);
464-
return newestDCCVersionIndex;
569+
570+
return result;
465571
}
466572
/// <summary>
467573
/// Takes the index of two program names from dccOptionNames and chooses our preferred one based on the preference list
@@ -498,20 +604,23 @@ private int ChoosePreferredDCCApp(int optionA, int optionB)
498604
/// <returns> the year/version OR -1 if the year could not be parsed </returns>
499605
private static int FindDCCVersion(string AppName)
500606
{
501-
if (AppName == null)
607+
if (string.IsNullOrEmpty(AppName))
502608
{
503609
return -1;
504610
}
505-
506-
int version;
611+
AppName = AppName.Trim();
612+
if (string.IsNullOrEmpty(AppName))
613+
return -1;
614+
507615
string[] piecesArray = AppName.Split(' ');
508-
if (piecesArray.Length == 0)
616+
if (piecesArray.Length < 2)
509617
{
510618
return -1;
511619
}
512620
//Get the number, which is always the last chunk separated by a space.
513621
string number = piecesArray[piecesArray.Length - 1];
514622

623+
int version;
515624
if (int.TryParse(number, out version))
516625
{
517626
return version;
@@ -535,9 +644,10 @@ private static int FindDCCVersion(string AppName)
535644
/// If MAYA_LOCATION is set, add this to the list as well.
536645
/// </summary>
537646
private static void FindDCCInstalls() {
538-
var dccOptionName = instance.dccOptionNames;
539-
var dccOptionPath = instance.dccOptionPaths;
647+
var dccOptionNames = instance.dccOptionNames;
648+
var dccOptionPaths = instance.dccOptionPaths;
540649

650+
// find dcc installation from vendor locations
541651
for (int i = 0; i < DCCVendorLocations.Length; i++)
542652
{
543653
if (!Directory.Exists(DCCVendorLocations[i]))
@@ -555,8 +665,8 @@ private static void FindDCCInstalls() {
555665
// Only accept those that start with 'maya' in either case.
556666
if (product.StartsWith ("maya", StringComparison.InvariantCultureIgnoreCase)) {
557667
string version = product.Substring ("maya".Length);
558-
dccOptionPath.Add (GetMayaExePath (productDir.FullName.Replace ("\\", "/")));
559-
dccOptionName.Add (GetUniqueDCCOptionName(kMayaOptionName + version));
668+
dccOptionPaths.Add (GetMayaExePathFromLocation (productDir.FullName.Replace ("\\", "/")));
669+
dccOptionNames.Add (GetUniqueDCCOptionName(kMayaOptionName + version));
560670
continue;
561671
}
562672

@@ -572,11 +682,21 @@ private static void FindDCCInstalls() {
572682
continue;
573683
}
574684

575-
dccOptionPath.Add(exePath);
576-
dccOptionName.Add(maxOptionName);
685+
dccOptionPaths.Add(exePath);
686+
dccOptionNames.Add(maxOptionName);
577687
}
578688
}
579689
}
690+
691+
// add extra locations defined by special environment variables
692+
string location = GetMayaLocationFromEnvironmentVariable("MAYA_LOCATION");
693+
694+
if (!string.IsNullOrEmpty(location))
695+
{
696+
dccOptionPaths.Add(GetMayaExePathFromLocation(location));
697+
dccOptionNames.Add("MAYA_LOCATION");
698+
}
699+
580700
instance.selectedDCCApp = instance.GetPreferredDCCApp();
581701
}
582702

@@ -604,7 +724,7 @@ public static string GetFirstValidVendorLocation()
604724
/// </summary>
605725
/// <returns>The maya exe path.</returns>
606726
/// <param name="location">Location of Maya install.</param>
607-
private static string GetMayaExePath(string location)
727+
private static string GetMayaExePathFromLocation(string location)
608728
{
609729
switch (Application.platform) {
610730
case RuntimePlatform.WindowsEditor:
@@ -684,7 +804,7 @@ public enum DCCType { Maya, Max };
684804
public static void AddDCCOption(string newOption, DCCType dcc){
685805
if (Application.platform == RuntimePlatform.OSXEditor && dcc == DCCType.Maya) {
686806
// on OSX we get a path ending in .app, which is not quite the exe
687-
newOption = GetMayaExePath(newOption);
807+
newOption = GetMayaExePathFromLocation(newOption);
688808
}
689809

690810
var dccOptionPaths = instance.dccOptionPaths;
@@ -697,6 +817,14 @@ public static void AddDCCOption(string newOption, DCCType dcc){
697817
switch (dcc) {
698818
case DCCType.Maya:
699819
var version = AskMayaVersion(newOption);
820+
if (version == null)
821+
{
822+
Debug.LogError("This version of Maya could not be launched properly");
823+
UnityEditor.EditorUtility.DisplayDialog("Error Loading 3D Application",
824+
"Failed to add Maya option, could not get version number from maya.exe",
825+
"Ok");
826+
return;
827+
}
700828
optionName = GetUniqueDCCOptionName("Maya " + version);
701829
break;
702830
case DCCType.Max:
@@ -739,8 +867,25 @@ static string AskMayaVersion(string exePath) {
739867
// Output is like: Maya 2018, Cut Number 201706261615
740868
// We want the stuff after 'Maya ' and before the comma.
741869
// (Uni-31601) less brittle! Consider also the mel command "about -version".
870+
if (string.IsNullOrEmpty(resultString))
871+
{
872+
return null;
873+
}
874+
875+
resultString = resultString.Trim();
742876
var commaIndex = resultString.IndexOf(',');
743-
return resultString.Substring(0, commaIndex).Substring("Maya ".Length);
877+
878+
if (commaIndex != -1)
879+
{
880+
const int versionStart = 5; // length of "Maya "
881+
return resultString.Length > versionStart ? resultString.Substring(0, commaIndex).Substring(versionStart) : null;
882+
}
883+
else
884+
{
885+
//This probably means we tried to launch Maya to check the version but it was some sort of broken maya.
886+
//We'll just return null and throw an error for it.
887+
return null;
888+
}
744889
}
745890

746891
/// <summary>

0 commit comments

Comments
 (0)