public void PopulatePrefabRowsFromTextureBaker(MB3_BatchPrefabBaker prefabBaker) { Undo.RecordObject(prefabBaker, "Populate prefab rows"); MB3_TextureBaker texBaker = prefabBaker.GetComponent <MB3_TextureBaker>(); List <GameObject> prefabs = new List <GameObject>(); List <GameObject> gos = texBaker.GetObjectsToCombine(); for (int i = 0; i < gos.Count; i++) { GameObject go = (GameObject)PrefabUtility.FindPrefabRoot(gos[i]); UnityEngine.Object obj = MBVersionEditor.PrefabUtility_GetCorrespondingObjectFromSource(go); if (obj != null && obj is GameObject) { if (!prefabs.Contains((GameObject)obj)) { prefabs.Add((GameObject)obj); } } else { Debug.LogWarning(String.Format("Object {0} did not have a prefab", gos[i])); } } List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow> newRows = new List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow>(); for (int i = 0; i < prefabs.Count; i++) { MB3_BatchPrefabBaker.MB3_PrefabBakerRow row = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow(); row.sourcePrefab = prefabs[i]; newRows.Add(row); } prefabBaker.prefabRows = newRows.ToArray(); }
public void DoClustering(MB3_TextureBaker tb) { if (this.clusterGrouper == null) { Debug.LogError("Cluster Grouper was null."); return; } Dictionary <string, List <Renderer> > dictionary = this.clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine()); Debug.Log("Found " + dictionary.Count + " cells with Renderers. Creating bakers."); if (this.clusterOnLMIndex) { Dictionary <string, List <Renderer> > dictionary2 = new Dictionary <string, List <Renderer> >(); foreach (string text in dictionary.Keys) { List <Renderer> gaws = dictionary[text]; Dictionary <int, List <Renderer> > dictionary3 = this.GroupByLightmapIndex(gaws); foreach (int num in dictionary3.Keys) { string key = text + "-LM-" + num; dictionary2.Add(key, dictionary3[num]); } } dictionary = dictionary2; } foreach (string key2 in dictionary.Keys) { List <Renderer> gaws2 = dictionary[key2]; this.AddMeshBaker(tb, key2, gaws2); } }
public static void CreateNewTextureBaker() { MB3_TextureBaker[] mbs = (MB3_TextureBaker[])Editor.FindObjectsOfType(typeof(MB3_TextureBaker)); 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>(); MB3_TextureBaker tb = nmb.AddComponent <MB3_TextureBaker>(); tb.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker; }
public MB3_MeshBakerGrouperCore CreateGrouper(ClusterType t, GrouperData data) { if (t == ClusterType.grid) { grouper = new MB3_MeshBakerGrouperGrid(data); } if (t == ClusterType.pie) { grouper = new MB3_MeshBakerGrouperPie(data); } if (t == ClusterType.agglomerative) { MB3_TextureBaker tb = GetComponent <MB3_TextureBaker>(); List <GameObject> gos; if (tb != null) { gos = tb.GetObjectsToCombine(); } else { gos = new List <GameObject>(); } grouper = new MB3_MeshBakerGrouperCluster(data, gos); } if (t == ClusterType.none) { grouper = new MB3_MeshBakerGrouperNone(data); } return(grouper); }
void AddMeshBaker(MB3_TextureBaker tb, string key, List <Renderer> gaws) { int numVerts = 0; for (int i = 0; i < gaws.Count; i++) { Mesh m = MB_Utility.GetMesh(gaws[i].gameObject); if (m != null) { numVerts += m.vertexCount; } } GameObject nmb = new GameObject("MeshBaker-" + key); nmb.transform.position = Vector3.zero; MB3_MeshBakerCommon newMeshBaker; if (numVerts >= 65535) { newMeshBaker = nmb.AddComponent <MB3_MultiMeshBaker>(); newMeshBaker.useObjsToMeshFromTexBaker = false; } else { newMeshBaker = nmb.AddComponent <MB3_MeshBaker>(); newMeshBaker.useObjsToMeshFromTexBaker = false; } newMeshBaker.textureBakeResults = tb.textureBakeResults; newMeshBaker.transform.parent = tb.transform; for (int i = 0; i < gaws.Count; i++) { newMeshBaker.GetObjectsToCombine().Add(gaws[i].gameObject); } }
public void DoClustering(MB3_TextureBaker tb) { if (clusterGrouper == null) { Debug.LogError("Cluster Grouper was null."); return; } //todo warn for no objects and no material bake result Dictionary <string, List <Renderer> > cell2objs = clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine()); Debug.Log("Found " + cell2objs.Count + " cells with Renderers. Creating bakers."); if (clusterOnLMIndex) { Dictionary <string, List <Renderer> > cell2objsNew = new Dictionary <string, List <Renderer> >(); foreach (string key in cell2objs.Keys) { List <Renderer> gaws = cell2objs[key]; Dictionary <int, List <Renderer> > idx2objs = GroupByLightmapIndex(gaws); foreach (int keyIdx in idx2objs.Keys) { string keyNew = key + "-LM-" + keyIdx; cell2objsNew.Add(keyNew, idx2objs[keyIdx]); } } cell2objs = cell2objsNew; } foreach (string key in cell2objs.Keys) { List <Renderer> gaws = cell2objs[key]; AddMeshBaker(tb, key, gaws); } }
private void AddMeshBaker(MB3_TextureBaker tb, string key, List <Renderer> gaws) { int num = 0; for (int i = 0; i < gaws.Count; i++) { Mesh mesh = MB_Utility.GetMesh(gaws[i].gameObject); if (mesh != null) { num += mesh.vertexCount; } } GameObject gameObject = new GameObject("MeshBaker-" + key); gameObject.transform.position = Vector3.zero; MB3_MeshBakerCommon mb3_MeshBakerCommon; if (num >= 65535) { mb3_MeshBakerCommon = gameObject.AddComponent <MB3_MultiMeshBaker>(); mb3_MeshBakerCommon.useObjsToMeshFromTexBaker = false; } else { mb3_MeshBakerCommon = gameObject.AddComponent <MB3_MeshBaker>(); mb3_MeshBakerCommon.useObjsToMeshFromTexBaker = false; } mb3_MeshBakerCommon.textureBakeResults = tb.textureBakeResults; mb3_MeshBakerCommon.transform.parent = tb.transform; for (int j = 0; j < gaws.Count; j++) { mb3_MeshBakerCommon.GetObjectsToCombine().Add(gaws[j].gameObject); } }
/// <summary> /// </summary> /// <param name="path"> /// path[0] meshbaker生成器资源路径 /// path[1] meshbaker材质资源路径 /// path[2] meshbaker贴图资源路径 /// path[3] meshbaker合并对象资源路径 /// </param> /// <param name="type"></param> /// <param name="count"></param> public CharObjCreator(string[] paths, BattleObjManager.E_BATTLE_OBJECT_TYPE type, int count) { bool retCode = false; m_meshbakerGo = ResourcesManagerMediator. GetGameObjectFromResourcesManager(paths[0]); if (m_meshbakerGo == null) { Debug.LogError("加载baker生成器资源出错" + paths[0]); return; } MB3_TextureBaker textureBaker = m_meshbakerGo.GetComponent <MB3_TextureBaker>(); m_meshBaker = m_meshbakerGo.GetComponentInChildren <MB3_MeshBaker>(); retCode = InitBaker(paths, textureBaker, m_meshBaker); if (!retCode) { Debug.LogError("MeshBaker初始化失败"); return; } m_seed = ResourcesManagerMediator.GetGameObjectFromResourcesManager(paths[3]); if (m_seed == null) { Debug.LogError("加载种子资源失败 " + paths[3]); return; } m_seed.transform.position = INIT_POS; m_count = count; }
void OnGUI() { GUILayout.Label("Time to bake textures: " + elapsedTime); if (GUILayout.Button("Combine textures & build combined mesh")) { MB3_MeshBaker meshbaker = target.GetComponent <MB3_MeshBaker>(); MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>(); //These can be assets configured at runtime or you can create them // on the fly like this textureBaker.textureBakeResults = ScriptableObject.CreateInstance <MB2_TextureBakeResults>(); textureBaker.resultMaterial = new Material(Shader.Find("Diffuse")); float t1 = Time.realtimeSinceStartup; textureBaker.CreateAtlases(); elapsedTime = Time.realtimeSinceStartup - t1; meshbaker.ClearMesh(); //only necessary if your not sure whats in the combined mesh meshbaker.textureBakeResults = textureBaker.textureBakeResults; //Add the objects to the combined mesh meshbaker.AddDeleteGameObjects(textureBaker.GetObjectsToCombine().ToArray(), null); meshbaker.Apply(); } }
private bool InitBaker(string[] paths, MB3_TextureBaker textureBaker, MB3_MeshBaker meshBaker) { bool result = false; Material material = ResourcesManagerMediator. GetNoGameObjectFromResourcesManager <Material>(paths[1]); if (material == null) { Debug.LogError("加载合并材质资源失败" + paths[1]); return(result); } MB2_TextureBakeResults textureBakeResults = ResourcesManagerMediator. GetNoGameObjectFromResourcesManager <MB2_TextureBakeResults>(paths[2]); if (textureBakeResults == null) { Debug.LogError("加载MB2_TextureBakeResults资源失败" + paths[2]); return(result); } textureBaker.resultMaterial = material; textureBaker.textureBakeResults = textureBakeResults; meshBaker.textureBakeResults = textureBakeResults; result = true; return(result); }
public void BuildAllSource(MB3_TextureBaker mom) { SerializedObject tbr = new SerializedObject(mom); SerializedProperty resultMaterials = tbr.FindProperty("resultMaterials"); MB3_TextureBakerEditorInternal.ConfigureMutiMaterialsFromObjsToCombine (mom,resultMaterials,tbr); tbr.UpdateIfDirtyOrScript(); }
private static void _bakeAllChildMeshBakers(UnityEngine.Object target, ref SerializedObject grouper) { MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target; MB3_TextureBaker tb = tbg.GetComponent <MB3_TextureBaker>(); try { MB3_MeshBakerCommon[] mBakers = tbg.GetComponentsInChildren <MB3_MeshBakerCommon>(); for (int i = 0; i < mBakers.Length; i++) { bool createdDummyMaterialBakeResult; if (grouper.targetObject == tbg) { MB3_MeshBakerEditorFunctions.BakeIntoCombined(mBakers[i], out createdDummyMaterialBakeResult, ref grouper); } else { MB3_MeshBakerEditorFunctions.BakeIntoCombined(mBakers[i], out createdDummyMaterialBakeResult); } } } catch (Exception ex) { Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString()); } finally { EditorUtility.ClearProgressBar(); } }
public override List <GameObject> GetObjectsToCombine() { if (useObjsToMeshFromTexBaker) { MB3_TextureBaker tb = gameObject.GetComponent <MB3_TextureBaker>(); if (tb == null) { tb = gameObject.transform.parent.GetComponent <MB3_TextureBaker>(); } if (tb != null) { return(tb.GetObjectsToCombine()); } else { Debug.LogWarning("Use Objects To Mesh From Texture Baker was checked but no texture baker"); return(new List <GameObject>()); } } else { if (objsToMesh == null) { objsToMesh = new List <GameObject>(); } return(objsToMesh); } }
public static void CreateCombinedMaterialAssets(MB3_TextureBaker target, string pth) { MB3_TextureBaker mom = (MB3_TextureBaker)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); //newMat.shader = r.sharedMaterial.shader; MB3_TextureBaker.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 MB2_TextureBakeResults AssetDatabase.CreateAsset(ScriptableObject.CreateInstance <MB2_TextureBakeResults>(), pth); mom.textureBakeResults = (MB2_TextureBakeResults)AssetDatabase.LoadAssetAtPath(pth, typeof(MB2_TextureBakeResults)); AssetDatabase.Refresh(); }
public void BuildAllSource(MB3_TextureBaker mom) { SerializedObject tbr = new SerializedObject(mom); SerializedProperty resultMaterials = tbr.FindProperty("resultMaterials"); MB3_TextureBakerEditorInternal.ConfigureMutiMaterialsFromObjsToCombine(mom, resultMaterials, tbr); tbr.UpdateIfDirtyOrScript(); }
void bakeAllBakersInScene() { MB3_MeshBakerRoot[] bakers = (MB3_MeshBakerRoot[])FindObjectsOfType(typeof(MB3_MeshBakerRoot)); for (int i = 0; i < bakers.Length; i++) { if (bakers[i] is MB3_TextureBaker) { MB3_TextureBaker tb = (MB3_TextureBaker)bakers[i]; tb.CreateAtlases(updateProgressBar, true, new MB3_EditorMethods()); } } EditorUtility.ClearProgressBar(); }
/// <summary> /// Gets the texture baker on this component or its parent if it exists /// </summary> /// <returns>The texture baker.</returns> public MB3_TextureBaker GetTextureBaker() { MB3_TextureBaker tb = GetComponent <MB3_TextureBaker>(); if (tb != null) { return(tb); } if (transform.parent != null) { return(transform.parent.GetComponent <MB3_TextureBaker>()); } return(null); }
public MB3_TextureBaker GetTextureBaker() { MB3_TextureBaker component = base.GetComponent <MB3_TextureBaker>(); if (component != null) { return(component); } if (base.transform.parent != null) { return(base.transform.parent.GetComponent <MB3_TextureBaker>()); } return(null); }
void _init(MB3_TextureBaker target) { textureBaker = new SerializedObject(target); doMultiMaterial = textureBaker.FindProperty("_doMultiMaterial"); fixOutOfBoundsUVs = textureBaker.FindProperty("_fixOutOfBoundsUVs"); resultMaterial = textureBaker.FindProperty("_resultMaterial"); resultMaterials = textureBaker.FindProperty("resultMaterials"); atlasPadding = textureBaker.FindProperty("_atlasPadding"); resizePowerOfTwoTextures = textureBaker.FindProperty("_resizePowerOfTwoTextures"); customShaderPropNames = textureBaker.FindProperty("_customShaderPropNames"); objsToMesh = textureBaker.FindProperty("objsToMesh"); maxTilingBakeSize = textureBaker.FindProperty("_maxTilingBakeSize"); textureBakeResults = textureBaker.FindProperty("_textureBakeResults"); texturePackingAlgorithm = textureBaker.FindProperty("_packingAlgorithm"); }
void _init(MB3_TextureBaker target) { textureBaker = new SerializedObject(target); doMultiMaterial = textureBaker.FindProperty("_doMultiMaterial"); fixOutOfBoundsUVs = textureBaker.FindProperty("_fixOutOfBoundsUVs"); resultMaterial = textureBaker.FindProperty("_resultMaterial"); resultMaterials = textureBaker.FindProperty("resultMaterials"); atlasPadding = textureBaker.FindProperty("_atlasPadding"); resizePowerOfTwoTextures = textureBaker.FindProperty("_resizePowerOfTwoTextures"); customShaderProperties= textureBaker.FindProperty("_customShaderProperties"); objsToMesh = textureBaker.FindProperty("objsToMesh"); maxTilingBakeSize = textureBaker.FindProperty("_maxTilingBakeSize"); maxAtlasSize = textureBaker.FindProperty("_maxAtlasSize"); textureBakeResults = textureBaker.FindProperty("_textureBakeResults"); texturePackingAlgorithm = textureBaker.FindProperty("_packingAlgorithm"); forcePowerOfTwoAtlas = textureBaker.FindProperty("_meshBakerTexturePackerForcePowerOfTwo"); }
void OnBuiltAtlasesSuccess() { Debug.Log("Calling success callback. baking meshes"); MB3_MeshBaker meshbaker = target.GetComponentInChildren <MB3_MeshBaker>(); MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>(); //elapsedTime = Time.realtimeSinceStartup - t1; if (result.isFinished && result.success) { meshbaker.ClearMesh(); //only necessary if your not sure whats in the combined mesh meshbaker.textureBakeResults = textureBaker.textureBakeResults; //Add the objects to the combined mesh meshbaker.AddDeleteGameObjects(textureBaker.GetObjectsToCombine().ToArray(), null, true); meshbaker.Apply(); } Debug.Log("Completed baking textures on frame " + Time.frameCount); }
public static GameObject CreateNewMeshBaker() { MB3_TextureBaker[] mbs = (MB3_TextureBaker[])GameObject.FindObjectsOfType(typeof(MB3_TextureBaker)); 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 ex) { if (ex == null) { ex = null; //Do nothing supress compiler warning } } GameObject nmb = new GameObject("TextureBaker (" + largest + ")"); nmb.transform.position = Vector3.zero; MB3_TextureBaker tb = nmb.AddComponent <MB3_TextureBaker>(); tb.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker; MB3_MeshBakerGrouper mbg = nmb.AddComponent <MB3_MeshBakerGrouper>(); GameObject meshBaker = new GameObject("MultiMeshBaker"); MB3_MultiMeshBaker mmb = meshBaker.AddComponent <MB3_MultiMeshBaker>(); mmb.meshCombiner.settingsHolder = mbg; meshBaker.transform.parent = nmb.transform; return(nmb); }
void OnGUI() { GUILayout.Label("Time to bake textures: " + elapsedTime); if (GUILayout.Button("Combine textures & build combined mesh all at once")) { MB3_MeshBaker meshbaker = target.GetComponentInChildren <MB3_MeshBaker>(); MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>(); //These can be assets configured at runtime or you can create them // on the fly like this textureBaker.textureBakeResults = ScriptableObject.CreateInstance <MB2_TextureBakeResults>(); textureBaker.resultMaterial = new Material(Shader.Find(GetShaderNameForPipeline())); float t1 = Time.realtimeSinceStartup; textureBaker.CreateAtlases(); elapsedTime = Time.realtimeSinceStartup - t1; meshbaker.ClearMesh(); //only necessary if your not sure whats in the combined mesh meshbaker.textureBakeResults = textureBaker.textureBakeResults; //Add the objects to the combined mesh meshbaker.AddDeleteGameObjects(textureBaker.GetObjectsToCombine().ToArray(), null, true); meshbaker.Apply(); } if (GUILayout.Button("Combine textures & build combined mesh using coroutine")) { Debug.Log("Starting to bake textures on frame " + Time.frameCount); MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>(); //These can be assets configured at runtime or you can create them // on the fly like this textureBaker.textureBakeResults = ScriptableObject.CreateInstance <MB2_TextureBakeResults>(); textureBaker.resultMaterial = new Material(Shader.Find(GetShaderNameForPipeline())); //register an OnSuccess function to be called when texture baking is complete textureBaker.onBuiltAtlasesSuccess = new MB3_TextureBaker.OnCombinedTexturesCoroutineSuccess(OnBuiltAtlasesSuccess); StartCoroutine(textureBaker.CreateAtlasesCoroutine(null, result, false, null, .01f)); } }
private static void _enableDisableRenderers(UnityEngine.Object target, bool enableRenderers) { MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target; MB3_TextureBaker tb = tbg.GetComponent <MB3_TextureBaker>(); try { MB3_MeshBakerCommon[] mBakers = tbg.GetComponentsInChildren <MB3_MeshBakerCommon>(); for (int i = 0; i < mBakers.Length; i++) { mBakers[i].EnableDisableSourceObjectRenderers(enableRenderers); } } catch (Exception ex) { Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString()); } finally { EditorUtility.ClearProgressBar(); } }
public override List <GameObject> GetObjectsToCombine() { if (!this.useObjsToMeshFromTexBaker) { if (this.objsToMesh == null) { this.objsToMesh = new List <GameObject>(); } return(this.objsToMesh); } MB3_TextureBaker component = base.gameObject.GetComponent <MB3_TextureBaker>(); if (component == null) { component = base.gameObject.transform.parent.GetComponent <MB3_TextureBaker>(); } if (component != null) { return(component.GetObjectsToCombine()); } Debug.LogWarning("Use Objects To Mesh From Texture Baker was checked but no texture baker"); return(new List <GameObject>()); }
public static void MigrateTestureBakerToVersion3Component(GameObject go) { MB2_TextureBaker tb2 = go.GetComponent <MB2_TextureBaker>(); if (tb2 == null) { return; } Debug.Log("Migrating Texture Baker"); MB3_TextureBaker tb3 = go.AddComponent <MB3_TextureBaker>(); tb3.atlasPadding = tb2.atlasPadding; tb3.doMultiMaterial = tb2.doMultiMaterial; tb3.fixOutOfBoundsUVs = tb2.fixOutOfBoundsUVs; tb3.maxTilingBakeSize = tb2.maxTilingBakeSize; tb3.objsToMesh = tb2.objsToMesh; tb3.packingAlgorithm = tb2.texturePackingAlgorithm; tb3.resizePowerOfTwoTextures = tb2.resizePowerOfTwoTextures; tb3.resultMaterial = tb2.resultMaterial; tb3.resultMaterials = tb2.resultMaterials; tb3.textureBakeResults = tb2.textureBakeResults; DestroyImmediate(tb2); }
void drawTabAddObjectsToBakers() { if (helpBoxString == null) { helpBoxString = ""; } EditorGUILayout.HelpBox("To add, select one or more objects in the hierarchy view. Child Game Objects with MeshRender or SkinnedMeshRenderer will be added. Use the fields below to filter what is added." + "To remove, use the fields below to filter what is removed.\n" + helpBoxString, UnityEditor.MessageType.None); target = (MB3_MeshBakerRoot)EditorGUILayout.ObjectField("Target to add objects to", target, typeof(MB3_MeshBakerRoot), true); if (target != null) { targetGO = target.gameObject; } else { targetGO = null; } if (targetGO != oldTargetGO && targetGO != null) { textureBaker = targetGO.GetComponent <MB3_TextureBaker>(); meshBaker = targetGO.GetComponent <MB3_MeshBaker>(); tbe = new MB3_TextureBakerEditorInternal(); mbe = new MB3_MeshBakerEditorInternal(); oldTargetGO = targetGO; if (textureBaker != null) { serializedObject = new SerializedObject(textureBaker); tbe.OnEnable(serializedObject); } else if (meshBaker != null) { serializedObject = new SerializedObject(meshBaker); mbe.OnEnable(serializedObject); } } EditorGUIUtility.labelWidth = 300; onlyStaticObjects = EditorGUILayout.Toggle("Only Static Objects", onlyStaticObjects); onlyEnabledObjects = EditorGUILayout.Toggle("Only Enabled Objects", onlyEnabledObjects); excludeMeshesWithOBuvs = EditorGUILayout.Toggle("Exclude meshes with out-of-bounds UVs", excludeMeshesWithOBuvs); excludeMeshesAlreadyAddedToBakers = EditorGUILayout.Toggle("Exclude GameObjects already added to bakers", excludeMeshesAlreadyAddedToBakers); mat = (Material)EditorGUILayout.ObjectField("Using Material", mat, typeof(Material), true); shaderMat = (Material)EditorGUILayout.ObjectField("Using Shader", shaderMat, typeof(Material), true); string[] lightmapDisplayValues = new string[257]; int[] lightmapValues = new int[257]; lightmapValues[0] = -2; lightmapValues[1] = -1; lightmapDisplayValues[0] = "don't filter on lightmapping"; lightmapDisplayValues[1] = "not lightmapped"; for (int i = 2; i < lightmapDisplayValues.Length; i++) { lightmapDisplayValues[i] = "" + i; lightmapValues[i] = i; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Using Lightmap Index "); lightmapIndex = EditorGUILayout.IntPopup(lightmapIndex, lightmapDisplayValues, lightmapValues); EditorGUILayout.EndHorizontal(); if (regExParseError != null && regExParseError.Length > 0) { EditorGUILayout.HelpBox("Error In Regular Expression:\n" + regExParseError, MessageType.Error); } searchRegEx = EditorGUILayout.TextField(GUIContentRegExpression, searchRegEx); EditorGUILayout.Separator(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Add Selected Meshes To Target")) { addSelectedObjects(); } if (GUILayout.Button("Remove Matching Meshes From Target")) { removeSelectedObjects(); } EditorGUILayout.EndHorizontal(); if (textureBaker != null) { MB_EditorUtil.DrawSeparator(); tbFoldout = EditorGUILayout.Foldout(tbFoldout, "Texture Baker"); if (tbFoldout) { tbe.DrawGUI(serializedObject, (MB3_TextureBaker)textureBaker, typeof(MB3_MeshBakerEditorWindow)); } } if (meshBaker != null) { MB_EditorUtil.DrawSeparator(); mbFoldout = EditorGUILayout.Foldout(mbFoldout, "Mesh Baker"); if (mbFoldout) { mbe.DrawGUI(serializedObject, (MB3_MeshBaker)meshBaker, typeof(MB3_MeshBakerEditorWindow)); } } }
void drawTabAddObjectsToBakers(){ EditorGUILayout.HelpBox("Select one or more objects in the hierarchy view. Child Game Objects with MeshRender will be added. Use the fields below to filter what is added.", UnityEditor.MessageType.None); target = (MB3_MeshBakerRoot) EditorGUILayout.ObjectField("Target to add objects to",target,typeof(MB3_MeshBakerRoot),true); if (target != null){ targetGO = target.gameObject; } else { targetGO = null; } if (targetGO != oldTargetGO && targetGO != null){ textureBaker = targetGO.GetComponent<MB3_TextureBaker>(); meshBaker = targetGO.GetComponent<MB3_MeshBaker>(); tbe = new MB3_TextureBakerEditorInternal(); mbe = new MB3_MeshBakerEditorInternal(); oldTargetGO = targetGO; } EditorGUIUtility.labelWidth = 300; onlyStaticObjects = EditorGUILayout.Toggle("Only Static Objects", onlyStaticObjects); onlyEnabledObjects = EditorGUILayout.Toggle("Only Enabled Objects", onlyEnabledObjects); excludeMeshesWithOBuvs = EditorGUILayout.Toggle("Exclude meshes with out-of-bounds UVs", excludeMeshesWithOBuvs); excludeMeshesAlreadyAddedToBakers = EditorGUILayout.Toggle("Exclude GameObjects already added to bakers", excludeMeshesAlreadyAddedToBakers); mat = (Material) EditorGUILayout.ObjectField("Using Material",mat,typeof(Material),true); shaderMat = (Material) EditorGUILayout.ObjectField("Using Shader",shaderMat,typeof(Material),true); string[] lightmapDisplayValues = new string[257]; int[] lightmapValues = new int[257]; lightmapValues[0] = -2; lightmapValues[1] = -1; lightmapDisplayValues[0] = "don't filter on lightmapping"; lightmapDisplayValues[1] = "not lightmapped"; for (int i = 2; i < lightmapDisplayValues.Length; i++){ lightmapDisplayValues[i] = "" + i; lightmapValues[i] = i; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Using Lightmap Index "); lightmapIndex = EditorGUILayout.IntPopup(lightmapIndex, lightmapDisplayValues, lightmapValues); EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); if (GUILayout.Button("Add Selected Meshes To Target")){ addSelectedObjects(); } if (textureBaker != null){ MB_EditorUtil.DrawSeparator(); tbFoldout = EditorGUILayout.Foldout(tbFoldout,"Texture Baker"); if (tbFoldout){ tbe.DrawGUI((MB3_TextureBaker) textureBaker, typeof(MB3_MeshBakerEditorWindow)); } } if (meshBaker != null){ MB_EditorUtil.DrawSeparator(); mbFoldout = EditorGUILayout.Foldout(mbFoldout,"Mesh Baker"); if (mbFoldout){ mbe.DrawGUI((MB3_MeshBaker) meshBaker, typeof(MB3_MeshBakerEditorWindow)); } } }
void createAndSetupBaker(List <GameObjectFilterInfo> gaws, string pthRoot) { for (int i = gaws.Count - 1; i >= 0; i--) { if (gaws[i].go == null) { gaws.RemoveAt(i); } } if (gaws.Count < 1) { Debug.LogError("No game objects."); return; } if (pthRoot == null || pthRoot == "") { Debug.LogError("Folder for saving created assets was not set."); return; } int numVerts = 0; for (int i = 0; i < gaws.Count; i++) { if (gaws[i].go != null) { numVerts = gaws[i].numVerts; } } GameObject newMeshBaker = null; if (numVerts >= 65535) { newMeshBaker = MB3_MultiMeshBakerEditor.CreateNewMeshBaker(); } else { newMeshBaker = MB3_MeshBakerEditor.CreateNewMeshBaker(); } newMeshBaker.name = ("MeshBaker-" + gaws[0].shaderName + "-LM" + gaws[0].lightmapIndex).ToString().Replace("/", "-"); MB3_TextureBaker tb = newMeshBaker.GetComponent <MB3_TextureBaker>(); MB3_MeshBakerCommon mb = tb.GetComponentInChildren <MB3_MeshBakerCommon>(); tb.GetObjectsToCombine().Clear(); for (int i = 0; i < gaws.Count; i++) { if (gaws[i].go != null) { tb.GetObjectsToCombine().Add(gaws[i].go); } } if (gaws[0].numMaterials > 1) { string pthMat = AssetDatabase.GenerateUniqueAssetPath(pthRoot + newMeshBaker.name + ".asset"); MB3_TextureBakerEditorInternal.CreateCombinedMaterialAssets(tb, pthMat); tb.doMultiMaterial = true; SerializedObject tbr = new SerializedObject(tb); SerializedProperty resultMaterials = tbr.FindProperty("resultMaterials"); MB3_TextureBakerEditorInternal.ConfigureMutiMaterialsFromObjsToCombine(tb, resultMaterials, tbr); } else { string pthMat = AssetDatabase.GenerateUniqueAssetPath(pthRoot + newMeshBaker.name + ".asset"); MB3_TextureBakerEditorInternal.CreateCombinedMaterialAssets(tb, pthMat); } if (gaws[0].isMeshRenderer) { mb.meshCombiner.renderType = MB_RenderType.meshRenderer; } else { mb.meshCombiner.renderType = MB_RenderType.skinnedMeshRenderer; } }
/// <summary> /// Bakes a combined mesh. /// </summary> /// <param name="so">If this is being called from Inspector code then pass in the SerializedObject for the component. /// This is necessary for "bake into prefab" which can corrupt the SerializedObject.</param> public static bool BakeIntoCombined(MB3_MeshBakerCommon mom, out bool createdDummyTextureBakeResults, ref SerializedObject so) { MB2_OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption; createdDummyTextureBakeResults = false; // Initial Validate { if (mom.meshCombiner.resultSceneObject != null && (MBVersionEditor.PrefabUtility_GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.modelPrefabAsset || MBVersionEditor.PrefabUtility_GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.prefabAsset)) { Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field."); mom.meshCombiner.resultSceneObject = null; } if (prefabOrSceneObject != MB2_OutputOptions.bakeIntoPrefab && prefabOrSceneObject != MB2_OutputOptions.bakeIntoSceneObject) { Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject"); return(false); } if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab) { if (MB3_MeshCombiner.EVAL_VERSION) { Debug.LogError("Cannot BakeIntoPrefab with evaluation version."); return(false); } if (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); } 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 a project asset. Is it an instance in the scene?"); return(false); } } } { // Find or create texture bake results 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."); } } } } // Second level of validation now that TextureBakeResults exists. 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); } // Add Delete Game Objects bool success; if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoSceneObject) { success = _BakeIntoCombinedSceneObject(mom, createdDummyTextureBakeResults, ref so); } else if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab) { success = _BakeIntoCombinedPrefab(mom, createdDummyTextureBakeResults, ref so); } else { Debug.LogError("Should be impossible."); success = false; } if (mom.clearBuffersAfterBake) { mom.meshCombiner.ClearBuffers(); } if (createdDummyTextureBakeResults) { MB_Utility.Destroy(mom.textureBakeResults); } return(success); }
public static bool BakeIntoCombined(MB3_MeshBakerCommon mom) { MB2_OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption; 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.GetComponent <MB3_TextureBaker>(); if (mom.textureBakeResults == null && tb != null) { mom.textureBakeResults = tb.textureBakeResults; } 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 && (PrefabUtility.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.ModelPrefab || PrefabUtility.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(Unwrapping.GenerateSecondaryUVSet); Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count)); if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoSceneObject) { PrefabType pt = PrefabUtility.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 == 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."); } else { RebuildPrefab(mom); } } else { Debug.LogError("Unknown parameter"); return(false); } } return(true); }
//posibilities // using fixOutOfBoundsUVs or not // public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker 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; } Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shader2Material_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >(); Dictionary <Material, Mesh> obUVobject2mesh_map = new Dictionary <Material, Mesh>(); //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; } } //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs if (mom.doMultiMaterialSplitAtlasesIfOBUVs) { for (int i = 0; i < mom.GetObjectsToCombine().Count; i++) { GameObject go = mom.GetObjectsToCombine()[i]; Mesh m = MB_Utility.GetMesh(go); MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult(); Renderer r = go.GetComponent <Renderer>(); for (int j = 0; j < r.sharedMaterials.Length; j++) { if (MB_Utility.hasOutOfBoundsUVs(m, ref dummyMar, j)) { if (!obUVobject2mesh_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"); obUVobject2mesh_map.Add(r.sharedMaterials[j], m); } } } } } //second pass put other materials without OB uvs in a shader to material 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 (!obUVobject2mesh_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 (!shader2Material_map.TryGetValue(newKey, out binsOfMatsThatUseShader)) { binsOfMatsThatUseShader = new List <List <Material> >(); binsOfMatsThatUseShader.Add(new List <Material>()); shader2Material_map.Add(newKey, binsOfMatsThatUseShader); } if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j])) { binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]); } } } } int numResMats = shader2Material_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 if (mom.doMultiMaterialSplitAtlasesIfTooBig) { if (mom.packingAlgorithm == MB2_PackingAlgorithmEnum.UnitysPackTextures) { Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split."); } else { numResMats = 0; foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys) { List <List <Material> > binsOfMatsThatUseShader = shader2Material_map[sh]; List <Material> allMatsThatUserShader = binsOfMatsThatUseShader[0];//at this point everything is in the same list binsOfMatsThatUseShader.RemoveAt(0); MB3_TextureCombiner 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); 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); } numResMats += binsOfMatsThatUseShader.Count; } } } //build the result materials if (shader2Material_map.Count == 0 && obUVobject2mesh_map.Count == 0) { Debug.LogError("Found no materials in list of objects to combine"); } mom.resultMaterials = new MB_MultiMaterial[numResMats + obUVobject2mesh_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 shader2Material_map.Keys) { foreach (List <Material> matsThatUse in shader2Material_map[sh]) { MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial(); mm.sourceMaterials = matsThatUse; 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 (matsThatUse.Count > 0 && matsThatUse[0] != null) { MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]); } AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } } foreach (Material m in obUVobject2mesh_map.Keys) { MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_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")); MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } MBVersionEditor.UpdateIfDirtyOrScript(textureBaker); }
/* tried to see if the MultiMaterialConfig could be done using the GroupBy filters. Saddly it didn't work */ public static void ConfigureMutiMaterialsFromObjsToCombine2(MB3_TextureBaker 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, MB_Utility.MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MB_Utility.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 = MB_Utility.GetMesh(gameObjects[i].go); int nVerts = 0; if (mm != null) { nVerts += mm.vertexCount; MB_Utility.MeshAnalysisResult mar; if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar)) { //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f); MB_Utility.hasOutOfBoundsUVs(mm, ref mar); //Rect dummy = mar.uvRect; MB_Utility.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 (!MB_Utility.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 = MB3_MeshBakerEditorWindow.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize); mom.resultMaterials = new MB_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) { MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_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")); MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } MBVersionEditor.UpdateIfDirtyOrScript(textureBaker); }
public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker 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("Material Bake Result asset must be set before using this operation."); return; } Dictionary<Shader,List<Material>> shader2Material_map = new Dictionary<Shader, List<Material>>(); Dictionary<Material,Mesh> obUVobject2material_map = new Dictionary<Material,Mesh>(); //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; } } //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs if (!mom.fixOutOfBoundsUVs){ for (int i = 0; i < mom.GetObjectsToCombine().Count; i++){ GameObject go = mom.GetObjectsToCombine()[i]; Mesh m = MB_Utility.GetMesh(go); Rect dummy = new Rect(); MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult(); Renderer r = go.GetComponent<Renderer>(); for (int j = 0; j < r.sharedMaterials.Length; j++){ if (MB_Utility.hasOutOfBoundsUVs(m, ref dummy, ref dummyMar, j)){ if (!obUVobject2material_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"); obUVobject2material_map.Add(r.sharedMaterials[j],m); } } } } } //second pass put other materials without OB uvs in a shader to material 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 (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j])) { if (r.sharedMaterials[j] == null) continue; List<Material> matsThatUseShader = null; if (!shader2Material_map.TryGetValue(r.sharedMaterials[j].shader, out matsThatUseShader)){ matsThatUseShader = new List<Material>(); shader2Material_map.Add(r.sharedMaterials[j].shader, matsThatUseShader); } if (!matsThatUseShader.Contains(r.sharedMaterials[j])) matsThatUseShader.Add(r.sharedMaterials[j]); } } } if (shader2Material_map.Count == 0 && obUVobject2material_map.Count == 0) Debug.LogError("Found no materials in list of objects to combine"); mom.resultMaterials = new MB_MultiMaterial[shader2Material_map.Count + obUVobject2material_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(Shader sh in shader2Material_map.Keys){ List<Material> matsThatUse = shader2Material_map[sh]; MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial(); mm.sourceMaterials = matsThatUse; string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(Shader.Find("Diffuse")); if (matsThatUse.Count > 0 && matsThatUse[0] != null){ MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]); } AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matName,typeof(Material)); k++; } foreach(Material m in obUVobject2material_map.Keys){ MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial(); mm.sourceMaterials = new List<Material>(); mm.sourceMaterials.Add(m); string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(Shader.Find("Diffuse")); MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat,m); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matName,typeof(Material)); k++; } textureBaker.UpdateIfDirtyOrScript(); }
public static void CreateCombinedMaterialAssets(MB3_TextureBaker target, string pth){ MB3_TextureBaker mom = (MB3_TextureBaker) 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); //newMat.shader = r.sharedMaterial.shader; MB3_TextureBaker.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 MB2_TextureBakeResults AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<MB2_TextureBakeResults>(),pth); mom.textureBakeResults = (MB2_TextureBakeResults) AssetDatabase.LoadAssetAtPath(pth, typeof(MB2_TextureBakeResults)); AssetDatabase.Refresh(); }
public void DrawGUI(MB3_TextureBaker mom, System.Type editorWindow){ if (textureBaker == null){ _init(mom); } textureBaker.Update(); showInstructions = EditorGUILayout.Foldout(showInstructions,"Instructions:"); 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); } mom.LOG_LEVEL = (MB2_LogLevel) EditorGUILayout.EnumPopup("Log Level", mom.LOG_LEVEL); EditorGUILayout.Separator(); EditorGUILayout.LabelField("Objects To Be Combined",EditorStyles.boldLabel); if (GUILayout.Button(openToolsWindowLabelContent)){ MB3_MeshBakerEditorWindowInterface mmWin = (MB3_MeshBakerEditorWindowInterface) EditorWindow.GetWindow(editorWindow); mmWin.target = (MB3_MeshBakerRoot) mom; } EditorGUILayout.PropertyField(objsToMesh,objectsToCombineGUIContent, true); EditorGUILayout.Separator(); EditorGUILayout.LabelField("Output",EditorStyles.boldLabel); if (GUILayout.Button(createPrefabAndMaterialLabelContent)){ string newPrefabPath = EditorUtility.SaveFilePanelInProject("Asset name", "", "asset", "Enter a name for the baked texture results"); if (newPrefabPath != null){ CreateCombinedMaterialAssets(mom, newPrefabPath); } } EditorGUILayout.PropertyField(textureBakeResults, textureBakeResultsGUIContent); if (textureBakeResults.objectReferenceValue != null){ showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained"); if (showContainsReport){ EditorGUILayout.HelpBox(((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info); } } EditorGUILayout.PropertyField(doMultiMaterial,new GUIContent("Multiple Combined Materials")); if (mom.doMultiMaterial){ EditorGUILayout.LabelField("Source Material To Combined Mapping",EditorStyles.boldLabel); if (GUILayout.Button(configMultiMatFromObjsContent)){ ConfigureMutiMaterialsFromObjsToCombine(mom,resultMaterials,textureBaker); } EditorGUILayout.BeginHorizontal(); resultMaterialsFoldout = EditorGUILayout.Foldout(resultMaterialsFoldout, combinedMaterialsGUIContent); if(GUILayout.Button(insertContent, EditorStyles.miniButtonLeft, buttonWidth)){ if (resultMaterials.arraySize == 0){ mom.resultMaterials = new MB_MultiMaterial[1]; } else { resultMaterials.InsertArrayElementAtIndex(resultMaterials.arraySize-1); } } 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(); string s = ""; if (i < mom.resultMaterials.Length && mom.resultMaterials[i] != null && mom.resultMaterials[i].combinedMaterial != null) s = mom.resultMaterials[i].combinedMaterial.shader.ToString(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("---------- submesh:" + i + " " + s,EditorStyles.boldLabel); if(GUILayout.Button(deleteContent, EditorStyles.miniButtonRight, buttonWidth)){ resultMaterials.DeleteArrayElementAtIndex(i); } if (i < resultMaterials.arraySize){ EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); SerializedProperty resMat = resultMaterials.GetArrayElementAtIndex(i); EditorGUILayout.PropertyField(resMat.FindPropertyRelative("combinedMaterial")); SerializedProperty sourceMats = resMat.FindPropertyRelative("sourceMaterials"); EditorGUILayout.PropertyField(sourceMats,true); } } } } else { EditorGUILayout.PropertyField(resultMaterial,new GUIContent("Combined Mesh Material")); } EditorGUILayout.Separator(); EditorGUILayout.LabelField("Material Bake Options",EditorStyles.boldLabel); EditorGUILayout.PropertyField(atlasPadding,new GUIContent("Atlas Padding")); EditorGUILayout.PropertyField(maxAtlasSize,maxAtlasSizeGUIContent); EditorGUILayout.PropertyField(resizePowerOfTwoTextures, resizePowerOfTwoGUIContent); EditorGUILayout.PropertyField(customShaderProperties,customShaderPropertyNamesGUIContent,true); EditorGUILayout.PropertyField(maxTilingBakeSize, maxTilingBakeSizeGUIContent); EditorGUILayout.PropertyField(fixOutOfBoundsUVs,fixOutOfBoundsGUIContent); if (texturePackingAlgorithm.intValue == (int) MB2_PackingAlgorithmEnum.UnitysPackTextures){ EditorGUILayout.HelpBox("Unity's texture packer has memory problems and frequently crashes the editor.",MessageType.Warning); } EditorGUILayout.PropertyField(texturePackingAlgorithm, texturePackingAgorithmGUIContent); if (texturePackingAlgorithm.intValue == (int) MB2_PackingAlgorithmEnum.MeshBakerTexturePacker || texturePackingAlgorithm.intValue == (int) MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Fast){ EditorGUILayout.PropertyField(forcePowerOfTwoAtlas,forcePowerOfTwoAtlasContent); } EditorGUILayout.Separator(); if (GUILayout.Button("Bake Materials Into Combined Material")){ mom.CreateAtlases(updateProgressBar, true, new MB3_EditorMethods()); EditorUtility.ClearProgressBar(); if (mom.textureBakeResults != null) EditorUtility.SetDirty(mom.textureBakeResults); } textureBaker.ApplyModifiedProperties(); textureBaker.SetIsDifferentCacheDirty(); }
public void DoClustering(MB3_TextureBaker tb){ if (clusterGrouper == null){ Debug.LogError("Cluster Grouper was null."); return; } //todo warn for no objects and no material bake result Dictionary<string,List<Renderer>> cell2objs = clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine()); Debug.Log ("Found " + cell2objs.Count + " cells with Renderers. Creating bakers."); if (clusterOnLMIndex){ Dictionary<string,List<Renderer>> cell2objsNew = new Dictionary<string, List<Renderer>>(); foreach (string key in cell2objs.Keys){ List<Renderer> gaws = cell2objs[key]; Dictionary<int,List<Renderer>> idx2objs = GroupByLightmapIndex(gaws); foreach(int keyIdx in idx2objs.Keys){ string keyNew = key + "-LM-" + keyIdx; cell2objsNew.Add (keyNew,idx2objs[keyIdx]); } } cell2objs = cell2objsNew; } foreach (string key in cell2objs.Keys){ List<Renderer> gaws = cell2objs[key]; AddMeshBaker (tb,key,gaws); } }
void AddMeshBaker(MB3_TextureBaker tb, string key, List<Renderer> gaws){ int numVerts = 0; for (int i = 0; i < gaws.Count; i++){ Mesh m = MB_Utility.GetMesh(gaws[i].gameObject); if (m != null) numVerts += m.vertexCount; } GameObject nmb = new GameObject("MeshBaker-" + key); nmb.transform.position = Vector3.zero; MB3_MeshBakerCommon newMeshBaker; if (numVerts >= 65535){ newMeshBaker = nmb.AddComponent<MB3_MultiMeshBaker>(); newMeshBaker.useObjsToMeshFromTexBaker = false; } else { newMeshBaker = nmb.AddComponent<MB3_MeshBaker>(); newMeshBaker.useObjsToMeshFromTexBaker = false; } newMeshBaker.textureBakeResults = tb.textureBakeResults; newMeshBaker.transform.parent = tb.transform; for (int i = 0; i < gaws.Count; i++){ newMeshBaker.GetObjectsToCombine().Add (gaws[i].gameObject); } }