MB_TextureBakerEditorConfigureTextureArrays.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. //----------------------------------------------
  2. // MeshBaker
  3. // Copyright © 2011-2012 Ian Deane
  4. //----------------------------------------------
  5. using UnityEngine;
  6. using System.Collections;
  7. using System.IO;
  8. using System;
  9. using System.Collections.Specialized;
  10. using System.Collections.Generic;
  11. using System.Text.RegularExpressions;
  12. using DigitalOpus.MB.Core;
  13. using UnityEditor;
  14. namespace DigitalOpus.MB.MBEditor
  15. {
  16. public class MB_TextureBakerConfigureTextureArrays
  17. {
  18. private class Slice
  19. {
  20. public List<MB_MaterialAndUVRect> atlasRects;
  21. public AtlasPackingResult packingResult;
  22. public int numAtlasRects;
  23. }
  24. private static GUIContent gc_TextureArrayOutputFormats = new GUIContent(
  25. "Texture Array Output Formats",
  26. "Texture Arrays do not have a 'TextureImporter' that lets you change the TextureArray format." +
  27. "You can provide a list of formats to be generated here. You will probably have one set of formats per platform.");
  28. public static void DrawTextureArrayConfiguration(MB3_TextureBaker momm, SerializedObject textureBaker, MB3_TextureBakerEditorInternal editorInternal)
  29. {
  30. EditorGUILayout.BeginVertical(editorInternal.editorStyles.multipleMaterialBackgroundStyle);
  31. EditorGUILayout.LabelField("Texture Array Slice Configuration", EditorStyles.boldLabel);
  32. float oldLabelWidth = EditorGUIUtility.labelWidth;
  33. if (GUILayout.Button(MB3_TextureBakerEditorInternal.configAtlasTextureSlicesFromObjsContent))
  34. {
  35. ConfigureTextureArraysFromObjsToCombine(momm, editorInternal.resultMaterialsTexArray, textureBaker);
  36. }
  37. if (GUILayout.Button("Report texture sizes"))
  38. {
  39. Debug.Log(ReportTextureSizesAndFormats(momm));
  40. }
  41. if (editorInternal.textureArrayOutputFormats.arraySize == 0)
  42. {
  43. EditorGUILayout.HelpBox("You need at least one output format.", MessageType.Error);
  44. }
  45. EditorGUILayout.PropertyField(editorInternal.textureArrayOutputFormats, gc_TextureArrayOutputFormats, true);
  46. EditorGUILayout.BeginHorizontal();
  47. editorInternal.resultMaterialsFoldout = EditorGUILayout.Foldout(editorInternal.resultMaterialsFoldout, MB3_TextureBakerEditorInternal.textureArrayCombinedMaterialFoldoutGUIContent);
  48. if (GUILayout.Button(MB3_TextureBakerEditorInternal.insertContent, EditorStyles.miniButtonLeft, MB3_TextureBakerEditorInternal.buttonWidth))
  49. {
  50. if (editorInternal.resultMaterialsTexArray.arraySize == 0)
  51. {
  52. momm.resultMaterialsTexArray = new MB_MultiMaterialTexArray[1];
  53. }
  54. else
  55. {
  56. int idx = editorInternal.resultMaterialsTexArray.arraySize - 1;
  57. editorInternal.resultMaterialsTexArray.InsertArrayElementAtIndex(idx);
  58. }
  59. }
  60. if (GUILayout.Button(MB3_TextureBakerEditorInternal.deleteContent, EditorStyles.miniButtonRight, MB3_TextureBakerEditorInternal.buttonWidth))
  61. {
  62. editorInternal.resultMaterialsTexArray.DeleteArrayElementAtIndex(editorInternal.resultMaterialsTexArray.arraySize - 1);
  63. }
  64. EditorGUILayout.EndHorizontal();
  65. if (editorInternal.resultMaterialsFoldout)
  66. {
  67. for (int i = 0; i < editorInternal.resultMaterialsTexArray.arraySize; i++)
  68. {
  69. EditorGUILayout.Separator();
  70. if (i % 2 == 1)
  71. {
  72. EditorGUILayout.BeginVertical(editorInternal.editorStyles.multipleMaterialBackgroundStyle);
  73. }
  74. else
  75. {
  76. EditorGUILayout.BeginVertical(editorInternal.editorStyles.multipleMaterialBackgroundStyleDarker);
  77. }
  78. string s = "";
  79. if (i < momm.resultMaterialsTexArray.Length && momm.resultMaterialsTexArray[i] != null && momm.resultMaterialsTexArray[i].combinedMaterial != null) s = momm.resultMaterialsTexArray[i].combinedMaterial.shader.ToString();
  80. EditorGUILayout.BeginHorizontal();
  81. EditorGUILayout.LabelField("---------- submesh:" + i + " " + s, EditorStyles.boldLabel);
  82. if (GUILayout.Button(MB3_TextureBakerEditorInternal.deleteContent, EditorStyles.miniButtonRight, MB3_TextureBakerEditorInternal.buttonWidth))
  83. {
  84. editorInternal.resultMaterialsTexArray.DeleteArrayElementAtIndex(i);
  85. }
  86. EditorGUILayout.EndHorizontal();
  87. if (i < editorInternal.resultMaterialsTexArray.arraySize)
  88. {
  89. EditorGUILayout.Separator();
  90. SerializedProperty resMat = editorInternal.resultMaterialsTexArray.GetArrayElementAtIndex(i);
  91. EditorGUILayout.PropertyField(resMat.FindPropertyRelative("combinedMaterial"));
  92. SerializedProperty slices = resMat.FindPropertyRelative("slices");
  93. EditorGUILayout.PropertyField(slices, true);
  94. }
  95. EditorGUILayout.EndVertical();
  96. }
  97. }
  98. EditorGUILayout.EndVertical();
  99. }
  100. public static string ReportTextureSizesAndFormats(MB3_TextureBaker mom)
  101. {
  102. if (mom.resultType != MB2_TextureBakeResults.ResultType.textureArray)
  103. {
  104. Debug.LogError("Result Type must be Texture Array.");
  105. return "";
  106. }
  107. for (int resMatIdx = 0; resMatIdx < mom.resultMaterialsTexArray.Length; resMatIdx++)
  108. {
  109. MB_MultiMaterialTexArray resMatTexArray = mom.resultMaterialsTexArray[resMatIdx];
  110. if (resMatTexArray.combinedMaterial == null)
  111. {
  112. Debug.LogError("Result Material " + resMatIdx + " is null");
  113. return "";
  114. }
  115. }
  116. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  117. // Visit each result material
  118. for (int resMatIdx = 0; resMatIdx < mom.resultMaterialsTexArray.Length; resMatIdx++)
  119. {
  120. MB_MultiMaterialTexArray resMatTexArray = mom.resultMaterialsTexArray[resMatIdx];
  121. // Do an atlas pack in order to collect all the textures needed by the result material
  122. // And group these by material texture property.
  123. MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
  124. combiner.saveAtlasesAsAssets = false;
  125. combiner.fixOutOfBoundsUVs = false;
  126. List<AtlasPackingResult> packingResults = new List<AtlasPackingResult>();
  127. Material tempMat = new Material(resMatTexArray.combinedMaterial.shader);
  128. List<Material> allSourceMaterials = new List<Material>();
  129. for (int sliceIdx = 0; sliceIdx < resMatTexArray.slices.Count; sliceIdx++)
  130. {
  131. List<Material> srcMats = new List<Material>();
  132. resMatTexArray.slices[sliceIdx].GetAllUsedMaterials(srcMats);
  133. for (int srcMatIdx = 0; srcMatIdx < srcMats.Count; srcMatIdx++)
  134. {
  135. if (srcMats[srcMatIdx] != null && !allSourceMaterials.Contains(srcMats[srcMatIdx]))
  136. {
  137. allSourceMaterials.Add(srcMats[srcMatIdx]);
  138. }
  139. }
  140. }
  141. MB_AtlasesAndRects atlasesAndRects = new MB_AtlasesAndRects();
  142. combiner.CombineTexturesIntoAtlases(null, atlasesAndRects, tempMat, mom.GetObjectsToCombine(), allSourceMaterials, null, packingResults,
  143. onlyPackRects:true, splitAtlasWhenPackingIfTooBig:false);
  144. // Now vist the packing results and collect all the textures
  145. Debug.Assert(packingResults.Count == 1);
  146. for (int texPropIdx = 0; texPropIdx < atlasesAndRects.texPropertyNames.Length; texPropIdx++)
  147. {
  148. string propertyName = atlasesAndRects.texPropertyNames[texPropIdx];
  149. sb.AppendLine(String.Format("Prop: {0}", propertyName));
  150. List<MB_MaterialAndUVRect> matsData = (List<MB_MaterialAndUVRect>)packingResults[0].data;
  151. HashSet<Material> visitedMats = new HashSet<Material>();
  152. for (int matAndGoIdx = 0; matAndGoIdx < matsData.Count; matAndGoIdx++)
  153. {
  154. Material mat = matsData[matAndGoIdx].material;
  155. if (visitedMats.Contains(mat)) continue;
  156. visitedMats.Add(mat);
  157. if (mat.HasProperty(propertyName))
  158. {
  159. Texture tex = mat.GetTexture(propertyName);
  160. if (tex != null)
  161. {
  162. string texFormatString = "UnknownFormat";
  163. string texWrapMode = "UnknownClampMode";
  164. if (tex is Texture2D)
  165. {
  166. texFormatString = ((Texture2D)tex).format.ToString();
  167. texWrapMode = ((Texture2D)tex).wrapMode.ToString();
  168. }
  169. sb.AppendLine(String.Format(" {0} x {1} format:{2} wrapMode:{3} {4}", tex.width.ToString().PadLeft(6,' '), tex.height.ToString().PadRight(6,' '), texFormatString.PadRight(20,' '), texWrapMode.PadRight(12,' '), tex.name));
  170. }
  171. }
  172. }
  173. }
  174. }
  175. return sb.ToString();
  176. }
  177. public static void ConfigureTextureArraysFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterialsTexArrays, SerializedObject textureBaker)
  178. {
  179. if (mom.GetObjectsToCombine().Count == 0)
  180. {
  181. Debug.LogError("You need to add some objects to combine before building the texture array result materials.");
  182. return;
  183. }
  184. if (resultMaterialsTexArrays.arraySize > 0)
  185. {
  186. Debug.LogError("You already have some texture array result materials configured. You must remove these before doing this operation.");
  187. return;
  188. }
  189. if (mom.textureBakeResults == null)
  190. {
  191. Debug.LogError("Texture Bake Result asset must be set before using this operation.");
  192. return;
  193. }
  194. //validate that the objects to be combined are valid
  195. for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
  196. {
  197. GameObject go = mom.GetObjectsToCombine()[i];
  198. if (go == null)
  199. {
  200. Debug.LogError("Null object in list of objects to combine at position " + i);
  201. return;
  202. }
  203. if (MB_Utility.GetMesh(go) == null)
  204. {
  205. Debug.LogError("Could not get mesh for object in list of objects to combine at position " + i);
  206. return;
  207. }
  208. Renderer r = go.GetComponent<Renderer>();
  209. if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
  210. {
  211. Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
  212. return;
  213. }
  214. if (r.sharedMaterial == null)
  215. {
  216. Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
  217. return;
  218. }
  219. }
  220. //Will sort into "result material"
  221. // slices
  222. Dictionary<MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List<Slice>> shader2ResultMat_map = new Dictionary<MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo, List<Slice>>();
  223. // first pass split by shader and analyse meshes.
  224. List<GameObject> objsToCombine = mom.GetObjectsToCombine();
  225. for (int meshIdx = 0; meshIdx < objsToCombine.Count; meshIdx++)
  226. {
  227. GameObject srcGo = objsToCombine[meshIdx];
  228. Mesh mesh = MB_Utility.GetMesh(srcGo);
  229. Renderer r = MB_Utility.GetRenderer(srcGo);
  230. if (mom.LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log("1st Pass 'Split By Shader' Processing Mesh: "+ mesh +" Num submeshes: " + r.sharedMaterials.Length);
  231. for (int submeshIdx = 0; submeshIdx < r.sharedMaterials.Length; submeshIdx++)
  232. {
  233. if (r.sharedMaterials[submeshIdx] == null) continue;
  234. MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo newKey = new MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo(r.sharedMaterials[submeshIdx].shader, r.sharedMaterials[submeshIdx]);
  235. // Initially we fill the list of srcMaterials with garbage MB_MaterialAndUVRects. Will get proper ones when we atlas pack.
  236. MB_MaterialAndUVRect submeshMaterial = new MB_MaterialAndUVRect(
  237. r.sharedMaterials[submeshIdx],
  238. new Rect(0, 0, 0, 0), // garbage value
  239. false, //garbage value
  240. new Rect(0, 0, 0, 0), // garbage value
  241. new Rect(0, 0, 0, 0), // garbage value
  242. new Rect(0, 0, 1, 1), // garbage value
  243. MB_TextureTilingTreatment.unknown, // garbage value
  244. r.name);
  245. submeshMaterial.objectsThatUse = new List<GameObject>();
  246. submeshMaterial.objectsThatUse.Add(r.gameObject);
  247. if (!shader2ResultMat_map.ContainsKey(newKey))
  248. {
  249. // this is a new shader create a new result material
  250. Slice srcMaterials = new Slice
  251. {
  252. atlasRects = new List<MB_MaterialAndUVRect>(),
  253. numAtlasRects = 1,
  254. };
  255. srcMaterials.atlasRects.Add(submeshMaterial);
  256. List<Slice> binsOfMatsThatUseShader = new List<Slice>();
  257. binsOfMatsThatUseShader.Add(srcMaterials);
  258. if (mom.LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(" Adding Source Material: " + submeshMaterial.material);
  259. shader2ResultMat_map.Add(newKey, binsOfMatsThatUseShader);
  260. }
  261. else
  262. {
  263. // there is a result material that uses this shader. Add this source material
  264. Slice srcMaterials = shader2ResultMat_map[newKey][0]; // There should only be one list of source materials
  265. if (srcMaterials.atlasRects.Find(x => x.material == submeshMaterial.material) == null)
  266. {
  267. if (mom.LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(" Adding Source Material: " + submeshMaterial.material);
  268. srcMaterials.atlasRects.Add(submeshMaterial);
  269. }
  270. }
  271. }
  272. }
  273. int resMatCount = 0;
  274. foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo resultMat in shader2ResultMat_map.Keys)
  275. {
  276. // at this point there there should be only one slice with all the source materials
  277. resMatCount++;
  278. // For each result material, all source materials are in the first slice.
  279. // We will now split these using a texture packer. Each "atlas" generated by the packer will be a slice.
  280. {
  281. // All source materials should be in the first slice at this point.
  282. List<Slice> slices = shader2ResultMat_map[resultMat];
  283. List<Slice> newSlices = new List<Slice>();
  284. Slice firstSlice = slices[0];
  285. List<Material> allMatsThatUserShader = new List<Material>();
  286. List<GameObject> objsThatUseFirstSlice = new List<GameObject>();
  287. for (int i = 0; i < firstSlice.atlasRects.Count; i++)
  288. {
  289. allMatsThatUserShader.Add(firstSlice.atlasRects[i].material);
  290. if (!objsThatUseFirstSlice.Contains(firstSlice.atlasRects[i].objectsThatUse[0]))
  291. {
  292. objsThatUseFirstSlice.Add(firstSlice.atlasRects[i].objectsThatUse[0]);
  293. }
  294. }
  295. MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
  296. combiner.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
  297. combiner.saveAtlasesAsAssets = false;
  298. combiner.fixOutOfBoundsUVs = true;
  299. combiner.doMergeDistinctMaterialTexturesThatWouldExceedAtlasSize = true;
  300. List<AtlasPackingResult> packingResults = new List<AtlasPackingResult>();
  301. Material tempMat = new Material(resultMat.shader);
  302. if (mom.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("======== 2nd pass. Use atlas packer to split the first slice into multiple if it exceeds atlas size. ");
  303. combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, null, packingResults,
  304. onlyPackRects:true, splitAtlasWhenPackingIfTooBig:true);
  305. if (mom.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("======== Completed packing with texture packer. numPackingResults: " + packingResults.Count);
  306. newSlices.Clear();
  307. // The texture packing just split the atlas into multiple atlases. Each atlas will become a "slice".
  308. for (int newSliceIdx = 0; newSliceIdx < packingResults.Count; newSliceIdx++)
  309. {
  310. List<MB_MaterialAndUVRect> sourceMats = new List<MB_MaterialAndUVRect>();
  311. List<MB_MaterialAndUVRect> packedMatRects = (List<MB_MaterialAndUVRect>) packingResults[newSliceIdx].data;
  312. HashSet<Rect> distinctAtlasRects = new HashSet<Rect>();
  313. for (int packedMatRectIdx = 0; packedMatRectIdx < packedMatRects.Count; packedMatRectIdx++)
  314. {
  315. MB_MaterialAndUVRect muvr = packedMatRects[packedMatRectIdx];
  316. distinctAtlasRects.Add(muvr.atlasRect);
  317. {
  318. Rect encapsulatingRect = muvr.GetEncapsulatingRect();
  319. Vector2 sizeInAtlas_px = new Vector2(
  320. packingResults[newSliceIdx].atlasX * encapsulatingRect.width,
  321. packingResults[newSliceIdx].atlasY * encapsulatingRect.height);
  322. }
  323. sourceMats.Add(muvr);
  324. }
  325. Slice slice = new Slice()
  326. {
  327. atlasRects = sourceMats,
  328. packingResult = packingResults[newSliceIdx],
  329. numAtlasRects = distinctAtlasRects.Count,
  330. };
  331. newSlices.Add(slice);
  332. }
  333. // Replace first slice with split version.
  334. if (mom.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("First slice exceeded atlas size splitting it into " + newSlices.Count + " slices");
  335. slices.RemoveAt(0);
  336. for (int i = 0; i < newSlices.Count; i++)
  337. {
  338. slices.Insert(i, newSlices[i]);
  339. }
  340. }
  341. }
  342. // build the texture array result materials
  343. if (shader2ResultMat_map.Count == 0) Debug.LogError("Found no materials in list of objects to combine");
  344. mom.resultMaterialsTexArray = new MB_MultiMaterialTexArray[shader2ResultMat_map.Count];
  345. int k = 0;
  346. foreach (MB3_TextureBakerEditorInternal.MultiMatSubmeshInfo resMatKey in shader2ResultMat_map.Keys)
  347. {
  348. List<Slice> srcSlices = shader2ResultMat_map[resMatKey];
  349. MB_MultiMaterialTexArray mm = mom.resultMaterialsTexArray[k] = new MB_MultiMaterialTexArray();
  350. for (int sliceIdx = 0; sliceIdx < srcSlices.Count; sliceIdx++)
  351. {
  352. Slice slice = srcSlices[sliceIdx];
  353. MB_TexArraySlice resSlice = new MB_TexArraySlice();
  354. List<Material> usedMats = new List<Material>();
  355. for (int srcMatIdx = 0; srcMatIdx < slice.atlasRects.Count; srcMatIdx++)
  356. {
  357. MB_MaterialAndUVRect matAndUVRect = slice.atlasRects[srcMatIdx];
  358. List<GameObject> objsThatUse = matAndUVRect.objectsThatUse;
  359. for (int objsThatUseIdx = 0; objsThatUseIdx < objsThatUse.Count; objsThatUseIdx++)
  360. {
  361. GameObject obj = objsThatUse[objsThatUseIdx];
  362. if (!resSlice.ContainsMaterialAndMesh(slice.atlasRects[srcMatIdx].material, MB_Utility.GetMesh(obj)))
  363. {
  364. resSlice.sourceMaterials.Add(
  365. new MB_TexArraySliceRendererMatPair()
  366. {
  367. renderer = obj,
  368. sourceMaterial = slice.atlasRects[srcMatIdx].material
  369. }
  370. );
  371. }
  372. }
  373. }
  374. {
  375. // Should we use considerUVs
  376. bool doConsiderUVs = false;
  377. // If there is more than one atlas rectangle in a slice then use considerUVs
  378. if (slice.numAtlasRects > 1)
  379. {
  380. doConsiderUVs = true;
  381. }
  382. else
  383. {
  384. // There is only one source material, could be:
  385. // - lots of tiling (don't want consider UVs)
  386. // - We are extracting a small part of a large atlas (want considerUVs)
  387. if (slice.packingResult.atlasX >= mom.maxAtlasSize ||
  388. slice.packingResult.atlasY >= mom.maxAtlasSize)
  389. {
  390. doConsiderUVs = false; // lots of tiling
  391. }
  392. else
  393. {
  394. doConsiderUVs = true; // extracting a small part of an atlas
  395. }
  396. }
  397. resSlice.considerMeshUVs = doConsiderUVs;
  398. }
  399. mm.slices.Add(resSlice);
  400. }
  401. // Enforce integrity. If a material appears in more than one slice then all those slices must be considerUVs=true
  402. {
  403. // collect all distinct materials
  404. HashSet<Material> distinctMats = new HashSet<Material>();
  405. Dictionary<Material, int> mat2sliceCount = new Dictionary<Material, int>();
  406. for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
  407. {
  408. for (int sliceMatIdx = 0; sliceMatIdx < mm.slices[sliceIdx].sourceMaterials.Count; sliceMatIdx++)
  409. {
  410. Material mat = mm.slices[sliceIdx].sourceMaterials[sliceMatIdx].sourceMaterial;
  411. distinctMats.Add(mat);
  412. mat2sliceCount[mat] = 0;
  413. }
  414. }
  415. // Count the number of slices that use each material.
  416. foreach (Material mat in distinctMats)
  417. {
  418. for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
  419. {
  420. if (mm.slices[sliceIdx].ContainsMaterial(mat))
  421. {
  422. mat2sliceCount[mat] = mat2sliceCount[mat] + 1;
  423. }
  424. }
  425. }
  426. // Check that considerUVs is true for any materials that appear more than once
  427. foreach (Material mat in distinctMats)
  428. {
  429. if (mat2sliceCount[mat] > 1)
  430. {
  431. for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
  432. {
  433. if (mm.slices[sliceIdx].ContainsMaterial(mat))
  434. {
  435. if (mom.LOG_LEVEL >= MB2_LogLevel.debug &&
  436. mm.slices[sliceIdx].considerMeshUVs) Debug.Log("There was a material " + mat + " that was used by more than one slice and considerUVs was false. sliceIdx:" + sliceIdx);
  437. mm.slices[sliceIdx].considerMeshUVs = true;
  438. }
  439. }
  440. }
  441. }
  442. }
  443. // Cleanup. remove "Renderer"s from source materials that do not use considerUVs and delete extra
  444. {
  445. // put any slices with consider UVs first
  446. List<MB_TexArraySlice> newSlices = new List<MB_TexArraySlice>();
  447. for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
  448. {
  449. if (mm.slices[sliceIdx].considerMeshUVs == true)
  450. {
  451. newSlices.Add(mm.slices[sliceIdx]);
  452. }
  453. }
  454. // for any slices without considerUVs, remove "renderer" and truncate
  455. for (int sliceIdx = 0; sliceIdx < mm.slices.Count; sliceIdx++)
  456. {
  457. MB_TexArraySlice slice = mm.slices[sliceIdx];
  458. if (slice.considerMeshUVs == false)
  459. {
  460. newSlices.Add(slice);
  461. HashSet<Material> distinctMats = slice.GetDistinctMaterials();
  462. slice.sourceMaterials.Clear();
  463. foreach (Material mat in distinctMats)
  464. {
  465. slice.sourceMaterials.Add(new MB_TexArraySliceRendererMatPair() {sourceMaterial = mat });
  466. }
  467. }
  468. }
  469. mm.slices = newSlices;
  470. }
  471. string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults);
  472. string baseName = Path.GetFileNameWithoutExtension(pth);
  473. string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
  474. string matName = folderPath + baseName + "-mat" + k + ".mat";
  475. Material existingAsset = AssetDatabase.LoadAssetAtPath<Material>(matName);
  476. if (!existingAsset)
  477. {
  478. Material newMat = new Material(Shader.Find("Standard"));
  479. // Don't try to configure the material we need the user to pick a shader that has TextureArrays
  480. AssetDatabase.CreateAsset(newMat, matName);
  481. }
  482. mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
  483. k++;
  484. }
  485. MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
  486. textureBaker.Update();
  487. }
  488. }
  489. }