Skip to content

Commit c8085d4

Browse files
authored
Merge pull request #146 from Unity-Technologies/uni-25710-safe-to-delete
Uni 25710 and uni 25723: fbx export settings minor changes
2 parents 0a2f46c + 30ed0a7 commit c8085d4

File tree

5 files changed

+87
-53
lines changed

5 files changed

+87
-53
lines changed

Assets/FbxExporters/Editor/ConvertToModel.cs

Lines changed: 36 additions & 3 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

Assets/FbxExporters/Editor/FbxExportSettings.cs

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

30-
exportSettings.weldVertices = EditorGUILayout.Toggle ("Weld Vertices:", exportSettings.weldVertices);
31-
3230
exportSettings.mayaCompatibleNames = EditorGUILayout.Toggle (
3331
new GUIContent ("Convert to Maya Compatible Naming:",
3432
"In Maya some symbols such as spaces and accents get replaced when importing an FBX " +
@@ -121,10 +119,16 @@ public class ExportSettings : ScriptableSingleton<ExportSettings>
121119
public const string kDefaultSavePath = ".";
122120

123121
// Note: default values are set in LoadDefaults().
124-
public bool weldVertices;
125122
public bool mayaCompatibleNames;
126123
public bool centerObjects;
127124

125+
/// <summary>
126+
/// In Convert-to-model, by default we delete the original object.
127+
/// This option lets you override that.
128+
/// </summary>
129+
[HideInInspector]
130+
public bool keepOriginalAfterConvert;
131+
128132
[SerializeField]
129133
public UnityEngine.Object turntableScene;
130134

@@ -143,9 +147,9 @@ public class ExportSettings : ScriptableSingleton<ExportSettings>
143147

144148
protected override void LoadDefaults()
145149
{
146-
weldVertices = true;
147150
mayaCompatibleNames = true;
148151
centerObjects = true;
152+
keepOriginalAfterConvert = false;
149153
convertToModelSavePath = kDefaultSavePath;
150154
turntableScene = null;
151155
}

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: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ public void BasicTest()
138138
// Create a cube.
139139
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
140140

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

145145
// Make sure it's what we expect.
146146
Assert.That(cube); // we kept the original
@@ -173,9 +173,20 @@ public void BasicTest()
173173
Assert.AreEqual(Path.GetFullPath(path), Path.GetDirectoryName(assetFullPath));
174174

175175
// Convert it again, make sure there's only one FbxPrefab (see UNI-25528).
176+
// Also make sure we deleted.
176177
var cubePrefabInstance2 = ConvertToModel.Convert(cubePrefabInstance,
177-
directoryFullPath: path, keepOriginal: false);
178+
directoryFullPath: path, keepOriginal: ConvertToModel.KeepOriginal.Delete);
179+
Assert.IsFalse(cubePrefabInstance);
178180
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+
}
179190
}
180191
}
181192
}

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)