public static GameObject CreateNewMeshBaker()
        {
            TextureCombineEntrance[] mbs = (TextureCombineEntrance[])GameObject.FindObjectsOfType(typeof(TextureCombineEntrance));
            Regex regex   = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
            int   largest = 0;

            try
            {
                for (int i = 0; i < mbs.Length; i++)
                {
                    Match match = regex.Match(mbs[i].name);
                    if (match.Success)
                    {
                        int val = Convert.ToInt32(match.Groups[1].Value);
                        if (val >= largest)
                        {
                            largest = val + 1;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                if (e == null)
                {
                    e = null;            //Do nothing supress compiler warning
                }
            }
            GameObject nmb = new GameObject("TextureCombineEntrance (" + largest + ")");

            nmb.transform.position = Vector3.zero;
            TextureCombineEntrance tb = nmb.AddComponent <TextureCombineEntrance>();

            tb.packingAlgorithm = PackingAlgorithmEnum.MeshBakerTexturePacker;
            ////MB3_MeshBakerGrouper mbg = nmb.AddComponent<MB3_MeshBakerGrouper>();
            GameObject           meshBaker = new GameObject("MeshBaker");
            MeshCombinerEntrance mb        = meshBaker.AddComponent <MeshCombinerEntrance>();

            meshBaker.transform.parent = nmb.transform;
            ////mb.meshCombiner.settingsHolder = mbg;
            return(nmb.gameObject);
        }
Example #2
0
        public static void CreateNewTextureBaker()
        {
            TextureCombineEntrance[] mbs = (TextureCombineEntrance[])UnityEditor.Editor.FindObjectsOfType(typeof(TextureCombineEntrance));
            Regex regex   = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
            int   largest = 0;

            try
            {
                for (int i = 0; i < mbs.Length; i++)
                {
                    Match match = regex.Match(mbs[i].name);
                    if (match.Success)
                    {
                        int val = Convert.ToInt32(match.Groups[1].Value);
                        if (val >= largest)
                        {
                            largest = val + 1;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                if (e == null)
                {
                    e = null;            //Do nothing supress compiler warning
                }
            }
            GameObject nmb = new GameObject("TextureBaker (" + largest + ")");

            nmb.transform.position = Vector3.zero;
            ////nmb.AddComponent<MB3_MeshBakerGrouper>();
            TextureCombineEntrance tb = nmb.AddComponent <TextureCombineEntrance>();

            tb.packingAlgorithm = PackingAlgorithmEnum.MeshBakerTexturePacker;
        }
Example #3
0
        /// <summary>
        /// 创建合并材质资源
        /// </summary>
        /// <param name="target"></param>
        /// <param name="pth"></param>
        public static void CreateCombinedMaterialAssets(TextureCombineEntrance target, string pth)
        {
            TextureCombineEntrance mom = (TextureCombineEntrance)target;
            string baseName            = Path.GetFileNameWithoutExtension(pth);

            if (baseName == null || baseName.Length == 0)
            {
                return;
            }
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);

            List <string> matNames = new List <string>();

            //多材质
            if (mom.doMultiMaterial)
            {
                for (int i = 0; i < mom.resultMaterials.Length; i++)
                {
                    matNames.Add(folderPath + baseName + "-mat" + i + ".mat");
                    AssetDatabase.CreateAsset(new Material(Shader.Find("Diffuse")), matNames[i]);
                    mom.resultMaterials[i].combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matNames[i], typeof(Material));
                }
            }
            else
            {
                matNames.Add(folderPath + baseName + "-mat.mat");
                Material newMat = null;
                if (mom.GetObjectsToCombine().Count > 0 && mom.GetObjectsToCombine()[0] != null)
                {
                    Renderer r = mom.GetObjectsToCombine()[0].GetComponent <Renderer>();
                    if (r == null)
                    {
                        Debug.LogWarning("Object " + mom.GetObjectsToCombine()[0] + " does not have a Renderer on it.");
                    }
                    else
                    {
                        if (r.sharedMaterial != null)
                        {
                            newMat = new Material(r.sharedMaterial);
                            TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, r.sharedMaterial);
                        }
                    }
                }
                else
                {
                    Debug.Log("If you add objects to be combined before creating the Combined Material Assets. " +
                              "Then Mesh Baker will create a result material that is a duplicate of the material on the first object to be combined. " +
                              "This saves time configuring the shader.");
                }

                if (newMat == null)
                {
                    newMat = new Material(Shader.Find("Diffuse"));
                }
                AssetDatabase.CreateAsset(newMat, matNames[0]);
                mom.resultMaterial = (Material)AssetDatabase.LoadAssetAtPath(matNames[0], typeof(Material));
            }
            //create the TextureBakeResults
            AssetDatabase.CreateAsset(ScriptableObject.CreateInstance <TextureBakeResults>(), pth);
            mom.textureBakeResults = (TextureBakeResults)AssetDatabase.LoadAssetAtPath(pth, typeof(TextureBakeResults));
            AssetDatabase.Refresh();
        }
Example #4
0
        //posibilities
        //  using fixOutOfBoundsUVs or not
        //
        /// <summary>
        /// 根据合并列表物体配置多材质
        /// </summary>
        /// <param name="mom"></param>
        /// <param name="resultMaterials"></param>
        /// <param name="textureBaker"></param>
        public static void ConfigureMutiMaterialsFromObjsToCombine(TextureCombineEntrance mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("合并列表为空");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("多材质映射已配置,在进行当前操作前需清除旧配置");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result 为空");
                return;
            }

            //validate that the objects to be combined are valid
            //验证合并列表内物体有效性
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObject go = mom.GetObjectsToCombine()[i];
                if (go == null)
                {
                    Debug.LogError("合并列表中有空物体于 " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("合并列表中第 " + i + " 个游戏物体没有 renderer 组件");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("合并列表中第 " + i + " 个游戏物体没有材质");
                    return;
                }
            }



            Dictionary <Material, Mesh> obUVobjectToMesh_map = new Dictionary <Material, Mesh>();

            //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
            //1.将所有带有obUV的网格置于单独的材质中,(如果不固定OB UV)
            if (mom.doMultiMaterialSplitAtlasesIfOBUVs)
            {
                for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
                {
                    GameObject         go       = mom.GetObjectsToCombine()[i];
                    Mesh               m        = MeshBakerUtility.GetMesh(go);
                    MeshAnalysisResult dummyMar = new MeshAnalysisResult();
                    Renderer           r        = go.GetComponent <Renderer>();
                    for (int j = 0; j < r.sharedMaterials.Length; j++)
                    {
                        if (MeshBakerUtility.hasOutOfBoundsUVs(m, ref dummyMar, j))
                        {
                            if (!obUVobjectToMesh_map.ContainsKey(r.sharedMaterials[j]))
                            {
                                Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. " +
                                                 "This object has been mapped to its own submesh in the combined mesh. " +
                                                 "It can share a submesh with other objects that use different materials " +
                                                 "if you use the fix out of bounds UVs feature which will bake the tiling");
                                obUVobjectToMesh_map.Add(r.sharedMaterials[j], m);
                            }
                        }
                    }
                }
            }

            Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shaderToMaterial_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >();

            //2.没有 OB uvs 的材质按 shader 添加到 shader2Material_map 中
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                Renderer r = mom.GetObjectsToCombine()[i].GetComponent <Renderer>();
                for (int j = 0; j < r.sharedMaterials.Length; j++)
                {
                    if (!obUVobjectToMesh_map.ContainsKey(r.sharedMaterials[j]))
                    { //if not already added
                        if (r.sharedMaterials[j] == null)
                        {
                            continue;
                        }
                        List <List <Material> > binsOfMatsThatUseShader = null;
                        MultiMatSubmeshInfo     newKey = new MultiMatSubmeshInfo(r.sharedMaterials[j].shader, r.sharedMaterials[j]);
                        if (!shaderToMaterial_map.TryGetValue(newKey, out binsOfMatsThatUseShader))
                        {
                            binsOfMatsThatUseShader = new List <List <Material> >();
                            binsOfMatsThatUseShader.Add(new List <Material>());
                            shaderToMaterial_map.Add(newKey, binsOfMatsThatUseShader);
                        }
                        if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j]))
                        {
                            binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]);
                        }
                    }
                }
            }

            int ResultMatsCount = shaderToMaterial_map.Count;

            //third pass for each shader grouping check how big the atlas would be and group into bins that would fit in an atlas
            // 3.检查每个 Shader-Mat 组的最终打包的 atlas 大小,过大则分到另一个图集中
            if (mom.doMultiMaterialSplitAtlasesIfTooBig)
            {
                if (mom.packingAlgorithm == PackingAlgorithmEnum.UnitysPackTextures)
                {
                    Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split.");
                }
                else
                {
                    ResultMatsCount = 0;
                    foreach (MultiMatSubmeshInfo sh in shaderToMaterial_map.Keys)
                    {
                        List <List <Material> > binsOfMatsThatUseShader = shaderToMaterial_map[sh];
                        List <Material>         allMatsThatUserShader   = binsOfMatsThatUseShader[0];//at this point everything is in the same list
                        binsOfMatsThatUseShader.RemoveAt(0);
                        TextureCombineHandler combiner = mom.CreateAndConfigureTextureCombiner();
                        combiner.saveAtlasesAsAssets = false;
                        if (allMatsThatUserShader.Count > 1)
                        {
                            combiner.fixOutOfBoundsUVs = mom.fixOutOfBoundsUVs;
                        }
                        else
                        {
                            combiner.fixOutOfBoundsUVs = false;
                        }

                        // Do the texture pack
                        List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>();
                        Material tempMat = new Material(sh.shader);
                        combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, null, packingResults, true, true);
                        for (int i = 0; i < packingResults.Count; i++)
                        {
                            List <MatsAndGOs> matsData = (List <MatsAndGOs>)packingResults[i].data;
                            List <Material>   mats     = new List <Material>();
                            for (int j = 0; j < matsData.Count; j++)
                            {
                                for (int kk = 0; kk < matsData[j].mats.Count; kk++)
                                {
                                    if (!mats.Contains(matsData[j].mats[kk].mat))
                                    {
                                        mats.Add(matsData[j].mats[kk].mat);
                                    }
                                }
                            }
                            binsOfMatsThatUseShader.Add(mats);
                        }
                        ResultMatsCount += binsOfMatsThatUseShader.Count;
                    }
                }
            }

            //build the result materials
            if (shaderToMaterial_map.Count == 0 && obUVobjectToMesh_map.Count == 0)
            {
                Debug.LogError("合并列表中没有材质");
            }

            mom.resultMaterials = new MultiMaterial[ResultMatsCount + obUVobjectToMesh_map.Count];
            string pth        = AssetDatabase.GetAssetPath(mom.textureBakeResults);
            string baseName   = Path.GetFileNameWithoutExtension(pth);
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
            int    k          = 0;

            foreach (MultiMatSubmeshInfo sh in shaderToMaterial_map.Keys)
            {
                foreach (List <Material> sourseMatsThatUseSameShader in shaderToMaterial_map[sh])
                {
                    MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial();
                    mm.sourceMaterials = sourseMatsThatUseSameShader;
                    if (mm.sourceMaterials.Count == 1)
                    {
                        mm.considerMeshUVs = false;
                    }
                    else
                    {
                        mm.considerMeshUVs = mom.fixOutOfBoundsUVs;
                    }
                    string matName = folderPath + baseName + "-mat" + k + ".mat";

                    Material newMat = new Material(Shader.Find("Diffuse"));
                    if (sourseMatsThatUseSameShader.Count > 0 && sourseMatsThatUseSameShader[0] != null)
                    {
                        //复制参数值
                        TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, sourseMatsThatUseSameShader[0]);
                    }
                    AssetDatabase.CreateAsset(newMat, matName);
                    //合并材质初始值为源材质列表第一个的值
                    mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                    k++;
                }
            }

            foreach (Material m in obUVobjectToMesh_map.Keys)
            {
                MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m);
                mm.considerMeshUVs = false;
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, m);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            SceneBakerUtilityInEditor.UpdateIfDirtyOrScript(textureBaker);
        }
Example #5
0
        /* tried to see if the MultiMaterialConfig could be done using the GroupBy filters. Saddly it didn't work  -_- */
        public static void ConfigureMutiMaterialsFromObjsToCombine2(TextureCombineEntrance mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result asset must be set before using this operation.");
                return;
            }

            //validate that the objects to be combined are valid
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObject go = mom.GetObjectsToCombine()[i];
                if (go == null)
                {
                    Debug.LogError("Null object in list of objects to combine at position " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
                    return;
                }
            }

            IGroupByFilter[] filters = new IGroupByFilter[3];
            filters[0] = new GroupByOutOfBoundsUVs();
            filters[1] = new GroupByShader();
            filters[2] = new MB3_GroupByStandardShaderType();

            List <GameObjectFilterInfo> gameObjects = new List <GameObjectFilterInfo>();
            HashSet <GameObject>        objectsAlreadyIncludedInBakers = new HashSet <GameObject>();

            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObjectFilterInfo goaw = new GameObjectFilterInfo(mom.GetObjectsToCombine()[i], objectsAlreadyIncludedInBakers, filters);
                if (goaw.materials.Length > 0) //don't consider renderers with no materials
                {
                    gameObjects.Add(goaw);
                }
            }

            //analyse meshes
            Dictionary <int, MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MeshAnalysisResult>();
            int totalVerts = 0;

            for (int i = 0; i < gameObjects.Count; i++)
            {
                //string rpt = String.Format("Processing {0} [{1} of {2}]", gameObjects[i].go.name, i, gameObjects.Count);
                //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " A", .6f);
                Mesh mm     = MeshBakerUtility.GetMesh(gameObjects[i].go);
                int  nVerts = 0;
                if (mm != null)
                {
                    nVerts += mm.vertexCount;
                    MeshAnalysisResult mar;
                    if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar))
                    {
                        //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f);
                        MeshBakerUtility.hasOutOfBoundsUVs(mm, ref mar);
                        //Rect dummy = mar.uvRect;
                        MeshBakerUtility.doSubmeshesShareVertsOrTris(mm, ref mar);
                        meshAnalysisResultCache.Add(mm.GetInstanceID(), mar);
                    }
                    if (mar.hasOutOfBoundsUVs)
                    {
                        int w = (int)mar.uvRect.width;
                        int h = (int)mar.uvRect.height;
                        gameObjects[i].outOfBoundsUVs = true;
                        gameObjects[i].warning       += " [WARNING: has uvs outside the range (0,1) tex is tiled " + w + "x" + h + " times]";
                    }
                    if (mar.hasOverlappingSubmeshVerts)
                    {
                        gameObjects[i].submeshesOverlap = true;
                        gameObjects[i].warning         += " [WARNING: Submeshes share verts or triangles. 'Multiple Combined Materials' feature may not work.]";
                    }
                }
                totalVerts += nVerts;
                //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Validate OBuvs Multi Material", .6f);
                Renderer mr = gameObjects[i].go.GetComponent <Renderer>();
                if (!MeshBakerUtility.AreAllSharedMaterialsDistinct(mr.sharedMaterials))
                {
                    gameObjects[i].warning += " [WARNING: Object uses same material on multiple submeshes. This may produce poor results when used with multiple materials or fix out of bounds uvs.]";
                }
            }

            List <GameObjectFilterInfo> objsNotAddedToBaker = new List <GameObjectFilterInfo>();

            Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > > gs2bakeGroupMap = null;//MB3_MeshBakerEditorWindow.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize);

            mom.resultMaterials = new MultiMaterial[gs2bakeGroupMap.Keys.Count];
            string pth        = AssetDatabase.GetAssetPath(mom.textureBakeResults);
            string baseName   = Path.GetFileNameWithoutExtension(pth);
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
            int    k          = 0;

            foreach (GameObjectFilterInfo m in gs2bakeGroupMap.Keys)
            {
                MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m.materials[0]);
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            SceneBakerUtilityInEditor.UpdateIfDirtyOrScript(textureBaker);
        }
Example #6
0
        public void DrawGUI(SerializedObject textureBaker, TextureCombineEntrance momm, Type editorWindow)
        {
            if (textureBaker == null)
            {
                return;
            }
            textureBaker.Update();

            showInstructions = EditorGUILayout.Foldout(showInstructions, "说明:");
            if (showInstructions)
            {
                EditorGUILayout.HelpBox("1. Add scene objects or prefabs to combine. For best results these should use the same shader as result material.\n\n" +
                                        "2. Create Empty Assets For Combined Material(s)\n\n" +
                                        "3. Check that shader on result material(s) are correct.\n\n" +
                                        "4. Bake materials into combined material(s).\n\n" +
                                        "5. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
                                        "6. You are now ready to build combined meshs or adjust meshes to use the combined material(s).", UnityEditor.MessageType.None);
            }

            EditorGUILayout.Separator();

            // Selected objects
            EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
            EditorGUILayout.LabelField("加入合并物体 ", EditorStyles.boldLabel);
            if (GUILayout.Button(openToolsWindowLabelContent))
            {
                IMeshCombinerEditorWindow mmWin = (IMeshCombinerEditorWindow)EditorWindow.GetWindow(editorWindow);
                mmWin.target = (MeshBakerRoot)momm;
            }

            object[] objs = EditorMethods.DropZone("将包含 Renderer 组件的游戏物体或父物体托至此处加入合并列表中", 300, 50);
            EditorMethods.AddDroppedObjects(objs, momm);

            //合并列表属性
            EditorGUILayout.PropertyField(objsToMesh, objectsToCombineGUIContent, true);

            EditorGUILayout.Separator();

            //合并列表属性下方按钮
            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("选中合并列表中的游戏物体"))
            {
                Selection.objects = momm.GetObjectsToCombine().ToArray();
                if (momm.GetObjectsToCombine().Count > 0)
                {
                    SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position;
                }
            }
            //排序按钮
            if (GUILayout.Button(gc_SortAlongAxis))
            {
                MeshBakerRoot.ZSortObjects sorter = new MeshBakerRoot.ZSortObjects();
                sorter.sortAxis = sortOrderAxis.vector3Value;
                sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine());
            }
            EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();


            // output
            EditorGUILayout.Separator();
            EditorGUILayout.LabelField("输出", EditorStyles.boldLabel);
            if (GUILayout.Button(createPrefabAndMaterialLabelContent))
            {
                string newPrefabPath = EditorUtility.SaveFilePanelInProject("新建合并材质资源名称", "", "asset", "Enter a name for the baked texture results");
                if (newPrefabPath != null)
                {
                    CreateCombinedMaterialAssets(momm, newPrefabPath);
                }
            }
            EditorGUILayout.PropertyField(textureBakeResults, textureBakeResultsGUIContent);

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

            //多材质合并
            EditorGUILayout.PropertyField(doMultiMaterial, new GUIContent("是否多材质合并"));

            if (momm.doMultiMaterial)
            {
                EditorGUILayout.BeginVertical(editorStyles.multipleMaterialBackgroundStyle);
                EditorGUILayout.LabelField("原始材质合并映射信息", EditorStyles.boldLabel);

                float oldLabelWidth = EditorGUIUtility.labelWidth;
                EditorGUIUtility.labelWidth = 300;
                EditorGUILayout.PropertyField(doMultiMaterialIfOBUVs, gc_DoMultiMaterialSplitAtlasesIfOBUVs);
                EditorGUILayout.PropertyField(doMultiMaterialSplitAtlasesIfTooBig, gc_DoMultiMaterialSplitAtlasesIfTooBig);
                EditorGUIUtility.labelWidth = oldLabelWidth;


                if (GUILayout.Button(configMultiMatFromObjsContent))
                {
                    ConfigureMutiMaterialsFromObjsToCombine(momm, resultMaterials, textureBaker);
                }

                EditorGUILayout.BeginHorizontal();
                resultMaterialsFoldout = EditorGUILayout.Foldout(resultMaterialsFoldout, combinedMaterialsGUIContent);

                //添加按钮
                if (GUILayout.Button(insertContent, EditorStyles.miniButtonLeft, buttonWidth))
                {
                    if (resultMaterials.arraySize == 0)
                    {
                        momm.resultMaterials = new MultiMaterial[1];
                        momm.resultMaterials[0].considerMeshUVs = momm.fixOutOfBoundsUVs;
                    }
                    else
                    {
                        int idx = resultMaterials.arraySize - 1;
                        resultMaterials.InsertArrayElementAtIndex(idx);
                        resultMaterials.GetArrayElementAtIndex(idx + 1).FindPropertyRelative("considerMeshUVs").boolValue = momm.fixOutOfBoundsUVs;
                    }
                }
                //删除按钮
                if (GUILayout.Button(deleteContent, EditorStyles.miniButtonRight, buttonWidth))
                {
                    resultMaterials.DeleteArrayElementAtIndex(resultMaterials.arraySize - 1);
                }
                EditorGUILayout.EndHorizontal();
                //合并材质列表
                if (resultMaterialsFoldout)
                {
                    for (int i = 0; i < resultMaterials.arraySize; i++)
                    {
                        EditorGUILayout.Separator();
                        if (i % 2 == 1)
                        {
                            EditorGUILayout.BeginVertical(editorStyles.multipleMaterialBackgroundStyle);
                        }
                        else
                        {
                            EditorGUILayout.BeginVertical(editorStyles.multipleMaterialBackgroundStyleDarker);
                        }
                        string s = "";
                        if (i < momm.resultMaterials.Length && momm.resultMaterials[i] != null && momm.resultMaterials[i].combinedMaterial != null)
                        {
                            s = momm.resultMaterials[i].combinedMaterial.shader.ToString();
                        }
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("--- " + i + ":" + s, EditorStyles.boldLabel);
                        //删除按钮
                        if (GUILayout.Button(deleteContent, EditorStyles.miniButtonRight, buttonWidth))
                        {
                            resultMaterials.DeleteArrayElementAtIndex(i);
                        }
                        EditorGUILayout.EndHorizontal();
                        if (i < resultMaterials.arraySize)
                        {
                            EditorGUILayout.Separator();
                            SerializedProperty resMat = resultMaterials.GetArrayElementAtIndex(i);
                            EditorGUILayout.PropertyField(resMat.FindPropertyRelative("combinedMaterial"));
                            EditorGUILayout.PropertyField(resMat.FindPropertyRelative("considerMeshUVs"));
                            SerializedProperty sourceMats = resMat.FindPropertyRelative("sourceMaterials");
                            EditorGUILayout.PropertyField(sourceMats, true);
                        }
                        EditorGUILayout.EndVertical();
                    }
                }
                EditorGUILayout.EndVertical();
            }
            else
            {
                EditorGUILayout.PropertyField(resultMaterial, new GUIContent("已合并材质"));
            }

            // settings 材质合并选项
            int labelWidth = 200;

            EditorGUILayout.Separator();
            EditorGUILayout.Separator();
            EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
            EditorGUILayout.LabelField("材质合并选项", EditorStyles.boldLabel);

            // Atlas 间隙
            DrawPropertyFieldWithLabelWidth(atlasPadding, gc_atlasPadding, labelWidth);
            // Atlas 最大尺寸
            DrawPropertyFieldWithLabelWidth(maxAtlasSize, maxAtlasSizeGUIContent, labelWidth);
            // POT
            DrawPropertyFieldWithLabelWidth(resizePowerOfTwoTextures, resizePowerOfTwoGUIContent, labelWidth);
            //
            DrawPropertyFieldWithLabelWidth(maxTilingBakeSize, maxTilingBakeSizeGUIContent, labelWidth);

            EditorGUI.BeginDisabledGroup(momm.doMultiMaterial);
            //是否计算网格 UV
            DrawPropertyFieldWithLabelWidth(considerMeshUVs, fixOutOfBoundsGUIContent, labelWidth);
            EditorGUI.EndDisabledGroup();

            if (texturePackingAlgorithm.intValue == (int)PackingAlgorithmEnum.MeshBakerTexturePacker ||
                texturePackingAlgorithm.intValue == (int)PackingAlgorithmEnum.MeshBakerTexturePacker_Fast)
            {
                //强制 POT
                DrawPropertyFieldWithLabelWidth(forcePowerOfTwoAtlas, forcePowerOfTwoAtlasContent, labelWidth);
            }

            //非 Texture 属性
            DrawPropertyFieldWithLabelWidth(considerNonTextureProperties, considerNonTexturePropertiesContent, labelWidth);

            if (texturePackingAlgorithm.intValue == (int)PackingAlgorithmEnum.UnitysPackTextures)
            {
                EditorGUILayout.HelpBox("Unity's texture packer has memory problems and frequently crashes the editor.", MessageType.Warning);
            }


            //合并算法选项
            EditorGUILayout.PropertyField(texturePackingAlgorithm, texturePackingAgorithmGUIContent);
            if (TextureCombinerPipeline.USE_EXPERIMENTAL_HOIZONTALVERTICAL)
            {
                if (texturePackingAlgorithm.enumValueIndex == (int)PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal)
                {
                    EditorGUILayout.PropertyField(useMaxAtlasWidthOverride, gc_useMaxAtlasWidthOverride);
                    if (!useMaxAtlasWidthOverride.boolValue)
                    {
                        EditorGUI.BeginDisabledGroup(true);
                    }
                    EditorGUILayout.PropertyField(maxAtlasWidthOverride, gc_overrideMaxAtlasWidth);
                    if (!useMaxAtlasWidthOverride.boolValue)
                    {
                        EditorGUI.EndDisabledGroup();
                    }
                }
                else if (texturePackingAlgorithm.enumValueIndex == (int)PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical)
                {
                    EditorGUILayout.PropertyField(useMaxAtlasHeightOverride, gc_useMaxAtlasHeightOverride);
                    if (!useMaxAtlasHeightOverride.boolValue)
                    {
                        EditorGUI.BeginDisabledGroup(true);
                    }
                    EditorGUILayout.PropertyField(maxAtlasHeightOverride, gc_overrideMaxAtlasHeight);
                    if (!useMaxAtlasHeightOverride.boolValue)
                    {
                        EditorGUI.EndDisabledGroup();
                    }
                }
            }

            EditorGUILayout.PropertyField(customShaderProperties, customShaderPropertyNamesGUIContent, true);
            EditorGUILayout.EndVertical();
            EditorGUILayout.Separator();
            Color oldColor = GUI.backgroundColor;

            GUI.color = buttonColor;
            if (GUILayout.Button("合并"))
            {
                momm.CreateAtlases(updateProgressBar, true, new EditorMethods());
                EditorUtility.ClearProgressBar();
                if (momm.textureBakeResults != null)
                {
                    EditorUtility.SetDirty(momm.textureBakeResults);
                }
            }
            GUI.backgroundColor = oldColor;
            textureBaker.ApplyModifiedProperties();
            if (GUI.changed)
            {
                textureBaker.SetIsDifferentCacheDirty();
            }
        }
        /// <summary>
        ///  Bakes a combined mesh.
        ///  如果是从Inspector代码中调用的,则传入该组件的SerializedObject
        ///  对于“烘焙到预制”可能会损坏SerializedObject。这是必需的
        /// </summary>
        public static bool BakeIntoCombined(MeshBakerCommon mom, out bool createdDummyTextureBakeResults, ref SerializedObject so)
        {
            OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;

            createdDummyTextureBakeResults = false;
            if (prefabOrSceneObject != OutputOptions.bakeIntoPrefab && prefabOrSceneObject != OutputOptions.bakeIntoSceneObject)
            {
                Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject");
                return(false);
            }

            //从父物体获得 贴图合并组件及其贴图合并结果 Asset
            TextureCombineEntrance tb = mom.GetComponentInParent <TextureCombineEntrance>();

            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 = TextureBakeResults.CreateForMaterialsOnRenderer(
                        gos.ToArray(),
                        mom.meshCombiner.GetMaterialsOnTargetRenderer());
                    Debug.Log("'Texture Bake Result' was not set. " +
                              "Creating a temporary one. Each material will be mapped to a separate submesh.");
                }
            }

            //合并检测
            ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust;

            if (!MeshBakerRoot.DoCombinedValidate(mom, ObjsToCombineTypes.sceneObjOnly, new EditorMethods(), vl))
            {
                return(false);
            }

            //检测空预制体资源是否已创建
            if (prefabOrSceneObject == 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 &&
                (SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.modelPrefab ||
                 SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == 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 == OutputOptions.bakeIntoSceneObject)
                {
                    PrefabType pt = SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject);
                    if (pt == PrefabType.prefab || pt == 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 == OutputOptions.bakeIntoPrefab)
                {
                    string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
                    if (prefabPth == null || prefabPth.Length == 0)
                    {
                        Debug.LogError("无法保存,合并游戏物体并非磁盘上的资源。");
                        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 == RendererType.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.");
                    }
                    //构建 Prefab
                    RebuildPrefab(mom, ref so);

                    MeshBakerUtility.Destroy(mom.meshCombiner.resultSceneObject);
                }
                else
                {
                    Debug.LogError("合并输出类型出错");
                    return(false);
                }
            }
            else
            {
                //加入合并失败
                if (mom.clearBuffersAfterBake)
                {
                    mom.meshCombiner.ClearBuffers();
                }
                if (createdDummyTextureBakeResults)
                {
                    MeshBakerUtility.Destroy(mom.textureBakeResults);
                }
                return(false);
            }

            //清除缓存数据
            if (mom.clearBuffersAfterBake)
            {
                mom.meshCombiner.ClearBuffers();
            }
            //临时Texture
            if (createdDummyTextureBakeResults)
            {
                MeshBakerUtility.Destroy(mom.textureBakeResults);
            }
            return(true);
        }