Skip to content

Commit f9f57a5

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/master' into UNI-25245-maya-in-non-default-path
# Conflicts: # Assets/FbxExporters/Editor/FbxExportSettings.cs
2 parents f8c3abc + 3517d1f commit f9f57a5

File tree

5 files changed

+108
-59
lines changed

5 files changed

+108
-59
lines changed

Assets/FbxExporters/Editor/ConvertToModel.cs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@ public static bool OnValidateMenuItem ()
6262
return true;
6363
}
6464

65+
/// <summary>
66+
/// After a convert-to-model, we normally delete the original object.
67+
/// That can be overridden.
68+
/// </summary>
69+
public enum KeepOriginal {
70+
Default, // Use the export settings.
71+
Keep, // Don't delete, just rename it.
72+
Delete, // Delete the original hierarchy.
73+
}
74+
75+
/// <summary>
76+
/// Gets the export settings.
77+
/// </summary>
78+
public static EditorTools.ExportSettings ExportSettings {
79+
get { return EditorTools.ExportSettings.instance; }
80+
}
81+
6582
/// <summary>
6683
/// Create instantiated model prefabs from a selection of objects.
6784
///
@@ -73,7 +90,10 @@ public static bool OnValidateMenuItem ()
7390
/// <param name="unityGameObjectsToConvert">Unity game objects to convert to Model Prefab instances</param>
7491
/// <param name="path">Path to save Model Prefab; use FbxExportSettings if null</param>
7592
/// <param name="keepOriginal">If set to <c>true</c> keep original gameobject hierarchy.</param>
76-
public static GameObject[] CreateInstantiatedModelPrefab (GameObject [] unityGameObjectsToConvert, string directoryFullPath = null, bool keepOriginal = true)
93+
public static GameObject[] CreateInstantiatedModelPrefab (
94+
GameObject [] unityGameObjectsToConvert,
95+
string directoryFullPath = null,
96+
KeepOriginal keepOriginal = KeepOriginal.Default)
7797
{
7898
if (directoryFullPath == null) {
7999
directoryFullPath = FbxExporters.EditorTools.ExportSettings.GetAbsoluteSavePath();
@@ -119,7 +139,7 @@ public static GameObject Convert (
119139
GameObject toConvert,
120140
string directoryFullPath = null,
121141
string fbxFullPath = null,
122-
bool keepOriginal = true)
142+
KeepOriginal keepOriginal = KeepOriginal.Default)
123143
{
124144
if (string.IsNullOrEmpty(fbxFullPath)) {
125145
// Generate a unique filename.
@@ -197,7 +217,20 @@ public static GameObject Convert (
197217
unityGO = PrefabUtility.ConnectGameObjectToPrefab(unityGO, prefab);
198218

199219
// Remove (now redundant) gameobject
200-
if (!keepOriginal) {
220+
bool actuallyKeepOriginal;
221+
switch(keepOriginal) {
222+
case KeepOriginal.Delete:
223+
actuallyKeepOriginal = false;
224+
break;
225+
case KeepOriginal.Keep:
226+
actuallyKeepOriginal = true;
227+
break;
228+
case KeepOriginal.Default:
229+
default:
230+
actuallyKeepOriginal = ExportSettings.keepOriginalAfterConvert;
231+
break;
232+
}
233+
if (!actuallyKeepOriginal) {
201234
Object.DestroyImmediate (toConvert);
202235
} else {
203236
// rename and put under scene root in case we need to check values
@@ -218,6 +251,7 @@ public static string IncrementFileName(string path, string filename)
218251
{
219252
string fileWithoutExt = Path.GetFileNameWithoutExtension (filename);
220253
string ext = Path.GetExtension (filename);
254+
// file, space, number, extension.
221255
string format = "{0} {1}{2}";
222256

223257
int index = 1;
@@ -226,10 +260,15 @@ public static string IncrementFileName(string path, string filename)
226260
var result = System.Text.RegularExpressions.Regex.Match(fileWithoutExt, @"\d+$");
227261
if (result != null) {
228262
var number = result.Value;
263+
264+
// Parse the number.
229265
int tempIndex;
230266
if (int.TryParse (number, out tempIndex)) {
231267
fileWithoutExt = fileWithoutExt.Remove (fileWithoutExt.LastIndexOf (number));
232-
format = "{0}{1}{2}"; // remove space from format
268+
// Change the format to remove the extra space we'd add
269+
// if there weren't already a number. Also, try to use the
270+
// same width (so Cube001 increments to Cube002, not Cube2).
271+
format = "{0}{1:D" + number.Length + "}{2}"; // file, number with padding, extension
233272
index = tempIndex+1;
234273
}
235274
}

Assets/FbxExporters/Editor/FbxExportSettings.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ public override void OnInspectorGUI() {
2828
EditorGUILayout.Space ();
2929
}
3030

31-
exportSettings.weldVertices = EditorGUILayout.Toggle ("Weld Vertices:", exportSettings.weldVertices);
32-
3331
exportSettings.mayaCompatibleNames = EditorGUILayout.Toggle (
3432
new GUIContent ("Convert to Maya Compatible Naming:",
3533
"In Maya some symbols such as spaces and accents get replaced when importing an FBX " +
@@ -156,7 +154,10 @@ public override void OnInspectorGUI() {
156154
}
157155
GUILayout.EndHorizontal ();
158156

159-
if (GUILayout.Button ("Install Unity Integration")) {
157+
var installIntegrationContent = new GUIContent(
158+
"Install Unity Integration",
159+
"Install and configure the Unity integration for Maya so that you can import and export directly to this project.");
160+
if (GUILayout.Button (installIntegrationContent)) {
160161
FbxExporters.Editor.IntegrationsUI.InstallMayaIntegration ();
161162
}
162163

@@ -191,10 +192,16 @@ public class ExportSettings : ScriptableSingleton<ExportSettings>
191192
;
192193

193194
// Note: default values are set in LoadDefaults().
194-
public bool weldVertices;
195195
public bool mayaCompatibleNames;
196196
public bool centerObjects;
197197

198+
/// <summary>
199+
/// In Convert-to-model, by default we delete the original object.
200+
/// This option lets you override that.
201+
/// </summary>
202+
[HideInInspector]
203+
public bool keepOriginalAfterConvert;
204+
198205
public int selectedMayaApp = 0;
199206

200207
[SerializeField]
@@ -222,9 +229,9 @@ public class ExportSettings : ScriptableSingleton<ExportSettings>
222229

223230
protected override void LoadDefaults()
224231
{
225-
weldVertices = true;
226232
mayaCompatibleNames = true;
227233
centerObjects = true;
234+
keepOriginalAfterConvert = false;
228235
convertToModelSavePath = kDefaultSavePath;
229236
turntableScene = null;
230237
mayaOptionPaths = null;

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -542,17 +542,16 @@ private void AssignLayerElementMaterial(FbxMesh fbxMesh, Mesh mesh, int material
542542
///
543543
/// Use fbxNode.GetMesh() to access the exported mesh.
544544
/// </summary>
545-
/// <param name="weldVertices">If set to <c>true</c>, combine identical vertices together into one Fbx vertex.</param>
546-
public void ExportMesh (Mesh mesh, FbxNode fbxNode, bool weldVertices = true, Material[] materials = null)
545+
public void ExportMesh (Mesh mesh, FbxNode fbxNode, Material[] materials = null)
547546
{
548547
var meshInfo = new MeshInfo(mesh, materials);
549-
ExportMesh(meshInfo, fbxNode, weldVertices);
548+
ExportMesh(meshInfo, fbxNode);
550549
}
551550

552551
/// <summary>
553552
/// Exports a unity mesh and attaches it to the node as an FbxMesh.
554553
/// </summary>
555-
void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode, bool weldVertices)
554+
void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode)
556555
{
557556
if (!meshInfo.IsValid) {
558557
return;
@@ -567,31 +566,20 @@ void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode, bool weldVertices)
567566

568567
// Create control points.
569568
Dictionary<Vector3, int> ControlPointToIndex = new Dictionary<Vector3, int> ();
570-
571-
int NumControlPoints = 0;
572-
if (weldVertices) {
573-
for (int v = 0; v < meshInfo.VertexCount; v++) {
574-
if (ControlPointToIndex.ContainsKey (meshInfo.Vertices [v])) {
569+
{
570+
var vertices = meshInfo.Vertices;
571+
for (int v = 0, n = meshInfo.VertexCount; v < n; v++) {
572+
if (ControlPointToIndex.ContainsKey (vertices [v])) {
575573
continue;
576574
}
577-
ControlPointToIndex [meshInfo.Vertices [v]] = NumControlPoints;
578-
579-
NumControlPoints++;
580-
}
581-
fbxMesh.InitControlPoints (NumControlPoints);
582-
583-
foreach (var controlPoint in ControlPointToIndex.Keys) {
584-
fbxMesh.SetControlPointAt (ConvertPositionToRightHanded(controlPoint),
585-
ControlPointToIndex [controlPoint]);
575+
ControlPointToIndex [vertices [v]] = ControlPointToIndex.Count();
586576
}
587-
} else {
588-
NumControlPoints = meshInfo.VertexCount;
589-
fbxMesh.InitControlPoints (NumControlPoints);
577+
fbxMesh.InitControlPoints (ControlPointToIndex.Count());
590578

591-
// copy control point data from Unity to FBX
592-
for (int v = 0; v < NumControlPoints; v++)
593-
{
594-
fbxMesh.SetControlPointAt(ConvertPositionToRightHanded(meshInfo.Vertices[v]), v);
579+
foreach (var kvp in ControlPointToIndex) {
580+
var controlPoint = kvp.Key;
581+
var index = kvp.Value;
582+
fbxMesh.SetControlPointAt (ConvertPositionToRightHanded(controlPoint), index);
595583
}
596584
}
597585

@@ -636,9 +624,7 @@ void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode, bool weldVertices)
636624
// properly export UVs, normals, binormals, etc.
637625
unmergedPolygons [current] = polyVert;
638626

639-
if (weldVertices) {
640-
polyVert = ControlPointToIndex [meshInfo.Vertices [polyVert]];
641-
}
627+
polyVert = ControlPointToIndex [meshInfo.Vertices [polyVert]];
642628
fbxMesh.AddPolygon (polyVert);
643629

644630
current++;
@@ -746,8 +732,7 @@ protected bool ExportInstance (GameObject unityGo, FbxNode fbxNode, FbxScene fbx
746732

747733
if (!SharedMeshes.TryGetValue (unityPrefabParent.name, out fbxMesh))
748734
{
749-
bool weldVertices = ExportSettings.weldVertices;
750-
ExportMesh (unityGo, fbxNode, weldVertices);
735+
ExportMesh (unityGo, fbxNode);
751736
if (fbxNode.GetMesh() != null) {
752737
SharedMeshes [unityPrefabParent.name] = fbxNode.GetMesh();
753738
}
@@ -812,8 +797,7 @@ protected int ExportComponents (
812797

813798
// try exporting mesh as an instance, export regularly if we cannot
814799
if (!ExportInstance (unityGo, fbxNode, fbxScene)) {
815-
bool weldVertices = ExportSettings.weldVertices;
816-
ExportMesh (unityGo, fbxNode, weldVertices);
800+
ExportMesh (unityGo, fbxNode);
817801
}
818802

819803
if (Verbose)
@@ -1494,7 +1478,7 @@ public static void UnRegisterMeshCallback(GetMeshForObject callback)
14941478
/// This goes through the callback system to find the right mesh and
14951479
/// allow plugins to substitute their own meshes.
14961480
/// </summary>
1497-
void ExportMesh (GameObject gameObject, FbxNode fbxNode, bool weldVertices)
1481+
void ExportMesh (GameObject gameObject, FbxNode fbxNode)
14981482
{
14991483
// First allow the object-based callbacks to have a hack at it.
15001484
foreach(var callback in MeshForObjectCallbacks) {
@@ -1547,14 +1531,14 @@ void ExportMesh (GameObject gameObject, FbxNode fbxNode, bool weldVertices)
15471531
if (meshFilter) {
15481532
var renderer = gameObject.GetComponent<Renderer>();
15491533
var materials = renderer ? renderer.sharedMaterials : null;
1550-
ExportMesh(new MeshInfo(meshFilter.sharedMesh, materials), fbxNode, weldVertices);
1534+
ExportMesh(new MeshInfo(meshFilter.sharedMesh, materials), fbxNode);
15511535
} else {
15521536
var smr = defaultComponent as SkinnedMeshRenderer;
15531537
if (smr) {
15541538
var mesh = new Mesh();
15551539
smr.BakeMesh(mesh);
15561540
var materials = smr.sharedMaterials;
1557-
ExportMesh(new MeshInfo(mesh, materials), fbxNode, weldVertices);
1541+
ExportMesh(new MeshInfo(mesh, materials), fbxNode);
15581542
Object.DestroyImmediate(mesh);
15591543
}
15601544
}

Assets/FbxExporters/Editor/UnitTests/ConvertToModelTest.cs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,23 @@ public void TestStaticHelpers()
2525
{
2626
var tempPath = Path.GetTempPath ();
2727
var basename = Path.GetFileNameWithoutExtension (Path.GetRandomFileName ());
28+
basename = basename + "yo"; // add some non-numeric stuff
2829

29-
var filename1 = basename + " 1.fbx";
30-
var filename2 = Path.Combine(tempPath, basename + " 2.fbx");
30+
var filename1 = basename + ".fbx";
31+
var filename2 = Path.Combine(tempPath, basename + " 1.fbx");
32+
Assert.AreEqual (filename2, ConvertToModel.IncrementFileName (tempPath, filename1));
33+
34+
filename1 = basename + " 1.fbx";
35+
filename2 = Path.Combine(tempPath, basename + " 2.fbx");
3136
Assert.AreEqual (filename2, ConvertToModel.IncrementFileName (tempPath, filename1));
3237

3338
filename1 = basename + "1.fbx";
3439
filename2 = Path.Combine(tempPath, basename + "2.fbx");
3540
Assert.AreEqual (filename2, ConvertToModel.IncrementFileName (tempPath, filename1));
3641

37-
filename1 = basename + "k.fbx";
38-
filename2 = Path.Combine(tempPath, basename + "k 1.fbx");
42+
// UNI-25513: bug was that Cube01.fbx => Cube2.fbx
43+
filename1 = basename + "01.fbx";
44+
filename2 = Path.Combine(tempPath, basename + "02.fbx");
3945
Assert.AreEqual (filename2, ConvertToModel.IncrementFileName (tempPath, filename1));
4046
}
4147

@@ -132,9 +138,9 @@ public void BasicTest()
132138
// Create a cube.
133139
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
134140

135-
// Convert it to a prefab.
141+
// Convert it to a prefab -- but keep the cube.
136142
var cubePrefabInstance = ConvertToModel.Convert(cube,
137-
directoryFullPath: path, keepOriginal: true);
143+
directoryFullPath: path, keepOriginal: ConvertToModel.KeepOriginal.Keep);
138144

139145
// Make sure it's what we expect.
140146
Assert.That(cube); // we kept the original
@@ -167,9 +173,20 @@ public void BasicTest()
167173
Assert.AreEqual(Path.GetFullPath(path), Path.GetDirectoryName(assetFullPath));
168174

169175
// Convert it again, make sure there's only one FbxPrefab (see UNI-25528).
176+
// Also make sure we deleted.
170177
var cubePrefabInstance2 = ConvertToModel.Convert(cubePrefabInstance,
171-
directoryFullPath: path, keepOriginal: false);
178+
directoryFullPath: path, keepOriginal: ConvertToModel.KeepOriginal.Delete);
179+
Assert.IsFalse(cubePrefabInstance);
172180
Assert.That(cubePrefabInstance2.GetComponents<FbxPrefab>().Length, Is.EqualTo(1));
181+
182+
// Create another cube, make sure the export settings drive whether we keep the cube or not.
183+
ConvertToModel.Convert(cube, directoryFullPath: path,
184+
keepOriginal: ConvertToModel.KeepOriginal.Default);
185+
if (ConvertToModel.ExportSettings.keepOriginalAfterConvert) {
186+
Assert.IsTrue(cube);
187+
} else {
188+
Assert.IsFalse(cube);
189+
}
173190
}
174191
}
175192
}

Assets/FbxExporters/Editor/UnitTests/FbxPrefabTest.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using NUnit.Framework;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using FbxExporters.Editor;
78

89
namespace FbxExporters.UnitTests
910
{
@@ -152,7 +153,7 @@ public void Init() {
152153

153154
// Convert it to FBX. The asset file will be deleted automatically
154155
// on termination.
155-
var fbxAsset = FbxExporters.Editor.ModelExporter.ExportObject(
156+
var fbxAsset = ModelExporter.ExportObject(
156157
GetRandomFbxFilePath(), m_original);
157158
m_source = AssetDatabase.LoadMainAssetAtPath(fbxAsset) as GameObject;
158159
m_originalHistory = Rep(m_source);
@@ -210,7 +211,7 @@ GameObject ModifySourceFbx()
210211
// enough, so the asset database knows to reload it. I was getting
211212
// test failures otherwise.
212213
SleepForFileTimestamp();
213-
FbxExporters.Editor.ModelExporter.ExportObjects (
214+
ModelExporter.ExportObjects (
214215
AssetDatabase.GetAssetPath(m_source),
215216
new Object[] { newModel } );
216217
AssetDatabase.Refresh();
@@ -291,7 +292,7 @@ public void BasicTest() {
291292
// Switch to some other model, which looks like the original model
292293
// (but is a totally different file). This will cause an update
293294
// immediately.
294-
var fbxAsset = FbxExporters.Editor.ModelExporter.ExportObject(
295+
var fbxAsset = ModelExporter.ExportObject(
295296
GetRandomFbxFilePath(), m_original);
296297
var newSource = AssetDatabase.LoadMainAssetAtPath(fbxAsset) as GameObject;
297298
Assert.IsTrue(newSource);
@@ -351,13 +352,13 @@ public void TestCubeAtRoot()
351352
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
352353
cube.name = "Cube";
353354
var cubeAssetPath = GetRandomFbxFilePath();
354-
var autoPrefab = FbxExporters.Editor.ConvertToModel.Convert(cube,
355+
var autoPrefab = ConvertToModel.Convert(cube,
355356
fbxFullPath: cubeAssetPath);
356357
Assert.IsTrue(autoPrefab);
357358

358359
// Make a maya locator.
359360
var locator = new GameObject("Cube");
360-
var locatorAssetPath = FbxExporters.Editor.ModelExporter.ExportObject(
361+
var locatorAssetPath = ModelExporter.ExportObject(
361362
GetRandomFbxFilePath(), locator);
362363

363364
// Check the prefab has all the default stuff it should have.
@@ -405,8 +406,9 @@ public void TestTransformAndReparenting()
405406
building3.transform.parent = building2.transform;
406407
building3.transform.localScale = new Vector3(.5f, .5f, .5f);
407408

408-
var original = FbxExporters.Editor.ConvertToModel.Convert (root,
409-
fbxFullPath: GetRandomFbxFilePath (), keepOriginal: true);
409+
var original = ConvertToModel.Convert (root,
410+
fbxFullPath: GetRandomFbxFilePath (),
411+
keepOriginal: ConvertToModel.KeepOriginal.Keep);
410412

411413
// Make sure it's OK.
412414
Assert.That (original.transform.GetChild (0).name, Is.EqualTo ("building2"));
@@ -417,7 +419,7 @@ public void TestTransformAndReparenting()
417419
// Modify the hierarchy, export to a new FBX, then copy the FBX under the prefab.
418420
root.SetActive(true);
419421
building2.name = "building2_renamed";
420-
var newCopyPath = FbxExporters.Editor.ModelExporter.ExportObject(
422+
var newCopyPath = ModelExporter.ExportObject(
421423
GetRandomFbxFilePath(), root);
422424
SleepForFileTimestamp();
423425
System.IO.File.Copy(

0 commit comments

Comments
 (0)