MB3_TextureBaker.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. //----------------------------------------------
  2. // MeshBaker
  3. // Copyright © 2011-2012 Ian Deane
  4. //----------------------------------------------
  5. using UnityEngine;
  6. using System.Collections;
  7. using System.Collections.Specialized;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Text;
  11. using System.IO;
  12. using DigitalOpus.MB.Core;
  13. /// <summary>
  14. /// Component that handles baking materials into a combined material.
  15. ///
  16. /// The result of the material baking process is a MB2_TextureBakeResults object, which
  17. /// becomes the input for the mesh baking.
  18. ///
  19. /// This class uses the MB_TextureCombiner to do the combining.
  20. ///
  21. /// This class is a Component (MonoBehavior) so it is serialized and found using GetComponent. If
  22. /// you want to access the texture baking functionality without creating a Component then use MB_TextureCombiner
  23. /// directly.
  24. /// </summary>
  25. public class MB3_TextureBaker : MB3_MeshBakerRoot
  26. {
  27. public MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info;
  28. [SerializeField]
  29. protected MB2_TextureBakeResults _textureBakeResults;
  30. public override MB2_TextureBakeResults textureBakeResults
  31. {
  32. get { return _textureBakeResults; }
  33. set { _textureBakeResults = value; }
  34. }
  35. [SerializeField]
  36. protected int _atlasPadding = 1;
  37. public virtual int atlasPadding
  38. {
  39. get { return _atlasPadding; }
  40. set { _atlasPadding = value; }
  41. }
  42. [SerializeField]
  43. protected int _maxAtlasSize = 4096;
  44. public virtual int maxAtlasSize
  45. {
  46. get { return _maxAtlasSize; }
  47. set { _maxAtlasSize = value; }
  48. }
  49. [SerializeField]
  50. protected bool _useMaxAtlasWidthOverride = false;
  51. public virtual bool useMaxAtlasWidthOverride
  52. {
  53. get { return _useMaxAtlasWidthOverride; }
  54. set { _useMaxAtlasWidthOverride = value; }
  55. }
  56. [SerializeField]
  57. protected int _maxAtlasWidthOverride = 4096;
  58. public virtual int maxAtlasWidthOverride
  59. {
  60. get { return _maxAtlasWidthOverride; }
  61. set { _maxAtlasWidthOverride = value; }
  62. }
  63. [SerializeField]
  64. protected bool _useMaxAtlasHeightOverride = false;
  65. public virtual bool useMaxAtlasHeightOverride
  66. {
  67. get { return _useMaxAtlasHeightOverride; }
  68. set { _useMaxAtlasHeightOverride = value; }
  69. }
  70. [SerializeField]
  71. protected int _maxAtlasHeightOverride = 4096;
  72. public virtual int maxAtlasHeightOverride
  73. {
  74. get { return _maxAtlasHeightOverride; }
  75. set { _maxAtlasHeightOverride = value; }
  76. }
  77. [SerializeField]
  78. protected bool _resizePowerOfTwoTextures = false;
  79. public virtual bool resizePowerOfTwoTextures
  80. {
  81. get { return _resizePowerOfTwoTextures; }
  82. set { _resizePowerOfTwoTextures = value; }
  83. }
  84. [SerializeField]
  85. protected bool _fixOutOfBoundsUVs = false; //is considerMeshUVs but can't change because it would break all existing bakers
  86. public virtual bool fixOutOfBoundsUVs
  87. {
  88. get { return _fixOutOfBoundsUVs; }
  89. set { _fixOutOfBoundsUVs = value; }
  90. }
  91. [SerializeField]
  92. protected int _maxTilingBakeSize = 1024;
  93. public virtual int maxTilingBakeSize
  94. {
  95. get { return _maxTilingBakeSize; }
  96. set { _maxTilingBakeSize = value; }
  97. }
  98. [SerializeField]
  99. protected MB2_PackingAlgorithmEnum _packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
  100. public virtual MB2_PackingAlgorithmEnum packingAlgorithm
  101. {
  102. get { return _packingAlgorithm; }
  103. set { _packingAlgorithm = value; }
  104. }
  105. [SerializeField]
  106. protected bool _meshBakerTexturePackerForcePowerOfTwo = true;
  107. public bool meshBakerTexturePackerForcePowerOfTwo
  108. {
  109. get { return _meshBakerTexturePackerForcePowerOfTwo; }
  110. set { _meshBakerTexturePackerForcePowerOfTwo = value; }
  111. }
  112. [SerializeField]
  113. protected List<ShaderTextureProperty> _customShaderProperties = new List<ShaderTextureProperty>();
  114. public virtual List<ShaderTextureProperty> customShaderProperties
  115. {
  116. get { return _customShaderProperties; }
  117. set { _customShaderProperties = value; }
  118. }
  119. //this is depricated
  120. [SerializeField]
  121. protected List<string> _customShaderPropNames_Depricated = new List<string>();
  122. public virtual List<string> customShaderPropNames
  123. {
  124. get { return _customShaderPropNames_Depricated; }
  125. set { _customShaderPropNames_Depricated = value; }
  126. }
  127. [SerializeField]
  128. protected MB2_TextureBakeResults.ResultType _resultType;
  129. public virtual MB2_TextureBakeResults.ResultType resultType
  130. {
  131. get { return _resultType; }
  132. set { _resultType = value; }
  133. }
  134. [SerializeField]
  135. protected bool _doMultiMaterial;
  136. public virtual bool doMultiMaterial
  137. {
  138. get { return _doMultiMaterial; }
  139. set { _doMultiMaterial = value; }
  140. }
  141. [SerializeField]
  142. protected bool _doMultiMaterialSplitAtlasesIfTooBig = true;
  143. public virtual bool doMultiMaterialSplitAtlasesIfTooBig
  144. {
  145. get { return _doMultiMaterialSplitAtlasesIfTooBig; }
  146. set { _doMultiMaterialSplitAtlasesIfTooBig = value; }
  147. }
  148. [SerializeField]
  149. protected bool _doMultiMaterialSplitAtlasesIfOBUVs = true;
  150. public virtual bool doMultiMaterialSplitAtlasesIfOBUVs
  151. {
  152. get { return _doMultiMaterialSplitAtlasesIfOBUVs; }
  153. set { _doMultiMaterialSplitAtlasesIfOBUVs = value; }
  154. }
  155. [SerializeField]
  156. protected Material _resultMaterial;
  157. public virtual Material resultMaterial
  158. {
  159. get { return _resultMaterial; }
  160. set { _resultMaterial = value; }
  161. }
  162. [SerializeField]
  163. protected bool _considerNonTextureProperties = false;
  164. public bool considerNonTextureProperties
  165. {
  166. get { return _considerNonTextureProperties; }
  167. set { _considerNonTextureProperties = value; }
  168. }
  169. [SerializeField]
  170. protected bool _doSuggestTreatment = true;
  171. public bool doSuggestTreatment
  172. {
  173. get { return _doSuggestTreatment; }
  174. set { _doSuggestTreatment = value; }
  175. }
  176. private MB3_TextureCombiner.CreateAtlasesCoroutineResult _coroutineResult;
  177. public MB3_TextureCombiner.CreateAtlasesCoroutineResult CoroutineResult
  178. {
  179. get
  180. {
  181. return _coroutineResult;
  182. }
  183. }
  184. public MB_MultiMaterial[] resultMaterials = new MB_MultiMaterial[0];
  185. public MB_MultiMaterialTexArray[] resultMaterialsTexArray = new MB_MultiMaterialTexArray[0];
  186. public MB_TextureArrayFormatSet[] textureArrayOutputFormats;
  187. public List<GameObject> objsToMesh; //todo make this Renderer
  188. public override List<GameObject> GetObjectsToCombine()
  189. {
  190. if (objsToMesh == null) objsToMesh = new List<GameObject>();
  191. return objsToMesh;
  192. }
  193. public MB_AtlasesAndRects[] CreateAtlases()
  194. {
  195. return CreateAtlases(null, false, null);
  196. }
  197. public delegate void OnCombinedTexturesCoroutineSuccess();
  198. public delegate void OnCombinedTexturesCoroutineFail();
  199. public OnCombinedTexturesCoroutineSuccess onBuiltAtlasesSuccess;
  200. public OnCombinedTexturesCoroutineFail onBuiltAtlasesFail;
  201. public MB_AtlasesAndRects[] OnCombinedTexturesCoroutineAtlasesAndRects;
  202. public IEnumerator CreateAtlasesCoroutine(ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
  203. {
  204. yield return _CreateAtlasesCoroutine(progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame);
  205. if (coroutineResult.success && onBuiltAtlasesSuccess != null)
  206. {
  207. onBuiltAtlasesSuccess();
  208. }
  209. if (!coroutineResult.success && onBuiltAtlasesFail != null)
  210. {
  211. onBuiltAtlasesFail();
  212. }
  213. }
  214. private IEnumerator _CreateAtlasesCoroutineAtlases(MB3_TextureCombiner combiner, ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
  215. {
  216. int numResults = 1;
  217. if (_doMultiMaterial)
  218. {
  219. numResults = resultMaterials.Length;
  220. }
  221. OnCombinedTexturesCoroutineAtlasesAndRects = new MB_AtlasesAndRects[numResults];
  222. for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
  223. {
  224. OnCombinedTexturesCoroutineAtlasesAndRects[i] = new MB_AtlasesAndRects();
  225. }
  226. //Do the material combining.
  227. for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
  228. {
  229. Material resMatToPass = null;
  230. List<Material> sourceMats = null;
  231. if (_doMultiMaterial)
  232. {
  233. sourceMats = resultMaterials[i].sourceMaterials;
  234. resMatToPass = resultMaterials[i].combinedMaterial;
  235. combiner.fixOutOfBoundsUVs = resultMaterials[i].considerMeshUVs;
  236. }
  237. else
  238. {
  239. resMatToPass = _resultMaterial;
  240. }
  241. MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult();
  242. yield return combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo, OnCombinedTexturesCoroutineAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods, coroutineResult2, maxTimePerFrame,
  243. onlyPackRects: false, splitAtlasWhenPackingIfTooBig: false);
  244. coroutineResult.success = coroutineResult2.success;
  245. if (!coroutineResult.success)
  246. {
  247. coroutineResult.isFinished = true;
  248. yield break;
  249. }
  250. }
  251. unpackMat2RectMap(OnCombinedTexturesCoroutineAtlasesAndRects);
  252. //Save the results
  253. textureBakeResults.resultType = MB2_TextureBakeResults.ResultType.atlas;
  254. textureBakeResults.resultMaterialsTexArray = new MB_MultiMaterialTexArray[0];
  255. textureBakeResults.doMultiMaterial = _doMultiMaterial;
  256. if (_doMultiMaterial)
  257. {
  258. textureBakeResults.resultMaterials = resultMaterials;
  259. }
  260. else
  261. {
  262. MB_MultiMaterial[] resMats = new MB_MultiMaterial[1];
  263. resMats[0] = new MB_MultiMaterial();
  264. resMats[0].combinedMaterial = _resultMaterial;
  265. resMats[0].considerMeshUVs = _fixOutOfBoundsUVs;
  266. resMats[0].sourceMaterials = new List<Material>();
  267. for (int i = 0; i < textureBakeResults.materialsAndUVRects.Length; i++)
  268. {
  269. resMats[0].sourceMaterials.Add(textureBakeResults.materialsAndUVRects[i].material);
  270. }
  271. textureBakeResults.resultMaterials = resMats;
  272. }
  273. if (LOG_LEVEL >= MB2_LogLevel.info) Debug.Log("Created Atlases");
  274. }
  275. internal IEnumerator _CreateAtlasesCoroutineTextureArray(MB3_TextureCombiner combiner, ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
  276. {
  277. MB_TextureArrayResultMaterial[] bakedMatsAndSlices = null;
  278. // Validate the formats
  279. if (textureArrayOutputFormats == null || textureArrayOutputFormats.Length == 0)
  280. {
  281. Debug.LogError("No Texture Array Output Formats. There must be at least one entry.");
  282. coroutineResult.isFinished = true;
  283. yield break;
  284. }
  285. for (int i = 0; i < textureArrayOutputFormats.Length; i++)
  286. {
  287. if (!textureArrayOutputFormats[i].ValidateTextureImporterFormatsExistsForTextureFormats(editorMethods, i))
  288. {
  289. Debug.LogError("Could not map the selected texture format to a Texture Importer Format. Safest options are ARGB32, or RGB24.");
  290. coroutineResult.isFinished = true;
  291. yield break;
  292. }
  293. }
  294. for (int resMatIdx = 0; resMatIdx < resultMaterialsTexArray.Length; resMatIdx++)
  295. {
  296. MB_MultiMaterialTexArray textureArraySliceConfig = resultMaterialsTexArray[resMatIdx];
  297. if (textureArraySliceConfig.combinedMaterial == null)
  298. {
  299. Debug.LogError("Material is null for Texture Array Slice Configuration: " + resMatIdx + ".");
  300. coroutineResult.isFinished = true;
  301. yield break;
  302. }
  303. List<MB_TexArraySlice> slices = textureArraySliceConfig.slices;
  304. for (int sliceIdx = 0; sliceIdx < slices.Count; sliceIdx++)
  305. {
  306. for (int srcMatIdx = 0; srcMatIdx < slices[sliceIdx].sourceMaterials.Count; srcMatIdx++)
  307. {
  308. MB_TexArraySliceRendererMatPair sourceMat = slices[sliceIdx].sourceMaterials[srcMatIdx];
  309. if (sourceMat.sourceMaterial == null)
  310. {
  311. Debug.LogError("Source material is null for Texture Array Slice Configuration: " + resMatIdx + " slice: " + sliceIdx);
  312. coroutineResult.isFinished = true;
  313. yield break;
  314. }
  315. if (slices[sliceIdx].considerMeshUVs)
  316. {
  317. if (sourceMat.renderer == null)
  318. {
  319. Debug.LogError("Renderer is null for Texture Array Slice Configuration: " + resMatIdx + " slice: " + sliceIdx + ". If considerUVs is enabled then a renderer must be supplied for each source material. The same source material can be used multiple times.");
  320. coroutineResult.isFinished = true;
  321. yield break;
  322. }
  323. }
  324. else
  325. {
  326. // TODO check for duplicate source mats.
  327. }
  328. }
  329. }
  330. }
  331. for (int resMatIdx = 0; resMatIdx < resultMaterialsTexArray.Length; resMatIdx++)
  332. {
  333. MB_MultiMaterialTexArray textureArraySliceConfig = resultMaterialsTexArray[resMatIdx];
  334. }
  335. // initialize structure to store results. For texture arrays the structure is two layers deep.
  336. // First layer is resultMaterial / submesh (each result material can use a different shader)
  337. // Second layer is a set of TextureArrays for the TextureProperties on that result material.
  338. int numResultMats = resultMaterialsTexArray.Length;
  339. bakedMatsAndSlices = new MB_TextureArrayResultMaterial[numResultMats];
  340. for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++)
  341. {
  342. bakedMatsAndSlices[resMatIdx] = new MB_TextureArrayResultMaterial();
  343. int numSlices = resultMaterialsTexArray[resMatIdx].slices.Count;
  344. MB_AtlasesAndRects[] slices = bakedMatsAndSlices[resMatIdx].slices = new MB_AtlasesAndRects[numSlices];
  345. for (int j = 0; j < numSlices; j++) slices[j] = new MB_AtlasesAndRects();
  346. }
  347. // Some of the slices will be atlases (more than one atlas per slice).
  348. // Do the material combining for these. First loop over the result materials (1 per submeshes).
  349. for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++)
  350. {
  351. yield return MB_TextureArrays._CreateAtlasesCoroutineSingleResultMaterial(resMatIdx, bakedMatsAndSlices[resMatIdx], resultMaterialsTexArray[resMatIdx],
  352. objsToMesh,
  353. combiner,
  354. textureArrayOutputFormats,
  355. resultMaterialsTexArray,
  356. customShaderProperties,
  357. progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame);
  358. if (!coroutineResult.success) yield break;
  359. }
  360. if (coroutineResult.success)
  361. {
  362. // Save the results into the TextureBakeResults.
  363. unpackMat2RectMap(bakedMatsAndSlices);
  364. textureBakeResults.resultType = MB2_TextureBakeResults.ResultType.textureArray;
  365. textureBakeResults.resultMaterials = new MB_MultiMaterial[0];
  366. textureBakeResults.resultMaterialsTexArray = resultMaterialsTexArray;
  367. if (LOG_LEVEL >= MB2_LogLevel.info) Debug.Log("Created Texture2DArrays");
  368. }
  369. else
  370. {
  371. if (LOG_LEVEL >= MB2_LogLevel.info) Debug.Log("Failed to create Texture2DArrays");
  372. }
  373. }
  374. private IEnumerator _CreateAtlasesCoroutine(ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f)
  375. {
  376. MBVersionConcrete mbv = new MBVersionConcrete();
  377. if (!MB3_TextureCombiner._RunCorutineWithoutPauseIsRunning && (mbv.GetMajorVersion() < 5 || (mbv.GetMajorVersion() == 5 && mbv.GetMinorVersion() < 3)))
  378. {
  379. Debug.LogError("Running the texture combiner as a coroutine only works in Unity 5.3 and higher");
  380. coroutineResult.success = false;
  381. yield break;
  382. }
  383. this.OnCombinedTexturesCoroutineAtlasesAndRects = null;
  384. if (maxTimePerFrame <= 0f)
  385. {
  386. Debug.LogError("maxTimePerFrame must be a value greater than zero");
  387. coroutineResult.isFinished = true;
  388. yield break;
  389. }
  390. MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;
  391. if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, null, vl))
  392. {
  393. coroutineResult.isFinished = true;
  394. yield break;
  395. }
  396. if (_doMultiMaterial && !_ValidateResultMaterials())
  397. {
  398. coroutineResult.isFinished = true;
  399. yield break;
  400. }
  401. else if (resultType == MB2_TextureBakeResults.ResultType.textureArray)
  402. {
  403. //TODO validate texture arrays.
  404. }
  405. else if (!_doMultiMaterial)
  406. {
  407. if (_resultMaterial == null)
  408. {
  409. Debug.LogError("Combined Material is null please create and assign a result material.");
  410. coroutineResult.isFinished = true;
  411. yield break;
  412. }
  413. Shader targShader = _resultMaterial.shader;
  414. for (int i = 0; i < objsToMesh.Count; i++)
  415. {
  416. Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
  417. for (int j = 0; j < ms.Length; j++)
  418. {
  419. Material m = ms[j];
  420. if (m != null && m.shader != targShader)
  421. {
  422. Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not small solid color textures will be generated.");
  423. }
  424. }
  425. }
  426. }
  427. MB3_TextureCombiner combiner = CreateAndConfigureTextureCombiner();
  428. combiner.saveAtlasesAsAssets = saveAtlasesAsAssets;
  429. OnCombinedTexturesCoroutineAtlasesAndRects = null;
  430. if (resultType == MB2_TextureBakeResults.ResultType.textureArray)
  431. {
  432. yield return _CreateAtlasesCoroutineTextureArray(combiner, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame);
  433. if (!coroutineResult.success) yield break;
  434. }
  435. else
  436. {
  437. yield return _CreateAtlasesCoroutineAtlases(combiner, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame);
  438. if (!coroutineResult.success) yield break;
  439. }
  440. //set the texture bake resultAtlasesAndRects on the Mesh Baker component if it exists
  441. MB3_MeshBakerCommon[] mb = GetComponentsInChildren<MB3_MeshBakerCommon>();
  442. for (int i = 0; i < mb.Length; i++)
  443. {
  444. mb[i].textureBakeResults = textureBakeResults;
  445. }
  446. coroutineResult.isFinished = true;
  447. }
  448. /// <summary>
  449. /// Creates the atlases.
  450. /// </summary>
  451. /// <returns>
  452. /// The atlases.
  453. /// </returns>
  454. /// <param name='progressInfo'>
  455. /// Progress info is a delegate function that displays a progress dialog. Can be null
  456. /// </param>
  457. /// <param name='saveAtlasesAsAssets'>
  458. /// if true atlases are saved as assets in the project folder. Othersise they are instances in memory
  459. /// </param>
  460. /// <param name='editorMethods'>
  461. /// Texture format tracker. Contains editor functionality such as save assets. Can be null.
  462. /// </param>
  463. public MB_AtlasesAndRects[] CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null)
  464. {
  465. MB_AtlasesAndRects[] mAndAs = null;
  466. try
  467. {
  468. _coroutineResult = new MB3_TextureCombiner.CreateAtlasesCoroutineResult();
  469. MB3_TextureCombiner.RunCorutineWithoutPause(CreateAtlasesCoroutine(progressInfo, _coroutineResult, saveAtlasesAsAssets, editorMethods, 1000f), 0);
  470. if (_coroutineResult.success && textureBakeResults != null)
  471. {
  472. mAndAs = this.OnCombinedTexturesCoroutineAtlasesAndRects;
  473. }
  474. }
  475. catch (Exception e)
  476. {
  477. Debug.LogError(e);
  478. }
  479. finally
  480. {
  481. if (saveAtlasesAsAssets)
  482. { //Atlases were saved to project so we don't need these ones
  483. if (mAndAs != null)
  484. {
  485. for (int j = 0; j < mAndAs.Length; j++)
  486. {
  487. MB_AtlasesAndRects mAndA = mAndAs[j];
  488. if (mAndA != null && mAndA.atlases != null)
  489. {
  490. for (int i = 0; i < mAndA.atlases.Length; i++)
  491. {
  492. if (mAndA.atlases[i] != null)
  493. {
  494. if (editorMethods != null) editorMethods.Destroy(mAndA.atlases[i]);
  495. else MB_Utility.Destroy(mAndA.atlases[i]);
  496. }
  497. }
  498. }
  499. }
  500. }
  501. }
  502. }
  503. return mAndAs;
  504. }
  505. void unpackMat2RectMap(MB_AtlasesAndRects[] rawResults)
  506. {
  507. List<MB_MaterialAndUVRect> mss = new List<MB_MaterialAndUVRect>();
  508. for (int i = 0; i < rawResults.Length; i++)
  509. {
  510. List<MB_MaterialAndUVRect> map = rawResults[i].mat2rect_map;
  511. if (map != null)
  512. {
  513. for (int j = 0; j < map.Count; j++)
  514. {
  515. map[j].textureArraySliceIdx = -1;
  516. mss.Add(map[j]);
  517. }
  518. }
  519. }
  520. textureBakeResults.version = MB2_TextureBakeResults.VERSION;
  521. textureBakeResults.materialsAndUVRects = mss.ToArray();
  522. }
  523. internal void unpackMat2RectMap(MB_TextureArrayResultMaterial[] rawResults)
  524. {
  525. List<MB_MaterialAndUVRect> mss = new List<MB_MaterialAndUVRect>();
  526. for (int resMatIdx = 0; resMatIdx < rawResults.Length; resMatIdx++)
  527. {
  528. MB_AtlasesAndRects[] slices = rawResults[resMatIdx].slices;
  529. for (int sliceIdx = 0; sliceIdx < slices.Length; sliceIdx++)
  530. {
  531. List<MB_MaterialAndUVRect> map = slices[sliceIdx].mat2rect_map;
  532. if (map != null)
  533. {
  534. for (int rectIdx = 0; rectIdx < map.Count; rectIdx++)
  535. {
  536. map[rectIdx].textureArraySliceIdx = sliceIdx;
  537. mss.Add(map[rectIdx]);
  538. }
  539. }
  540. }
  541. }
  542. textureBakeResults.version = MB2_TextureBakeResults.VERSION;
  543. textureBakeResults.materialsAndUVRects = mss.ToArray();
  544. }
  545. public MB3_TextureCombiner CreateAndConfigureTextureCombiner()
  546. {
  547. MB3_TextureCombiner combiner = new MB3_TextureCombiner();
  548. combiner.LOG_LEVEL = LOG_LEVEL;
  549. combiner.atlasPadding = _atlasPadding;
  550. combiner.maxAtlasSize = _maxAtlasSize;
  551. combiner.maxAtlasHeightOverride = _maxAtlasHeightOverride;
  552. combiner.maxAtlasWidthOverride = _maxAtlasWidthOverride;
  553. combiner.useMaxAtlasHeightOverride = _useMaxAtlasHeightOverride;
  554. combiner.useMaxAtlasWidthOverride = _useMaxAtlasWidthOverride;
  555. combiner.customShaderPropNames = _customShaderProperties;
  556. combiner.fixOutOfBoundsUVs = _fixOutOfBoundsUVs;
  557. combiner.maxTilingBakeSize = _maxTilingBakeSize;
  558. combiner.packingAlgorithm = _packingAlgorithm;
  559. combiner.resultType = _resultType;
  560. combiner.meshBakerTexturePackerForcePowerOfTwo = _meshBakerTexturePackerForcePowerOfTwo;
  561. combiner.resizePowerOfTwoTextures = _resizePowerOfTwoTextures;
  562. combiner.considerNonTextureProperties = _considerNonTextureProperties;
  563. return combiner;
  564. }
  565. public static void ConfigureNewMaterialToMatchOld(Material newMat, Material original)
  566. {
  567. if (original == null)
  568. {
  569. Debug.LogWarning("Original material is null, could not copy properties to " + newMat + ". Setting shader to " + newMat.shader);
  570. return;
  571. }
  572. newMat.shader = original.shader;
  573. newMat.CopyPropertiesFromMaterial(original);
  574. ShaderTextureProperty[] texPropertyNames = MB3_TextureCombinerPipeline.shaderTexPropertyNames;
  575. for (int j = 0; j < texPropertyNames.Length; j++)
  576. {
  577. Vector2 scale = Vector2.one;
  578. Vector2 offset = Vector2.zero;
  579. if (newMat.HasProperty(texPropertyNames[j].name))
  580. {
  581. newMat.SetTextureOffset(texPropertyNames[j].name, offset);
  582. newMat.SetTextureScale(texPropertyNames[j].name, scale);
  583. }
  584. }
  585. }
  586. string PrintSet(HashSet<Material> s)
  587. {
  588. StringBuilder sb = new StringBuilder();
  589. foreach (Material m in s)
  590. {
  591. sb.Append(m + ",");
  592. }
  593. return sb.ToString();
  594. }
  595. bool _ValidateResultMaterials()
  596. {
  597. HashSet<Material> allMatsOnObjs = new HashSet<Material>();
  598. for (int i = 0; i < objsToMesh.Count; i++)
  599. {
  600. if (objsToMesh[i] != null)
  601. {
  602. Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
  603. for (int j = 0; j < ms.Length; j++)
  604. {
  605. if (ms[j] != null) allMatsOnObjs.Add(ms[j]);
  606. }
  607. }
  608. }
  609. HashSet<Material> allMatsInMapping = new HashSet<Material>();
  610. for (int i = 0; i < resultMaterials.Length; i++)
  611. {
  612. for (int j = i + 1; j < resultMaterials.Length; j++)
  613. {
  614. if (resultMaterials[i].combinedMaterial == resultMaterials[j].combinedMaterial)
  615. {
  616. Debug.LogError(String.Format("Source To Combined Mapping: Submesh {0} and Submesh {1} use the same combined material. These should be different", i, j));
  617. return false;
  618. }
  619. }
  620. MB_MultiMaterial mm = resultMaterials[i];
  621. if (mm.combinedMaterial == null)
  622. {
  623. Debug.LogError("Combined Material is null please create and assign a result material.");
  624. return false;
  625. }
  626. Shader targShader = mm.combinedMaterial.shader;
  627. for (int j = 0; j < mm.sourceMaterials.Count; j++)
  628. {
  629. if (mm.sourceMaterials[j] == null)
  630. {
  631. Debug.LogError("There are null entries in the list of Source Materials");
  632. return false;
  633. }
  634. if (targShader != mm.sourceMaterials[j].shader)
  635. {
  636. Debug.LogWarning("Source material " + mm.sourceMaterials[j] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated.");
  637. }
  638. if (allMatsInMapping.Contains(mm.sourceMaterials[j]))
  639. {
  640. Debug.LogError("A Material " + mm.sourceMaterials[j] + " appears more than once in the list of source materials in the source material to combined mapping. Each source material must be unique.");
  641. return false;
  642. }
  643. allMatsInMapping.Add(mm.sourceMaterials[j]);
  644. }
  645. }
  646. if (allMatsOnObjs.IsProperSubsetOf(allMatsInMapping))
  647. {
  648. allMatsInMapping.ExceptWith(allMatsOnObjs);
  649. Debug.LogWarning("There are materials in the mapping that are not used on your source objects: " + PrintSet(allMatsInMapping));
  650. }
  651. if (resultMaterials != null && resultMaterials.Length > 0 && allMatsInMapping.IsProperSubsetOf(allMatsOnObjs))
  652. {
  653. allMatsOnObjs.ExceptWith(allMatsInMapping);
  654. Debug.LogError("There are materials on the objects to combine that are not in the mapping: " + PrintSet(allMatsOnObjs));
  655. return false;
  656. }
  657. return true;
  658. }
  659. }