Skip to content

Commit

Permalink
Merge pull request #314 from Unity-Technologies/UNI-23144-convert-to-…
Browse files Browse the repository at this point in the history
…prefab-dont-override-fbx

Uni 23144 convert to prefab dont override fbx
  • Loading branch information
vkovec authored Feb 23, 2018
2 parents 2d18ef0 + d32b6a1 commit b9355a0
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 4 deletions.
43 changes: 39 additions & 4 deletions Assets/FbxExporters/Editor/ConvertToModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,29 @@ public static GameObject Convert (
string directoryFullPath = null,
string fbxFullPath = null)
{
// Only create the prefab (no FBX export) if we have selected the root of a model prefab instance.
// Children of model prefab instances will also have "model prefab instance"
// as their prefab type, so it is important that it is the root that is selected.
//
// e.g. If I have the following hierarchy:
// Cube
// -- Sphere
//
// Both the Cube and Sphere will have ModelPrefabInstance as their prefab type.
// However, when selecting the Sphere to convert, we don't want to connect it to the
// existing FBX but create a new FBX containing just the sphere.
PrefabType unityPrefabType = PrefabUtility.GetPrefabType(toConvert);
if (unityPrefabType == PrefabType.ModelPrefabInstance && toConvert.Equals(PrefabUtility.FindPrefabRoot(toConvert))) {
// don't re-export fbx
// create prefab out of model instance in scene, link to existing fbx
var mainAsset = PrefabUtility.GetPrefabParent(toConvert) as GameObject;
var mainAssetRelPath = AssetDatabase.GetAssetPath(mainAsset);
var mainAssetAbsPath = Directory.GetParent(Application.dataPath) + "/" + mainAssetRelPath;
SetupFbxPrefab(toConvert, mainAsset, mainAssetRelPath, mainAssetAbsPath);

return toConvert;
}

if (string.IsNullOrEmpty(fbxFullPath)) {
// Generate a unique filename.
if (string.IsNullOrEmpty (directoryFullPath)) {
Expand Down Expand Up @@ -155,12 +178,27 @@ public static GameObject Convert (
// relative to the project, not relative to the assets folder.
var unityMainAsset = AssetDatabase.LoadMainAssetAtPath (projectRelativePath) as GameObject;
if (!unityMainAsset) {
throw new System.Exception ("Failed to convert " + toConvert.name);;
throw new System.Exception ("Failed to convert " + toConvert.name);
}

// Copy the mesh/materials from the FBX
UpdateFromSourceRecursive (toConvert, unityMainAsset);

SetupFbxPrefab (toConvert, unityMainAsset, projectRelativePath, fbxFullPath);

toConvert.name = Path.GetFileNameWithoutExtension (fbxFullPath);
return toConvert;
}


/// <summary>
/// Create the prefab and connect it to the given fbx asset.
/// </summary>
/// <param name="toConvert">Hierarchy to convert.</param>
/// <param name="unityMainAsset">Main asset in the FBX.</param>
/// <param name="projectRelativePath">Fbx project relative path.</param>
/// <param name="fbxFullPath">Fbx full path.</param>
public static void SetupFbxPrefab(GameObject toConvert, GameObject unityMainAsset, string projectRelativePath, string fbxFullPath){
// Set up the FbxPrefab component so it will auto-update.
// Make sure to delete whatever FbxPrefab history we had.
var fbxPrefab = toConvert.GetComponent<FbxPrefab>();
Expand All @@ -179,9 +217,6 @@ public static GameObject Convert (
string.Format("Failed to create prefab asset in [{0}] from fbx [{1}]",
prefabFileName, fbxFullPath));
}

toConvert.name = Path.GetFileNameWithoutExtension (fbxFullPath);
return toConvert;
}

/// <summary>
Expand Down
54 changes: 54 additions & 0 deletions Assets/FbxExporters/Editor/UnitTests/ConvertToModelTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,5 +256,59 @@ public void TestInstanceNameMatchesFilename()

Assert.AreEqual (Path.GetFileNameWithoutExtension (path), cube.name);
}

[Test]
public void TestConvertModelInstance()
{
// expected result: prefab is linked to originally exported
// fbx and no new fbx is created.

// create hierarchy (Cube->Sphere)
var cube = GameObject.CreatePrimitive (PrimitiveType.Cube);
var sphere = GameObject.CreatePrimitive (PrimitiveType.Sphere);

sphere.transform.SetParent (cube.transform);

// export using regular model export
var filename = GetRandomFileNamePath();
GameObject fbxObj = ExportSelection (filename, cube);

// add back to scene
GameObject fbxInstance = PrefabUtility.InstantiatePrefab (fbxObj) as GameObject;
Assert.That (fbxInstance, Is.Not.Null);

// attach some components
var rigidBody = fbxInstance.AddComponent<Rigidbody> ();
Assert.That (rigidBody, Is.Not.Null);

var instanceSphere = fbxInstance.transform.GetChild (0);
Assert.That (instanceSphere, Is.Not.Null);

var boxCollider = instanceSphere.gameObject.AddComponent<BoxCollider> ();
Assert.That (boxCollider, Is.Not.Null);

// convert to prefab
GameObject converted = ConvertToModel.Convert (fbxInstance, Path.GetDirectoryName(filename));
Assert.That (converted, Is.EqualTo (fbxInstance));

// check meshes link to original fbx
var prefabCubeMesh = fbxInstance.GetComponent<MeshFilter>().sharedMesh;
Assert.That (prefabCubeMesh, Is.Not.Null);

var fbxObjAssetPath = AssetDatabase.GetAssetPath (fbxObj);

Assert.That (AssetDatabase.GetAssetPath (prefabCubeMesh), Is.EqualTo (fbxObjAssetPath));

var prefabSphere = fbxInstance.transform.GetChild (0);
Assert.That (prefabSphere, Is.Not.Null);
var prefabSphereMesh = prefabSphere.GetComponent<MeshFilter> ().sharedMesh;
Assert.That (prefabSphere, Is.Not.Null);

Assert.That (AssetDatabase.GetAssetPath (prefabSphereMesh), Is.EqualTo (fbxObjAssetPath));

// check that components are still there
Assert.That (fbxInstance.GetComponent<Rigidbody>(), Is.Not.Null);
Assert.That (prefabSphere.GetComponent<BoxCollider> (), Is.Not.Null);
}
}
}
3 changes: 3 additions & 0 deletions Assets/FbxExporters/Editor/UnitTests/ExporterTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ protected virtual GameObject ExportSelection(params Object[] selected)
{
// export selected to a file, then return the root
var filename = GetRandomFileNamePath();
return ExportSelection (filename, selected);
}

protected virtual GameObject ExportSelection(string filename, params Object[] selected){
Debug.unityLogger.logEnabled = false;
var fbxFileName = FbxExporters.Editor.ModelExporter.ExportObjects (filename, selected) as string;
Debug.unityLogger.logEnabled = true;
Expand Down

0 comments on commit b9355a0

Please sign in to comment.