public void SaveMeshesToOutputFolderAndAssignToSMRs(Mesh[] targetMeshes, SkinnedMeshRenderer[] targetSMRs)
        {
            //validate meshes
            for (int i = 0; i < targetMeshes.Length; i++)
            {
                if (targetSMRs[i] == null)
                {
                    Debug.LogError(string.Format("Target Mesh {0} is null", i));
                    return;
                }

                if (targetSMRs[i].sharedMesh == null)
                {
                    Debug.LogError(string.Format("Target Mesh {0} does not have a mesh", i));
                    return;
                }
                MB_PrefabType pt = MBVersionEditor.GetPrefabType(targetMeshes[i]);
                if (pt == MB_PrefabType.modelPrefab)
                {
                    Debug.LogError(string.Format("Target Mesh {0} is an imported model prefab. Can't modify these meshes because changes will be overwritten the next time the model is saved or reimported. Try instantiating the prefab and using skinned meshes from the scene instance.", i));
                    return;
                }
            }
            //validate output folder
            if (outputFolderProp.stringValue == null)
            {
                Debug.LogError("Output folder must be set");
                return;
            }
            if (outputFolderProp.stringValue.StartsWith(Application.dataPath))
            {
                string relativePath = "Assets" + outputFolderProp.stringValue.Substring(Application.dataPath.Length);
                string gid          = AssetDatabase.AssetPathToGUID(relativePath);
                if (gid == null)
                {
                    Debug.LogError("Output folder must be a folder in the Unity project Asset folder");
                    return;
                }
            }
            else
            {
                Debug.LogError("Output folder must be a folder in the Unity project Asset folder");
                return;
            }
            for (int i = 0; i < targetMeshes.Length; i++)
            {
                Mesh   m   = targetMeshes[i];
                string pth = ConvertAbsolutePathToUnityPath(outputFolderProp.stringValue + "/" + targetMeshes[i].name + ".Asset");
                if (pth == null)
                {
                    Debug.LogError("The output folder must be a folder in the project Assets folder.");
                    return;
                }
                AssetDatabase.CreateAsset(m, pth);
                targetSMRs[i].sharedMesh = m;
                Debug.Log(string.Format("Created mesh at {0}. Updated Skinned Mesh {1} to use created mesh.", pth, targetSMRs[i].name));
            }
            AssetDatabase.SaveAssets();
        }
        public void SaveMeshesToOutputFolderAndAssignToSMRs(Mesh[] targetMeshes, SkinnedMeshRenderer[] targetSMRs)
        {
            //validate meshes
            for (int i = 0; i < targetMeshes.Length; i++)
            {
                if (targetSMRs[i] == null)
                {
                    Debug.LogError(string.Format("Target Mesh {0} is null", i));
                    return;
                }

                if (targetSMRs[i].sharedMesh == null)
                {
                    Debug.LogError(string.Format("Target Mesh {0} does not have a mesh", i));
                    return;
                }
                MB_PrefabType pt = MBVersionEditor.PrefabUtility_GetPrefabType(targetMeshes[i]);
                if (pt == MB_PrefabType.modelPrefabAsset)
                {
                    Debug.LogError(string.Format("Target Mesh {0} is an imported model prefab. Can't modify these meshes because changes will be overwritten the next time the model is saved or reimported. Try instantiating the prefab and using skinned meshes from the scene instance.", i));
                    return;
                }
            }
            //validate output folder
            if (outputFolderProp.stringValue == null)
            {
                Debug.LogError("Output folder must be set");
                return;
            }
            else
            {
                if (!MB_BatchPrefabBakerEditorFunctions.ValidateFolderIsInProject("Output Folder", outputFolderProp.stringValue))
                {
                    return;
                }
            }
            for (int i = 0; i < targetMeshes.Length; i++)
            {
                Mesh   m   = targetMeshes[i];
                string pth = MB_BatchPrefabBakerEditorFunctions.ConvertAnyPathToProjectRelativePath(outputFolderProp.stringValue + "/" + targetMeshes[i].name + ".Asset");
                if (pth == null)
                {
                    Debug.LogError("The output folder must be a folder in the project Assets folder.");
                    return;
                }
                AssetDatabase.CreateAsset(m, pth);
                targetSMRs[i].sharedMesh = m;
                Debug.Log(string.Format("Created mesh at {0}. Updated Skinned Mesh {1} to use created mesh.", pth, targetSMRs[i].name));
            }
            AssetDatabase.SaveAssets();
        }
Ejemplo n.º 3
0
        public static void AddDroppedObjects(object[] objs, MB3_MeshBakerRoot momm)
        {
            if (objs != null)
            {
                HashSet <Renderer> renderersToAdd = new HashSet <Renderer>();
                for (int i = 0; i < objs.Length; i++)
                {
                    object obj = objs[i];
                    if (obj is GameObject)
                    {
                        Renderer[] rs = ((GameObject)obj).GetComponentsInChildren <Renderer>();
                        for (int j = 0; j < rs.Length; j++)
                        {
                            if (rs[j] is MeshRenderer || rs[j] is SkinnedMeshRenderer)
                            {
                                renderersToAdd.Add(rs[j]);
                            }
                        }
                    }
                }

                int numAdded = 0;
                List <GameObject> objsToCombine = momm.GetObjectsToCombine();
                bool failedToAddAssets          = false;
                foreach (Renderer r in renderersToAdd)
                {
                    if (!objsToCombine.Contains(r.gameObject))
                    {
                        MB_PrefabType prefabType = MBVersionEditor.GetPrefabType(r.gameObject);
                        if (prefabType == MB_PrefabType.modelPrefab || prefabType == MB_PrefabType.prefab)
                        {
                            failedToAddAssets = true;
                        }
                        else
                        {
                            objsToCombine.Add(r.gameObject);
                            numAdded++;
                        }
                    }
                }

                if (failedToAddAssets)
                {
                    Debug.LogError("Did not add some object(s) because they are not scene objects");
                }
                Debug.Log("Added " + numAdded + " renderers");
            }
        }
Ejemplo n.º 4
0
        private static List <GameObject> FindAllPrefabInstances(UnityEngine.Object myPrefab)
        {
            List <GameObject> result = new List <GameObject>();

            GameObject[] allObjects = (GameObject[])GameObject.FindObjectsOfType(typeof(GameObject));
            foreach (GameObject go in allObjects)
            {
                MB_PrefabType objPrefabType = MBVersionEditor.PrefabUtility_GetPrefabType(go);
                if (objPrefabType == MB_PrefabType.scenePefabInstance)
                {
                    UnityEngine.Object GO_prefab = MBVersionEditor.PrefabUtility_GetCorrespondingObjectFromSource(go);
                    if (myPrefab == GO_prefab)
                    {
                        result.Add(go);
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 5
0
 public bool CheckPrefabTypes(MB_ObjsToCombineTypes objToCombineType, List <GameObject> objsToMesh)
 {
     for (int i = 0; i < objsToMesh.Count; i++)
     {
         MB_PrefabType pt = MBVersionEditor.GetPrefabType(objsToMesh[i]);
         if (pt == MB_PrefabType.sceneInstance)
         {
             // these are scene objects
             if (objToCombineType == MB_ObjsToCombineTypes.prefabOnly)
             {
                 Debug.LogWarning("The list of objects to combine contains scene objects. You probably want prefabs. If using scene objects ensure position is zero, rotation is zero and scale is one. Translation, Rotation and Scale will be baked into the generated mesh." + objsToMesh[i] + " is a scene object");
                 return(false);
             }
         }
         else if (objToCombineType == MB_ObjsToCombineTypes.sceneObjOnly)
         {
             //these are prefabs
             Debug.LogWarning("The list of objects to combine contains prefab assets. You probably want scene objects." + objsToMesh[i] + " is a prefab object");
             return(false);
         }
     }
     return(true);
 }
    /// <summary>
    /// We will modify the source object so duplicate them
    /// </summary>
    /// <param name="tempGameObjectInstances"></param>
    public static void _DuplicateSrcObjectInstancesAndUnpack(MB_RenderType renderType, GameObject[] objsToCombine, List <Transform> tempGameObjectInstances)
    {
        Debug.Assert(renderType == MB_RenderType.skinnedMeshRenderer, "RenderType must be Skinned Mesh Renderer");
        // first pass, collect the prefab-instance roots for each of the src objects.
        Transform[] sceneInstanceParents = new Transform[objsToCombine.Length];
        for (int i = 0; i < objsToCombine.Length; i++)
        {
            // Get the prefab root
            GameObject pr = null;
            {
                MB_PrefabType pt = MBVersionEditor.PrefabUtility_GetPrefabType(objsToCombine[i]);
                if (pt == MB_PrefabType.scenePefabInstance || pt == MB_PrefabType.isInstanceAndNotAPartOfAnyPrefab)
                {
                    pr = MBVersionEditor.PrefabUtility_GetPrefabInstanceRoot(objsToCombine[i]);
                }

                if (pr == null)
                {
                    pr = _FindCommonAncestorForBonesAnimatorAndSmr(objsToCombine[i]);
                }
            }

            sceneInstanceParents[i] = pr.transform;
        }

        // second pass, some of the parents could be children of other parents. ensure that we are
        // using the uppermost ancestor for all.
        for (int i = 0; i < objsToCombine.Length; i++)
        {
            sceneInstanceParents[i] = _FindUppermostParent(objsToCombine[i], sceneInstanceParents);
        }

        // Now build a map of sceneInstanceParents to the renderers contained beneath.
        Dictionary <Transform, List <Transform> > srcPrefabInstances2Renderers = new Dictionary <Transform, List <Transform> >();

        for (int i = 0; i < objsToCombine.Length; i++)
        {
            List <Transform> renderersUsed;
            if (!srcPrefabInstances2Renderers.TryGetValue(sceneInstanceParents[i], out renderersUsed))
            {
                renderersUsed = new List <Transform>();
                srcPrefabInstances2Renderers.Add(sceneInstanceParents[i], renderersUsed);
            }

            renderersUsed.Add(objsToCombine[i].transform);
        }

        // Duplicate the prefab-instance-root scene objects
        List <Transform> srcRoots  = new List <Transform>(srcPrefabInstances2Renderers.Keys);
        List <Transform> targRoots = new List <Transform>();

        for (int i = 0; i < srcRoots.Count; i++)
        {
            Transform  src = srcRoots[i];
            GameObject n   = GameObject.Instantiate <GameObject>(src.gameObject);
            n.transform.rotation   = src.rotation;
            n.transform.position   = src.position;
            n.transform.localScale = src.localScale;
            targRoots.Add(n.transform);
            tempGameObjectInstances.Add(targRoots[i]);
            _CheckSrcRootScale(renderType, src);
        }

        // Find the correct duplicated objsToCombine in the new instances that maps to objs in "objsToCombine".
        List <GameObject> newObjsToCombine = new List <GameObject>();

        for (int i = 0; i < srcRoots.Count; i++)
        {
            List <Transform> renderers = srcPrefabInstances2Renderers[srcRoots[i]];
            for (int j = 0; j < renderers.Count; j++)
            {
                Transform t = MB_BatchPrefabBakerEditorFunctions.FindCorrespondingTransform(srcRoots[i], renderers[j], targRoots[i]);
                Debug.Assert(!newObjsToCombine.Contains(t.gameObject));
                newObjsToCombine.Add(t.gameObject);
            }
        }
        Debug.Assert(newObjsToCombine.Count == objsToCombine.Length);

        for (int i = 0; i < newObjsToCombine.Count; i++)
        {
            //GameObject go = newObjsToCombine[i];
            //SerializedObject so = null;
            //MB_PrefabType pt = MBVersionEditor.GetPrefabType(go);
            //if (pt == MB_PrefabType.sceneInstance)
            //{
            //    MBVersionEditor.UnpackPrefabInstance(go, ref so);
            //}

            objsToCombine[i] = newObjsToCombine[i];
        }
    }
Ejemplo n.º 7
0
        public void DrawGUI(SerializedObject meshBaker, MB3_MeshBakerCommon target, UnityEngine.Object[] targets, System.Type editorWindowType)
        {
            if (meshBaker == null)
            {
                return;
            }

            meshBaker.Update();

            showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions:");
            if (showInstructions)
            {
                EditorGUILayout.HelpBox("1. Bake combined material(s).\n\n" +
                                        "2. If necessary set the 'Texture Bake Results' field.\n\n" +
                                        "3. Add scene objects or prefabs to combine or check 'Same As Texture Baker'. For best results these should use the same shader as result material.\n\n" +
                                        "4. Select options and 'Bake'.\n\n" +
                                        "6. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
                                        "7. (optional) Disable renderers in source objects.", UnityEditor.MessageType.None);

                EditorGUILayout.Separator();
            }

            MB3_MeshBakerCommon momm = (MB3_MeshBakerCommon)target;

            EditorGUILayout.PropertyField(logLevel, gc_logLevelContent);
            EditorGUILayout.PropertyField(textureBakeResults, gc_textureBakeResultsGUIContent);
            bool doingTextureArray = false;

            if (textureBakeResults.objectReferenceValue != null)
            {
                doingTextureArray  = ((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).resultType == MB2_TextureBakeResults.ResultType.textureArray;
                showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained");
                if (showContainsReport)
                {
                    EditorGUILayout.HelpBox(((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info);
                }
            }

            EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
            EditorGUILayout.LabelField("Objects To Be Combined", EditorStyles.boldLabel);
            if (momm.GetTextureBaker() != null)
            {
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
            }
            else
            {
                useObjsToMeshFromTexBaker.boolValue = false;
                momm.useObjsToMeshFromTexBaker      = false;
                GUI.enabled = false;
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
                GUI.enabled = true;
            }

            if (!momm.useObjsToMeshFromTexBaker)
            {
                if (GUILayout.Button(gc_openToolsWindowLabelContent))
                {
                    MB3_MeshBakerEditorWindow mmWin = (MB3_MeshBakerEditorWindow)EditorWindow.GetWindow(editorWindowType);
                    mmWin.SetTarget((MB3_MeshBakerRoot)momm);
                }

                object[] objs = MB3_EditorMethods.DropZone("Drag & Drop Renderers or Parents\n" + "HERE\n" +
                                                           "to add objects to be combined", 300, 50);
                MB3_EditorMethods.AddDroppedObjects(objs, momm);

                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                EditorGUILayout.Separator();
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Select Objects In Scene"))
                {
                    List <MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
                    List <GameObject>          obsToCombine   = new List <GameObject>();

                    foreach (MB3_MeshBakerCommon baker in selectedBakers)
                    {
                        obsToCombine.AddRange(baker.GetObjectsToCombine());
                    }
                    Selection.objects = obsToCombine.ToArray();
                    if (momm.GetObjectsToCombine().Count > 0)
                    {
                        SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position;
                    }
                }
                if (GUILayout.Button(gc_SortAlongAxis))
                {
                    MB3_MeshBakerRoot.ZSortObjects sorter = new MB3_MeshBakerRoot.ZSortObjects();
                    sorter.sortAxis = sortOrderAxis.vector3Value;
                    sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine());
                }
                EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none);
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                GUI.enabled = false;
                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                GUI.enabled = true;
            }
            EditorGUILayout.EndVertical();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Output", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(outputOptions, gc_outputOptoinsGUIContent);
            if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoSceneObject)
            {
                Transform pgo = (Transform)EditorGUILayout.ObjectField(gc_parentSceneObject, parentSceneObject.objectReferenceValue, typeof(Transform), true);
                if (pgo != null && MB_Utility.IsSceneInstance(pgo.gameObject))
                {
                    parentSceneObject.objectReferenceValue = pgo;
                }
                else
                {
                    parentSceneObject.objectReferenceValue = null;
                }

                //todo switch to renderer
                momm.meshCombiner.resultSceneObject = (GameObject)EditorGUILayout.ObjectField("Combined Mesh Object", momm.meshCombiner.resultSceneObject, typeof(GameObject), true);
                if (momm is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    Mesh   m = (Mesh)mesh.objectReferenceValue;
                    if (m != null)
                    {
                        l += " (" + m.GetInstanceID() + ")";
                    }
                    Mesh nm = (Mesh)EditorGUILayout.ObjectField(gc_combinedMesh, m, typeof(Mesh), true);
                    if (nm != m)
                    {
                        Undo.RecordObject(momm, "Assign Mesh");
                        ((MB3_MeshCombinerSingle)momm.meshCombiner).SetMesh(nm);
                        mesh.objectReferenceValue = nm;
                    }
                }
            }
            else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoPrefab)
            {
                if (momm.meshCombiner.settings.renderType == MB_RenderType.skinnedMeshRenderer)
                {
                    EditorGUILayout.HelpBox("The workflow for baking Skinned Meshes into prefabs has changed as of version 29.1. " +
                                            "It is no longer necessary to manually copy bones to the target prefab after baking. This should happen automatically.", MessageType.Info);
                }

                Transform pgo = (Transform)EditorGUILayout.ObjectField(gc_parentSceneObject, parentSceneObject.objectReferenceValue, typeof(Transform), true);
                if (pgo != null && MB_Utility.IsSceneInstance(pgo.gameObject))
                {
                    parentSceneObject.objectReferenceValue = pgo;
                }
                else
                {
                    parentSceneObject.objectReferenceValue = null;
                }

                EditorGUILayout.BeginHorizontal();
                momm.resultPrefab = (GameObject)EditorGUILayout.ObjectField(gc_combinedMeshPrefabGUIContent, momm.resultPrefab, typeof(GameObject), true);
                if (momm.resultPrefab != null)
                {
                    string assetPath = AssetDatabase.GetAssetPath(momm.resultPrefab);
                    if (assetPath == null || assetPath.Length == 0)
                    {
                        Debug.LogError("The " + gc_combinedMeshPrefabGUIContent.text + " must be a prefab asset, not a scene GameObject");
                        momm.resultPrefab = null;
                    }
                    else
                    {
                        MB_PrefabType pt = MBVersionEditor.PrefabUtility_GetPrefabType(momm.resultPrefab);
                        if (pt != MB_PrefabType.prefabAsset)
                        {
                            Debug.LogError("The " + gc_combinedMeshPrefabGUIContent.text + " must be a prefab asset, the prefab type was '" + pt + "'");
                            momm.resultPrefab = null;
                        }
                    }
                }
                else
                {
                    if (GUILayout.Button("Create Empty Prefab"))
                    {
                        if (!Application.isPlaying)
                        {
                            string path          = EditorUtility.SaveFilePanelInProject("Create Empty Prefab", "MyPrefab", "prefab", "Create a prefab containing an empty GameObject");
                            string pathNoFolder  = Path.GetDirectoryName(path);
                            string fileNameNoExt = Path.GetFileNameWithoutExtension(path);
                            List <MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
                            if (selectedBakers.Count > 1)
                            {
                                Debug.Log("About to create prefabs for " + selectedBakers.Count);
                            }
                            int idx = 0;
                            foreach (MB3_MeshBakerCommon baker in selectedBakers)
                            {
                                createEmptyPrefab(baker, pathNoFolder, fileNameNoExt, idx);
                                idx++;
                            }
                        }
                    }
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.PropertyField(resultPrefabLeaveInstanceInSceneAfterBake, gc_resultPrefabLeaveInstanceInSceneAfterBake);
                if (momm is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    Mesh   m = (Mesh)mesh.objectReferenceValue;
                    if (m != null)
                    {
                        l += " (" + m.GetInstanceID() + ")";
                    }
                    Mesh nm = (Mesh)EditorGUILayout.ObjectField(gc_combinedMesh, m, typeof(Mesh), true);
                    if (nm != m)
                    {
                        Undo.RecordObject(momm, "Assign Mesh");
                        ((MB3_MeshCombinerSingle)momm.meshCombiner).SetMesh(nm);
                        mesh.objectReferenceValue = nm;
                    }
                }
            }
            else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
            {
                EditorGUILayout.HelpBox("Try the BatchPrefabBaker component! It makes preparing a batch of prefabs for static/ dynamic batching much easier.", MessageType.Info);
                if (GUILayout.Button("Choose Folder For Bake In Place Meshes"))
                {
                    string newFolder = EditorUtility.SaveFolderPanel("Folder For Bake In Place Meshes", Application.dataPath, "");
                    if (!newFolder.Contains(Application.dataPath))
                    {
                        Debug.LogWarning("The chosen folder must be in your assets folder.");
                    }
                    string folder = "Assets" + newFolder.Replace(Application.dataPath, "");
                    List <MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
                    Undo.RecordObjects(targets, "Undo Set Folder");
                    foreach (MB3_MeshBakerCommon baker in selectedBakers)
                    {
                        baker.bakeAssetsInPlaceFolderPath = folder;
                        EditorUtility.SetDirty(baker);
                    }
                }

                EditorGUILayout.LabelField("Folder For Meshes: " + momm.bakeAssetsInPlaceFolderPath);
            }

            if (momm is MB3_MultiMeshBaker)
            {
                MB3_MultiMeshCombiner mmc = (MB3_MultiMeshCombiner)momm.meshCombiner;
                mmc.maxVertsInMesh = EditorGUILayout.IntField("Max Verts In Mesh", mmc.maxVertsInMesh);
            }

            //-----------------------------------
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
            bool settingsEnabled = true;

            //------------- Mesh Baker Settings is a bit tricky because it is an interface.



            EditorGUILayout.Space();
            UnityEngine.Object obj = settingsHolder.objectReferenceValue;

            // Don't use a PropertyField because we may not be able to use the assigned object. It may not implement requried interface.
            obj = EditorGUILayout.ObjectField(gc_Settings, obj, typeof(UnityEngine.Object), true);

            if (obj == null)
            {
                settingsEnabled = true;
                settingsHolder.objectReferenceValue = null;
                if (meshBakerSettingsExternal != null)
                {
                    meshBakerSettingsExternal.OnDisable();
                    meshBakerSettingsExternal = null;
                }
            }

            else if (obj is GameObject)
            {
                // Check to see if there is a component on this game object that implements MB_IMeshBakerSettingsHolder
                MB_IMeshBakerSettingsHolder itf = (MB_IMeshBakerSettingsHolder)((GameObject)obj).GetComponent(typeof(MB_IMeshBakerSettingsHolder));
                if (itf != null)
                {
                    settingsEnabled = false;
                    Component settingsHolderComponent = (Component)itf;
                    if (settingsHolder.objectReferenceValue != settingsHolderComponent)
                    {
                        settingsHolder.objectReferenceValue = settingsHolderComponent;
                        meshBakerSettingsExternal           = new MB_MeshBakerSettingsEditor();
                        UnityEngine.Object targetObj;
                        string             propertyName;
                        itf.GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
                        SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
                        meshBakerSettingsExternal.OnEnable(meshBakerSettings);
                    }
                }
                else
                {
                    settingsEnabled = true;
                    settingsHolder  = null;
                    if (meshBakerSettingsExternal != null)
                    {
                        meshBakerSettingsExternal.OnDisable();
                        meshBakerSettingsExternal = null;
                    }
                }
            }
            else if (obj is MB_IMeshBakerSettingsHolder)
            {
                settingsEnabled = false;
                if (settingsHolder.objectReferenceValue != obj)
                {
                    settingsHolder.objectReferenceValue = obj;
                    meshBakerSettingsExternal           = new MB_MeshBakerSettingsEditor();
                    UnityEngine.Object targetObj;
                    string             propertyName;
                    ((MB_IMeshBakerSettingsHolder)obj).GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
                    SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
                    meshBakerSettingsExternal.OnEnable(meshBakerSettings);
                }
            }
            else
            {
                Debug.LogError("Object was not a Mesh Baker Settings object.");
            }
            EditorGUILayout.Space();

            if (settingsHolder.objectReferenceValue == null)
            {
                // Use the meshCombiner settings
                meshBakerSettingsThis.DrawGUI(momm.meshCombiner, settingsEnabled, doingTextureArray);
            }
            else
            {
                if (meshBakerSettingsExternal == null)
                {
                    meshBakerSettingsExternal = new MB_MeshBakerSettingsEditor();
                    UnityEngine.Object targetObj;
                    string             propertyName;
                    ((MB_IMeshBakerSettingsHolder)obj).GetMeshBakerSettingsAsSerializedProperty(out propertyName, out targetObj);
                    SerializedProperty meshBakerSettings = new SerializedObject(targetObj).FindProperty(propertyName);
                    meshBakerSettingsExternal.OnEnable(meshBakerSettings);
                }
                meshBakerSettingsExternal.DrawGUI(((MB_IMeshBakerSettingsHolder)settingsHolder.objectReferenceValue).GetMeshBakerSettings(), settingsEnabled, doingTextureArray);
            }

            Color oldColor = GUI.backgroundColor;

            GUI.backgroundColor = buttonColor;
            if (GUILayout.Button("Bake"))
            {
                List <MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
                if (selectedBakers.Count > 1)
                {
                    Debug.Log("About to bake " + selectedBakers.Count);
                }
                foreach (MB3_MeshBakerCommon baker in selectedBakers)
                {
                    // Why are we caching and recreating the SerializedObject? Because "bakeIntoPrefab" corrupts the serialized object
                    // and the meshBaker SerializedObject throws an NRE the next time it gets used.
                    MB3_MeshBakerCommon mbr = (MB3_MeshBakerCommon)meshBaker.targetObject;
                    bake(baker);
                    meshBaker = new SerializedObject(mbr);
                }
            }
            GUI.backgroundColor = oldColor;

            string enableRenderersLabel;
            bool   disableRendererInSource = false;

            if (momm.GetObjectsToCombine().Count > 0)
            {
                Renderer r = MB_Utility.GetRenderer(momm.GetObjectsToCombine()[0]);
                if (r != null && r.enabled)
                {
                    disableRendererInSource = true;
                }
            }
            if (disableRendererInSource)
            {
                enableRenderersLabel = "Disable Renderers On Source Objects";
            }
            else
            {
                enableRenderersLabel = "Enable Renderers On Source Objects";
            }
            if (GUILayout.Button(enableRenderersLabel))
            {
                List <MB3_MeshBakerCommon> selectedBakers = _getBakersFromTargets(targets);
                foreach (MB3_MeshBakerCommon baker in selectedBakers)
                {
                    baker.EnableDisableSourceObjectRenderers(!disableRendererInSource);
                }
            }

            meshBaker.ApplyModifiedProperties();
            meshBaker.SetIsDifferentCacheDirty();
        }
    public static bool BakeIntoCombined(MB3_MeshBakerCommon mom, out bool createdDummyTextureBakeResults)
    {
        MB2_OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;

        createdDummyTextureBakeResults = false;
        if (MB3_MeshCombiner.EVAL_VERSION && prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
        {
            Debug.LogError("Cannot BakeIntoPrefab with evaluation version.");
            return(false);
        }
        if (prefabOrSceneObject != MB2_OutputOptions.bakeIntoPrefab && prefabOrSceneObject != MB2_OutputOptions.bakeIntoSceneObject)
        {
            Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject");
            return(false);
        }

        MB3_TextureBaker tb = mom.GetComponentInParent <MB3_TextureBaker>();

        if (mom.textureBakeResults == null && tb != null)
        {
            mom.textureBakeResults = tb.textureBakeResults;
        }
        if (mom.textureBakeResults == null)
        {
            if (_OkToCreateDummyTextureBakeResult(mom))
            {
                createdDummyTextureBakeResults = true;
                List <GameObject> gos = mom.GetObjectsToCombine();
                if (mom.GetNumObjectsInCombined() > 0)
                {
                    if (mom.clearBuffersAfterBake)
                    {
                        mom.ClearMesh();
                    }
                    else
                    {
                        Debug.LogError("'Texture Bake Result' must be set to add more objects to a combined mesh that already contains objects. Try enabling 'clear buffers after bake'");
                        return(false);
                    }
                }
                mom.textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(gos.ToArray(), mom.meshCombiner.GetMaterialsOnTargetRenderer());
                if (mom.meshCombiner.LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("'Texture Bake Result' was not set. Creating a temporary one. Each material will be mapped to a separate submesh.");
                }
            }
        }
        MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;

        if (!MB3_MeshBakerRoot.DoCombinedValidate(mom, MB_ObjsToCombineTypes.sceneObjOnly, new MB3_EditorMethods(), vl))
        {
            return(false);
        }
        if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab &&
            mom.resultPrefab == null)
        {
            Debug.LogError("Need to set the Combined Mesh Prefab field. Create a prefab asset, drag an empty game object into it, and drag it to the 'Combined Mesh Prefab' field.");
            return(false);
        }
        if (mom.meshCombiner.resultSceneObject != null &&
            (MBVersionEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.modelPrefab ||
             MBVersionEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.prefab))
        {
            Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field.");
            mom.meshCombiner.resultSceneObject = null;
        }

        mom.ClearMesh();
        if (mom.AddDeleteGameObjects(mom.GetObjectsToCombine().ToArray(), null, false))
        {
            mom.Apply(UnwrapUV2);
            if (createdDummyTextureBakeResults)
            {
                Debug.Log(String.Format("Successfully baked {0} meshes each material is mapped to its own submesh.", mom.GetObjectsToCombine().Count));
            }
            else
            {
                Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count));
            }


            if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoSceneObject)
            {
                MB_PrefabType pt = MBVersionEditor.GetPrefabType(mom.meshCombiner.resultSceneObject);
                if (pt == MB_PrefabType.prefab || pt == MB_PrefabType.modelPrefab)
                {
                    Debug.LogError("Combined Mesh Object is a prefab asset. If output option bakeIntoSceneObject then this must be an instance in the scene.");
                    return(false);
                }
            }
            else if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
            {
                string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
                if (prefabPth == null || prefabPth.Length == 0)
                {
                    Debug.LogError("Could not save result to prefab. Result Prefab value is not an Asset.");
                    return(false);
                }
                string baseName    = Path.GetFileNameWithoutExtension(prefabPth);
                string folderPath  = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 7);
                string newFilename = folderPath + baseName + "-mesh";
                SaveMeshsToAssetDatabase(mom, folderPath, newFilename);


                if (mom.meshCombiner.renderType == MB_RenderType.skinnedMeshRenderer)
                {
                    Debug.LogWarning("Render type is skinned mesh renderer. " +
                                     "Can't create prefab until all bones have been added to the combined mesh object " + mom.resultPrefab +
                                     " Add the bones then drag the combined mesh object to the prefab.");
                }
                RebuildPrefab(mom);

                MB_Utility.Destroy(mom.meshCombiner.resultSceneObject);
            }
            else
            {
                Debug.LogError("Unknown parameter");
                return(false);
            }
        }
        else
        {
            if (mom.clearBuffersAfterBake)
            {
                mom.meshCombiner.ClearBuffers();
            }
            if (createdDummyTextureBakeResults)
            {
                MB_Utility.Destroy(mom.textureBakeResults);
            }
            return(false);
        }
        if (mom.clearBuffersAfterBake)
        {
            mom.meshCombiner.ClearBuffers();
        }
        if (createdDummyTextureBakeResults)
        {
            MB_Utility.Destroy(mom.textureBakeResults);
        }
        return(true);
    }
        public void CopyBoneWeightsFromSeamMeshToOtherMeshes(MB3_BoneWeightCopier bwc)
        {
            if (bwc.seamMesh == null)
            {
                Debug.LogError("The seamMesh cannot be null.");
                return;
            }

            UnityEngine.Object pr        = (UnityEngine.Object)PrefabUtility.GetPrefabObject(bwc.seamMesh.gameObject);
            string             assetPath = null;

            if (pr != null)
            {
                assetPath = AssetDatabase.GetAssetPath(pr);
            }
            if (assetPath != null)
            {
                ModelImporter mi = (ModelImporter)AssetImporter.GetAtPath(assetPath);
                if (mi != null)
                {
                    if (mi.optimizeMesh)
                    {
                        Debug.LogError(string.Format("The seam mesh has 'optimized' checked in the asset importer. This will result in no vertices. Uncheck 'optimized'."));
                        return;
                    }
                }
            }
            //todo check that output game object exists and is a prefab
            if (bwc.outputPrefab == null)
            {
                Debug.LogError(string.Format("The output game object must be assigned and must be a prefab of a game object in the project folder."));
                return;
            }
            if (MBVersionEditor.GetPrefabType(bwc.outputPrefab) != MB_PrefabType.prefab)
            {
                Debug.LogError("The output game object must be a prefab. Create a prefab in the project and drag an empty game object to it.");
                return;
            }

            //duplicate the source prefab and the meshes
            if (copyOfInput != null)
            {
                DestroyImmediate(copyOfInput);
            }
            copyOfInput = (GameObject)GameObject.Instantiate(bwc.inputGameObject);
            SkinnedMeshRenderer[] targSkinnedMeshes = copyOfInput.GetComponentsInChildren <SkinnedMeshRenderer>();
            Mesh[] targs = new Mesh[targSkinnedMeshes.Length];
            for (int i = 0; i < targSkinnedMeshes.Length; i++)
            {
                if (targSkinnedMeshes[i].sharedMesh == null)
                {
                    Debug.LogError(string.Format("Skinned Mesh {0} does not have a mesh", targSkinnedMeshes[i]));
                    return;
                }
                MB_PrefabType pt = MBVersionEditor.GetPrefabType(targSkinnedMeshes[i].gameObject);
                if (pt == MB_PrefabType.modelPrefab)
                {
                    Debug.LogError(string.Format("Target Mesh {0} is an imported model prefab. Can't modify these meshes because changes will be overwritten the next time the model is saved or reimported. Try instantiating the prefab and using skinned meshes from the scene instance.", i));
                    return;
                }
                targs[i] = (Mesh)GameObject.Instantiate(targSkinnedMeshes[i].sharedMesh);
            }
            MB3_CopyBoneWeights.CopyBoneWeightsFromSeamMeshToOtherMeshes(bwc.radius, bwc.seamMesh.sharedMesh, targs);
            SaveMeshesToOutputFolderAndAssignToSMRs(targs, targSkinnedMeshes);

            EditorUtility.SetDirty(copyOfInput);


            // TODO tried using 2018 replace prefab but there were errors.
            //MBVersionEditor.ReplacePrefab(copyOfInput, assetPath, MB_ReplacePrefabOption.connectToPrefab | MB_ReplacePrefabOption.nameBased);
            PrefabUtility.ReplacePrefab(copyOfInput, bwc.outputPrefab, ReplacePrefabOptions.ConnectToPrefab | ReplacePrefabOptions.ReplaceNameBased);

            AssetDatabase.SaveAssets();
            DestroyImmediate(copyOfInput);
        }