internal IEnumerator _CreateAtlasesCoroutineTextureArray(MB3_TextureCombiner combiner, ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f) { MB_TextureArrayResultMaterial[] bakedMatsAndSlices = null; // Validate the formats if (textureArrayOutputFormats == null || textureArrayOutputFormats.Length == 0) { Debug.LogError("No Texture Array Output Formats. There must be at least one entry."); coroutineResult.isFinished = true; yield break; } for (int i = 0; i < textureArrayOutputFormats.Length; i++) { if (!textureArrayOutputFormats[i].ValidateTextureImporterFormatsExistsForTextureFormats(editorMethods, i)) { Debug.LogError("Could not map the selected texture format to a Texture Importer Format. Safest options are ARGB32, or RGB24."); coroutineResult.isFinished = true; yield break; } } for (int resMatIdx = 0; resMatIdx < resultMaterialsTexArray.Length; resMatIdx++) { MB_MultiMaterialTexArray textureArraySliceConfig = resultMaterialsTexArray[resMatIdx]; if (textureArraySliceConfig.combinedMaterial == null) { Debug.LogError("Material is null for Texture Array Slice Configuration: " + resMatIdx + "."); coroutineResult.isFinished = true; yield break; } List <MB_TexArraySlice> slices = textureArraySliceConfig.slices; for (int sliceIdx = 0; sliceIdx < slices.Count; sliceIdx++) { for (int srcMatIdx = 0; srcMatIdx < slices[sliceIdx].sourceMaterials.Count; srcMatIdx++) { MB_TexArraySliceRendererMatPair sourceMat = slices[sliceIdx].sourceMaterials[srcMatIdx]; if (sourceMat.sourceMaterial == null) { Debug.LogError("Source material is null for Texture Array Slice Configuration: " + resMatIdx + " slice: " + sliceIdx); coroutineResult.isFinished = true; yield break; } if (slices[sliceIdx].considerMeshUVs) { if (sourceMat.renderer == null) { 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."); coroutineResult.isFinished = true; yield break; } } else { // TODO check for duplicate source mats. } } } } // initialize structure to store results. For texture arrays the structure is two layers deep. // First layer is resultMaterial / submesh (each result material can use a different shader) // Second layer is a set of TextureArrays for the TextureProperties on that result material. int numResultMats = resultMaterialsTexArray.Length; bakedMatsAndSlices = new MB_TextureArrayResultMaterial[numResultMats]; for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++) { bakedMatsAndSlices[resMatIdx] = new MB_TextureArrayResultMaterial(); int numSlices = resultMaterialsTexArray[resMatIdx].slices.Count; MB_AtlasesAndRects[] slices = bakedMatsAndSlices[resMatIdx].slices = new MB_AtlasesAndRects[numSlices]; for (int j = 0; j < numSlices; j++) { slices[j] = new MB_AtlasesAndRects(); } } // Some of the slices will be atlases (more than one atlas per slice). // Do the material combining for these. First loop over the result materials (1 per submeshes). for (int resMatIdx = 0; resMatIdx < bakedMatsAndSlices.Length; resMatIdx++) { yield return(MB_TextureArrays._CreateAtlasesCoroutineSingleResultMaterial(resMatIdx, bakedMatsAndSlices[resMatIdx], resultMaterialsTexArray[resMatIdx], objsToMesh, combiner, textureArrayOutputFormats, resultMaterialsTexArray, customShaderProperties, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame)); if (!coroutineResult.success) { yield break; } } if (coroutineResult.success) { // Save the results into the TextureBakeResults. unpackMat2RectMap(bakedMatsAndSlices); if (editorMethods != null) { editorMethods.GetMaterialPrimaryKeysIfAddressables(textureBakeResults); } textureBakeResults.resultType = MB2_TextureBakeResults.ResultType.textureArray; textureBakeResults.resultMaterials = new MB_MultiMaterial[0]; textureBakeResults.resultMaterialsTexArray = resultMaterialsTexArray; if (LOG_LEVEL >= MB2_LogLevel.info) { Debug.Log("Created Texture2DArrays"); } } else { if (LOG_LEVEL >= MB2_LogLevel.info) { Debug.Log("Failed to create Texture2DArrays"); } } }
private IEnumerator _CreateAtlasesCoroutine(ProgressUpdateDelegate progressInfo, CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f) { MBVersionConcrete mbv = new MBVersionConcrete(); if (!MB3_TextureCombiner._RunCorutineWithoutPauseIsRunning && (mbv.GetMajorVersion() < 5 || (mbv.GetMajorVersion() == 5 && mbv.GetMinorVersion() < 3))) { Debug.LogError("Running the texture combiner as a coroutine only works in Unity 5.3 and higher"); coroutineResult.success = false; yield break; } this.OnCombinedTexturesCoroutineAtlasesAndRects = null; if (maxTimePerFrame <= 0f) { Debug.LogError("maxTimePerFrame must be a value greater than zero"); coroutineResult.isFinished = true; yield break; } MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust; if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, null, vl)) { coroutineResult.isFinished = true; yield break; } if (_doMultiMaterial && !_ValidateResultMaterials()) { coroutineResult.isFinished = true; yield break; } else if (resultType == MB2_TextureBakeResults.ResultType.textureArray) { //TODO validate texture arrays. } else if (!_doMultiMaterial) { if (_resultMaterial == null) { Debug.LogError("Combined Material is null please create and assign a result material."); coroutineResult.isFinished = true; yield break; } Shader targShader = _resultMaterial.shader; for (int i = 0; i < objsToMesh.Count; i++) { Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]); for (int j = 0; j < ms.Length; j++) { Material m = ms[j]; if (m != null && m.shader != targShader) { 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."); } } } } MB3_TextureCombiner combiner = CreateAndConfigureTextureCombiner(); combiner.saveAtlasesAsAssets = saveAtlasesAsAssets; OnCombinedTexturesCoroutineAtlasesAndRects = null; if (resultType == MB2_TextureBakeResults.ResultType.textureArray) { yield return(MB_TextureArrays._CreateAtlasesCoroutineTextureArray(this, combiner, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame)); if (!coroutineResult.success) { yield break; } } else { yield return(_CreateAtlasesCoroutineAtlases(combiner, progressInfo, coroutineResult, saveAtlasesAsAssets, editorMethods, maxTimePerFrame)); if (!coroutineResult.success) { yield break; } } //set the texture bake resultAtlasesAndRects on the Mesh Baker component if it exists MB3_MeshBakerCommon[] mb = GetComponentsInChildren <MB3_MeshBakerCommon>(); for (int i = 0; i < mb.Length; i++) { mb[i].textureBakeResults = textureBakeResults; } coroutineResult.isFinished = true; }