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); }
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; }
/// <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(); }
//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); }
/* 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); }
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); }