Skip to content

Commit 8b9a2c5

Browse files
authored
UT-3305 Export Outside Assets Folder (#533)
Add ability export outside the Assets folder and tests for it.
1 parent 4d3acb2 commit 8b9a2c5

File tree

6 files changed

+131
-19
lines changed

6 files changed

+131
-19
lines changed

com.unity.formats.fbx/Editor/ExportModelEditorWindow.cs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,27 @@ protected void OnGUI ()
364364
GUILayout.BeginHorizontal();
365365
EditorGUILayout.LabelField(new GUIContent(
366366
"Export Path",
367-
"Relative path for saving Model Prefabs."),GUILayout.Width(LabelWidth - FieldOffset));
367+
"Location where the FBX will be saved."),GUILayout.Width(LabelWidth - FieldOffset));
368368

369-
var pathLabels = ExportSettings.GetRelativeFbxSavePaths();
369+
var pathLabels = ExportSettings.GetMixedFbxSavePaths();
370+
371+
if (this is ConvertToPrefabEditorWindow)
372+
{
373+
pathLabels = ExportSettings.GetRelativeFbxSavePaths();
374+
}
370375

371376
ExportSettings.instance.SelectedFbxPath = EditorGUILayout.Popup (ExportSettings.instance.SelectedFbxPath, pathLabels, GUILayout.MinWidth(SelectableLabelMinWidth));
372377

378+
// Set export setting for exporting outside the project on choosing a path
379+
if (string.IsNullOrEmpty(ExportSettings.ConvertToAssetRelativePath(ExportSettings.FbxAbsoluteSavePath)))
380+
{
381+
ExportSettings.instance.ExportOutsideProject = true;
382+
}
383+
else
384+
{
385+
ExportSettings.instance.ExportOutsideProject = false;
386+
}
387+
373388
if (GUILayout.Button(new GUIContent("...", "Browse to a new location to export to"), EditorStyles.miniButton, GUILayout.Width(BrowseButtonWidth)))
374389
{
375390
string initialPath = Application.dataPath;
@@ -378,23 +393,30 @@ protected void OnGUI ()
378393
"Select Export Model Path", initialPath, null
379394
);
380395

381-
// Unless the user canceled, make sure they chose something in the Assets folder.
396+
// Unless the user canceled, save path.
382397
if (!string.IsNullOrEmpty(fullPath))
383398
{
384399
var relativePath = ExportSettings.ConvertToAssetRelativePath(fullPath);
385-
if (string.IsNullOrEmpty(relativePath))
400+
401+
// If exporting an fbx for a prefab, not allowed to export outside the Assets folder
402+
if (this is ConvertToPrefabEditorWindow && string.IsNullOrEmpty(relativePath))
386403
{
387404
Debug.LogWarning("Please select a location in the Assets folder");
388405
}
406+
// We're exporting outside Assets folder, so store the absolute path
407+
else if (string.IsNullOrEmpty(relativePath))
408+
{
409+
ExportSettings.AddFbxSavePath(fullPath);
410+
}
411+
// Store the relative path to the Assets folder
389412
else
390413
{
391414
ExportSettings.AddFbxSavePath(relativePath);
392-
393-
// Make sure focus is removed from the selectable label
394-
// otherwise it won't update
395-
GUIUtility.hotControl = 0;
396-
GUIUtility.keyboardControl = 0;
397415
}
416+
// Make sure focus is removed from the selectable label
417+
// otherwise it won't update
418+
GUIUtility.hotControl = 0;
419+
GUIUtility.keyboardControl = 0;
398420
}
399421
}
400422
GUILayout.EndHorizontal();

com.unity.formats.fbx/Editor/ExportModelSettings.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ public override void OnInspectorGUI ()
9999
GUILayout.BeginHorizontal();
100100
EditorGUILayout.LabelField(new GUIContent("Preserve Import Settings for Existing FBX",
101101
"If checked, the import settings from the overwritten FBX will be carried over to the new version."), GUILayout.Width(LabelWidth - FieldOffset));
102+
// greyed out if exporting outside assets folder
103+
EditorGUI.BeginDisabledGroup(ExportSettings.instance.ExportOutsideProject);
102104
exportSettings.SetPreserveImportSettings(EditorGUILayout.Toggle(exportSettings.PreserveImportSettings));
105+
EditorGUI.EndDisabledGroup();
103106
GUILayout.EndHorizontal();
104107
}
105108
}
@@ -174,7 +177,7 @@ internal class ExportModelSettingsSerialize : ExportOptionsSettingsSerializeBase
174177
private ExportSettings.ObjectPosition objectPosition = ExportSettings.ObjectPosition.LocalCentered;
175178
[SerializeField]
176179
private bool exportUnrendered = true;
177-
private bool preserveImportSettings = true;
180+
private bool preserveImportSettings = false;
178181

179182
public override ExportSettings.Include ModelAnimIncludeOption { get { return include; } }
180183
public void SetModelAnimIncludeOption(ExportSettings.Include include) { this.include = include; }
@@ -185,7 +188,7 @@ internal class ExportModelSettingsSerialize : ExportOptionsSettingsSerializeBase
185188
public override bool ExportUnrendered { get { return exportUnrendered; } }
186189
public void SetExportUnredererd(bool exportUnrendered){ this.exportUnrendered = exportUnrendered; }
187190
public override bool PreserveImportSettings { get { return preserveImportSettings; } }
188-
public void SetPreserveImportSettings(bool preserveImportSettings){ this.preserveImportSettings = preserveImportSettings; }
191+
public void SetPreserveImportSettings(bool preserveImportSettings){ this.preserveImportSettings = preserveImportSettings && !ExportSettings.instance.ExportOutsideProject; }
189192
public override bool AllowSceneModification { get { return false; } }
190193
}
191194
}

com.unity.formats.fbx/Editor/FbxExportSettings.cs

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ public enum ObjectPosition { LocalCentered = 0, WorldAbsolute = 1, Reset = 2 /*
285285

286286
public enum LODExportType { All = 0, Highest = 1, Lowest = 2 }
287287

288+
public bool ExportOutsideProject;
289+
288290
internal const string kDefaultSavePath = ".";
289291
private static List<string> s_PreferenceList = new List<string>() {kMayaOptionName, kMayaLtOptionName, kMaxOptionName};
290292
//Any additional names require a space after the name
@@ -1112,13 +1114,48 @@ internal static string[] GetRelativeSavePaths(List<string> exportSavePaths){
11121114
return relSavePaths;
11131115
}
11141116

1117+
/// <summary>
1118+
/// Returns the paths for display in the menu.
1119+
/// Paths inside the Assets folder are relative, while those outside are kept absolute.
1120+
/// </summary>
1121+
internal static string[] GetMixedSavePaths(List<string> exportSavePaths)
1122+
{
1123+
string[] displayPaths = new string[exportSavePaths.Count];
1124+
string forwardslash = " \u2044 ";
1125+
for (int i = 0; i < displayPaths.Length; i++)
1126+
{
1127+
// if path is in Assets folder, shorten it
1128+
if (!Path.IsPathRooted(exportSavePaths[i]))
1129+
{
1130+
displayPaths[i] = string.Format("Assets{0}{1}", forwardslash, exportSavePaths[i] == "."? "" : NormalizePath(exportSavePaths [i], isRelative: true).Replace("/", forwardslash));
1131+
}
1132+
else
1133+
{
1134+
displayPaths[i] = exportSavePaths[i].Replace("/", forwardslash);
1135+
}
1136+
}
1137+
1138+
return displayPaths;
1139+
}
1140+
11151141
/// <summary>
11161142
/// The path where Export model will save the new fbx.
11171143
/// This is relative to the Application.dataPath ; it uses '/' as the
11181144
/// separator on all platforms.
1145+
/// Only returns the paths within the Assets folder of the project.
11191146
/// </summary>
11201147
internal static string[] GetRelativeFbxSavePaths(){
1121-
return GetRelativeSavePaths(instance.fbxSavePaths);
1148+
// sort the list of paths, putting project paths first
1149+
instance.fbxSavePaths.Sort((x, y) => Path.IsPathRooted(x).CompareTo(Path.IsPathRooted(y)));
1150+
var relPathCount = instance.fbxSavePaths.FindAll(x => !Path.IsPathRooted(x)).Count;
1151+
1152+
// reset selected path if it's out of range
1153+
if (instance.SelectedFbxPath > relPathCount - 1)
1154+
{
1155+
instance.SelectedFbxPath = 0;
1156+
}
1157+
1158+
return GetRelativeSavePaths(instance.fbxSavePaths.GetRange(0, relPathCount));
11221159
}
11231160

11241161
/// <summary>
@@ -1130,6 +1167,15 @@ internal static string[] GetRelativePrefabSavePaths(){
11301167
return GetRelativeSavePaths(instance.prefabSavePaths);
11311168
}
11321169

1170+
/// <summary>
1171+
/// The paths formatted for display in the menu.
1172+
/// Paths outside the Assets folder are kept as they are and ones inside are shortened.
1173+
/// </summary>
1174+
internal static string[] GetMixedFbxSavePaths()
1175+
{
1176+
return GetMixedSavePaths(instance.fbxSavePaths);
1177+
}
1178+
11331179
/// <summary>
11341180
/// Adds the save path to given save path list.
11351181
/// </summary>
@@ -1141,7 +1187,15 @@ private static void AddSavePath(string savePath, ref List<string> exportSavePath
11411187
return;
11421188
}
11431189

1144-
savePath = NormalizePath (savePath, isRelative: true);
1190+
if (ExportSettings.instance.ExportOutsideProject)
1191+
{
1192+
savePath = NormalizePath(savePath, isRelative: false);
1193+
}
1194+
else
1195+
{
1196+
savePath = NormalizePath(savePath, isRelative: true);
1197+
}
1198+
11451199
if (exportSavePaths.Contains (savePath)) {
11461200
// move to first place if it isn't already
11471201
if (exportSavePaths [0] == savePath) {
@@ -1168,10 +1222,17 @@ internal static void AddPrefabSavePath(string savePath){
11681222
instance.SelectedPrefabPath = 0;
11691223
}
11701224

1171-
internal static string GetAbsoluteSavePath(string relativePath){
1172-
var absolutePath = Path.Combine(Application.dataPath, relativePath);
1173-
return NormalizePath(absolutePath, isRelative: false,
1174-
separator: Path.DirectorySeparatorChar);
1225+
internal static string GetAbsoluteSavePath(string savePath){
1226+
var projectAbsolutePath = Path.Combine(Application.dataPath, savePath);
1227+
projectAbsolutePath = NormalizePath(projectAbsolutePath, isRelative: false, separator: Path.DirectorySeparatorChar);
1228+
1229+
// if path is outside Assets folder, it's already absolute so return the original path
1230+
if (string.IsNullOrEmpty(ExportSettings.ConvertToAssetRelativePath(projectAbsolutePath)))
1231+
{
1232+
return savePath;
1233+
}
1234+
1235+
return projectAbsolutePath;
11751236
}
11761237

11771238
internal static string FbxAbsoluteSavePath{

com.unity.formats.fbx/Tests/FbxApiTests/PublicAPITest.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,19 @@ public void TestExportObjects()
7676
Assert.Greater(mesh.triangles.Length, 0);
7777
}
7878
}
79+
80+
// UT-3305 Test exporting an fbx outside the Assets folder of the project
81+
[Test]
82+
public void TestExportOutsideProject()
83+
{
84+
Assert.IsNotNull(m_toExport);
85+
Assert.Greater(m_toExport.Length, 1);
86+
var filename = GetTempOutsideFilePath();
87+
88+
var fbxFileName = ModelExporter.ExportObjects(filename, m_toExport);
89+
90+
Assert.IsNotNull(fbxFileName);
91+
Assert.AreEqual(fbxFileName, filename);
92+
}
7993
}
8094
}

com.unity.formats.fbx/Tests/FbxTests/ModelExporterTest.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,10 @@ public void TestPreserveImportSettings()
10531053
var originalImportBlendShapes = importer.importBlendShapes;
10541054

10551055
// re-export with preserve import settings true and verify settings are the same
1056-
ModelExporter.ExportObjects(filename, new Object[] { cube });
1056+
var exportOptions = new ExportModelSettingsSerialize();
1057+
exportOptions.SetPreserveImportSettings(true);
1058+
1059+
ModelExporter.ExportObjects(filename, new Object[] { cube }, exportOptions);
10571060
importer = AssetImporter.GetAtPath(filename) as ModelImporter;
10581061
importer.SaveAndReimport();
10591062
Assert.AreEqual(originalImportBlendShapes, importer.importBlendShapes);
@@ -1063,7 +1066,8 @@ public void TestPreserveImportSettings()
10631066
Assert.AreEqual(originalGuid, newGuid);
10641067

10651068
// re-export with preserve import settings false and verify settings are different
1066-
var exportOptions = new ExportModelSettingsSerialize();
1069+
exportOptions = new ExportModelSettingsSerialize();
1070+
exportOptions.SetPreserveImportSettings(false);
10671071

10681072
exportOptions.SetPreserveImportSettings(false);
10691073
ModelExporter.ExportObjects(filename, new Object[] { cube }, exportOptions);

com.unity.formats.fbx/Tests/Scripts/ExporterTestBaseAPI.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ protected string GetRandomPrefabAssetPath() {
122122
return GetRandomFileNamePath(extName: ".prefab", unityPathSeparator: true);
123123
}
124124

125+
/// <summary>
126+
/// Returns a temp file path outside the Unity project.
127+
/// </summary>
128+
protected string GetTempOutsideFilePath()
129+
{
130+
return Path.GetTempFileName();
131+
}
132+
125133
/// <summary>
126134
/// Creates a test hierarchy of cubes.
127135
/// Root

0 commit comments

Comments
 (0)