Skip to content

Commit c31e7e6

Browse files
committed
code review fixes
-remove KeepOriginal -don't instantiate FBX or modify any transforms/sibling indices -don't abreviate "Renderer"
1 parent 5bdbea2 commit c31e7e6

File tree

3 files changed

+70
-158
lines changed

3 files changed

+70
-158
lines changed

Assets/FbxExporters/Editor/ConvertToModel.cs

Lines changed: 65 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,6 @@ 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-
7565
/// <summary>
7666
/// Gets the export settings.
7767
/// </summary>
@@ -89,11 +79,9 @@ public static EditorTools.ExportSettings ExportSettings {
8979
/// <returns>list of instanced Model Prefabs</returns>
9080
/// <param name="unityGameObjectsToConvert">Unity game objects to convert to Model Prefab instances</param>
9181
/// <param name="path">Path to save Model Prefab; use FbxExportSettings if null</param>
92-
/// <param name="keepOriginal">If set to <c>true</c> keep original gameobject hierarchy.</param>
9382
public static GameObject[] CreateInstantiatedModelPrefab (
9483
GameObject [] unityGameObjectsToConvert,
95-
string directoryFullPath = null,
96-
KeepOriginal keepOriginal = KeepOriginal.Default)
84+
string directoryFullPath = null)
9785
{
9886
if (directoryFullPath == null) {
9987
directoryFullPath = FbxExporters.EditorTools.ExportSettings.GetAbsoluteSavePath();
@@ -106,8 +94,7 @@ public static GameObject[] CreateInstantiatedModelPrefab (
10694
foreach(var go in toExport) {
10795
try {
10896
wasExported.Add(Convert(go,
109-
directoryFullPath: directoryFullPath,
110-
keepOriginal: keepOriginal));
97+
directoryFullPath: directoryFullPath));
11198
} catch(System.Exception xcp) {
11299
Debug.LogException(xcp);
113100
}
@@ -121,8 +108,6 @@ public static GameObject[] CreateInstantiatedModelPrefab (
121108
/// This returns a new object; the converted object may be modified or destroyed.
122109
///
123110
/// This refreshes the asset database.
124-
///
125-
/// If "keepOriginal" is set, the converted object is modified but remains in the scene.
126111
/// </summary>
127112
/// <returns>The instance that replaces 'toConvert' in the scene.</returns>
128113
/// <param name="toConvert">GameObject hierarchy to replace with a prefab.</param>
@@ -134,12 +119,10 @@ public static GameObject[] CreateInstantiatedModelPrefab (
134119
/// to a directory in which to put the fbx file. Ignored if
135120
/// fbxFullPath is specified. May be null, in which case we use the
136121
/// export settings.</param>
137-
/// <param name="keepOriginal">If set to <c>true</c>, keep the original in the scene.</param>
138122
public static GameObject Convert (
139123
GameObject toConvert,
140124
string directoryFullPath = null,
141-
string fbxFullPath = null,
142-
KeepOriginal keepOriginal = KeepOriginal.Default)
125+
string fbxFullPath = null)
143126
{
144127
if (string.IsNullOrEmpty(fbxFullPath)) {
145128
// Generate a unique filename.
@@ -182,68 +165,28 @@ public static GameObject Convert (
182165
throw new System.Exception ("Failed to convert " + toConvert.name);;
183166
}
184167

185-
// Instantiate the FBX file.
186-
var unityGO = PrefabUtility.InstantiatePrefab (unityMainAsset, toConvert.scene)
187-
as GameObject;
188-
if (!unityGO) {
189-
throw new System.Exception ("Failed to convert " + toConvert.name);;
190-
}
191-
192-
// Copy the components over to the instance of the FBX.
193-
SetupImportedGameObject (toConvert, unityGO);
194-
195-
// temporary quick fix
196-
var temp = toConvert;
197-
toConvert = unityGO;
198-
unityGO = temp;
168+
// Copy the mesh/materials from the FBX
169+
UpdateFromFBX (toConvert, unityMainAsset);
199170

200171
// Set up the FbxPrefab component so it will auto-update.
201172
// Make sure to delete whatever FbxPrefab history we had.
202-
var fbxPrefab = unityGO.GetComponent<FbxPrefab>();
173+
var fbxPrefab = toConvert.GetComponent<FbxPrefab>();
203174
if (fbxPrefab) {
204175
Object.DestroyImmediate(fbxPrefab);
205176
}
206-
fbxPrefab = unityGO.AddComponent<FbxPrefab>();
177+
fbxPrefab = toConvert.AddComponent<FbxPrefab>();
207178
fbxPrefab.SetSourceModel(unityMainAsset);
208179

209-
// Disconnect from the FBX file.
210-
PrefabUtility.DisconnectPrefabInstance(unityGO);
211-
212180
// Create a prefab from the instantiated and componentized unityGO.
213181
var prefabFileName = Path.ChangeExtension(projectRelativePath, ".prefab");
214-
var prefab = PrefabUtility.CreatePrefab(prefabFileName, unityGO);
182+
var prefab = PrefabUtility.CreatePrefab(prefabFileName, toConvert, ReplacePrefabOptions.ConnectToPrefab);
215183
if (!prefab) {
216184
throw new System.Exception(
217185
string.Format("Failed to create prefab asset in [{0}] from fbx [{1}]",
218186
prefabFileName, fbxFullPath));
219187
}
220188

221-
// Connect to the prefab file.
222-
unityGO = PrefabUtility.ConnectGameObjectToPrefab(unityGO, prefab);
223-
224-
// Remove (now redundant) gameobject
225-
bool actuallyKeepOriginal;
226-
switch(keepOriginal) {
227-
case KeepOriginal.Delete:
228-
actuallyKeepOriginal = false;
229-
break;
230-
case KeepOriginal.Keep:
231-
actuallyKeepOriginal = true;
232-
break;
233-
case KeepOriginal.Default:
234-
default:
235-
actuallyKeepOriginal = ExportSettings.keepOriginalAfterConvert;
236-
break;
237-
}
238-
if (!actuallyKeepOriginal) {
239-
Object.DestroyImmediate (toConvert);
240-
} else {
241-
// rename and put under scene root in case we need to check values
242-
toConvert.name = "_safe_to_delete_" + toConvert.name;
243-
toConvert.SetActive (false);
244-
}
245-
246-
return unityGO;
189+
return toConvert;
247190
}
248191

249192
/// <summary>
@@ -318,73 +261,75 @@ public static void EnforceUniqueNames(IEnumerable<GameObject> exportSet)
318261
}
319262

320263
/// <summary>
321-
/// Sets up the imported GameObject to match the original.
322-
/// - Updates the name to be the same as original (i.e. remove the "(Clone)")
323-
/// - Moves the imported object to the correct position in the hierarchy
324-
/// - Updates the transform of the imported GameObject to match the original
325-
/// - Copy over missing components and component values
264+
/// Updates the meshes and materials of the exported GameObjects
265+
/// to link to those imported from the FBX.
326266
/// </summary>
327-
/// <param name="orig">Original GameObject.</param>
328-
/// <param name="imported">Imported GameObject.</param>
329-
public static void SetupImportedGameObject(GameObject orig, GameObject imported)
267+
/// <param name="orig">Original.</param>
268+
/// <param name="fbx">Fbx.</param>
269+
public static void UpdateFromFBX(GameObject orig, GameObject fbx)
330270
{
331-
Transform importedTransform = imported.transform;
332-
Transform origTransform = orig.transform;
333-
334-
// configure transform and maintain local pose
335-
importedTransform.SetParent (origTransform.parent, false);
336-
importedTransform.SetSiblingIndex (origTransform.GetSiblingIndex());
337-
338-
// copy the components over, assuming that the hierarchy order is unchanged
339-
if (origTransform.hierarchyCount != importedTransform.hierarchyCount) {
340-
Debug.LogWarning (string.Format ("Warning: Exported {0} objects, but only imported {1}",
341-
origTransform.hierarchyCount, importedTransform.hierarchyCount));
271+
// recurse over orig, for each transform finding the corresponding transform in the FBX
272+
// and copying the meshes and materials over from the FBX
273+
var goDict = GetNameToFbxGameObject(orig, fbx);
274+
var q = new Queue<Transform> ();
275+
q.Enqueue (orig.transform);
276+
while (q.Count > 0) {
277+
var t = q.Dequeue ();
278+
279+
if (goDict [t.name] == null) {
280+
Debug.LogWarning (string.Format ("Warning: Could not find Object {0} in FBX", t.name));
281+
continue;
282+
}
283+
CopyComponents (t.gameObject, goDict [t.name]);
284+
foreach (Transform child in t) {
285+
q.Enqueue (child);
286+
}
342287
}
343-
FixSiblingOrder (orig.transform, imported.transform);
344-
345-
// the imported GameObject will have the same name as the file to which it was imported from,
346-
// which might not be the same name as the original GameObject
347-
CopyComponentsRecursive (orig, imported, namesExpectedMatch:false);
348288
}
349289

350290
/// <summary>
351-
/// Given two hierarchies of nodes whose names match up,
352-
/// make the 'imported' hierarchy have its children be in the same
353-
/// order as the 'orig' hierarchy.
354-
///
355-
/// The 'orig' hierarchy is not modified.
291+
/// Gets a dictionary linking exported GameObject name to fbx game object.
356292
/// </summary>
357-
public static void FixSiblingOrder(Transform orig, Transform imported){
358-
foreach (Transform origChild in orig) {
359-
Transform importedChild = imported.Find (origChild.name);
360-
if (importedChild == null) {
361-
Debug.LogWarning (string.Format(
362-
"Warning: Could not find {0} in parented under {1} in import hierarchy",
363-
origChild.name, imported.name
364-
));
365-
continue;
293+
/// <returns>Dictionary containing the name to fbx game object.</returns>
294+
/// <param name="orig">Original.</param>
295+
/// <param name="fbx">Fbx.</param>
296+
private static Dictionary<string,GameObject> GetNameToFbxGameObject(GameObject orig, GameObject fbx){
297+
var nameToGO = new Dictionary<string,GameObject> ();
298+
299+
var q = new Queue<Transform> ();
300+
q.Enqueue (orig.transform);
301+
while (q.Count > 0) {
302+
var t = q.Dequeue ();
303+
nameToGO [t.name] = null;
304+
foreach (Transform child in t) {
305+
q.Enqueue (child);
366306
}
367-
importedChild.SetSiblingIndex (origChild.GetSiblingIndex ());
368-
FixSiblingOrder (origChild, importedChild);
369307
}
370-
}
371308

372-
private static void CopyComponentsRecursive(GameObject from, GameObject to, bool namesExpectedMatch = true){
373-
if (namesExpectedMatch && !to.name.StartsWith(from.name) || from.transform.childCount != to.transform.childCount) {
374-
Debug.LogError (string.Format("Error: hierarchies don't match (From: {0}, To: {1})", from.name, to.name));
375-
return;
309+
nameToGO [orig.name] = fbx;
310+
311+
var fbxQ = new Queue<Transform> ();
312+
foreach (Transform child in fbx.transform) {
313+
fbxQ.Enqueue (child);
376314
}
377315

378-
CopyComponents (from, to);
379-
for (int i = 0; i < from.transform.childCount; i++) {
380-
CopyComponentsRecursive(from.transform.GetChild(i).gameObject, to.transform.GetChild(i).gameObject);
316+
while (fbxQ.Count > 0) {
317+
var t = fbxQ.Dequeue ();
318+
if (!nameToGO.ContainsKey (t.name)) {
319+
Debug.LogWarning (string.Format("Warning: {0} in FBX but not in converted hierarchy", t.name));
320+
continue;
321+
}
322+
nameToGO [t.name] = t.gameObject;
323+
foreach (Transform child in t) {
324+
fbxQ.Enqueue (child);
325+
}
381326
}
382-
}
383327

328+
return nameToGO;
329+
}
384330

385331
/// <summary>
386-
/// Copy components on the 'from' object which is the object
387-
/// in the scene that we imported from the FBX,
332+
/// Copy components on the 'from' object which is the FBX,
388333
/// over to the 'to' object which is the object in the
389334
/// scene we exported.
390335
///
@@ -430,9 +375,9 @@ public static void CopyComponents(GameObject to, GameObject from){
430375
} else if (toComponent is MeshFilter) {
431376
EditorJsonUtility.FromJsonOverwrite (json, toComponent);
432377
} else if (toComponent is Renderer) {
433-
var toRen = toComponent as Renderer;
434-
var fromRen = component as Renderer;
435-
toRen.sharedMaterials = fromRen.sharedMaterials;
378+
var toRenderer = toComponent as Renderer;
379+
var fromRenderer = component as Renderer;
380+
toRenderer.sharedMaterials = fromRenderer.sharedMaterials;
436381
}
437382
}
438383
}

Assets/FbxExporters/Editor/UnitTests/ConvertToModelTest.cs

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -58,37 +58,6 @@ public void TestStaticHelpers()
5858
Assert.AreEqual("a 2", a2.name);
5959
}
6060

61-
// Test FixSiblingOrder
62-
{
63-
var a = new GameObject("a").transform;
64-
var b = new GameObject("a").transform;
65-
66-
var a1 = new GameObject("a1").transform;
67-
var a2 = new GameObject("a2").transform;
68-
var a3 = new GameObject("a3").transform;
69-
70-
var b1 = new GameObject("a1").transform;
71-
var b2 = new GameObject("a2").transform;
72-
var b3 = new GameObject("a3").transform;
73-
74-
a1.parent = a;
75-
a2.parent = a;
76-
a3.parent = a;
77-
78-
b3.parent = b;
79-
b1.parent = b;
80-
b2.parent = b;
81-
82-
// Assert same set, different order.
83-
Assert.That(ChildNames(b), Is.EquivalentTo(ChildNames(a)));
84-
Assert.That(ChildNames(b), Is.Not.EqualTo(ChildNames(a)));
85-
86-
// Fix the sibling order. Now we have same set, same order!
87-
ConvertToModel.FixSiblingOrder(a, b);
88-
Assert.That(ChildNames(b), Is.EquivalentTo(ChildNames(a)));
89-
Assert.That(ChildNames(b), Is.EqualTo(ChildNames(a)));
90-
}
91-
9261
// Test CopyComponents
9362
{
9463
var a = new GameObject("a");
@@ -121,7 +90,7 @@ public void TestStaticHelpers()
12190
Assert.AreEqual ("BB", b.transform.GetChild (1).name);
12291
Assert.AreEqual (Vector3.zero, b1.transform.localPosition);
12392

124-
ConvertToModel.SetupImportedGameObject (a, b);
93+
ConvertToModel.UpdateFromFBX (a, b);
12594

12695
Assert.IsTrue (b.GetComponent<BoxCollider> ());
12796
Assert.AreEqual ("AA", b.transform.GetChild (1).name);
@@ -140,7 +109,7 @@ public void BasicTest()
140109

141110
// Convert it to a prefab -- but keep the cube.
142111
var cubePrefabInstance = ConvertToModel.Convert(cube,
143-
directoryFullPath: path, keepOriginal: ConvertToModel.KeepOriginal.Keep);
112+
directoryFullPath: path);
144113

145114
// Make sure it's what we expect.
146115
Assert.That(cube); // we kept the original
@@ -175,13 +144,12 @@ public void BasicTest()
175144
// Convert it again, make sure there's only one FbxPrefab (see UNI-25528).
176145
// Also make sure we deleted.
177146
var cubePrefabInstance2 = ConvertToModel.Convert(cubePrefabInstance,
178-
directoryFullPath: path, keepOriginal: ConvertToModel.KeepOriginal.Delete);
147+
directoryFullPath: path);
179148
Assert.IsFalse(cubePrefabInstance);
180149
Assert.That(cubePrefabInstance2.GetComponents<FbxPrefab>().Length, Is.EqualTo(1));
181150

182151
// 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);
152+
ConvertToModel.Convert(cube, directoryFullPath: path);
185153
if (ConvertToModel.ExportSettings.keepOriginalAfterConvert) {
186154
Assert.IsTrue(cube);
187155
} else {

Assets/FbxExporters/Editor/UnitTests/FbxPrefabTest.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,7 @@ public void TestTransformAndReparenting()
407407
building3.transform.localScale = new Vector3(.5f, .5f, .5f);
408408

409409
var original = ConvertToModel.Convert (root,
410-
fbxFullPath: GetRandomFbxFilePath (),
411-
keepOriginal: ConvertToModel.KeepOriginal.Keep);
410+
fbxFullPath: GetRandomFbxFilePath ());
412411

413412
// Make sure it's OK.
414413
Assert.That (original.transform.GetChild (0).name, Is.EqualTo ("building2"));

0 commit comments

Comments
 (0)