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);
    }
Esempio n. 2
0
    /// <summary>
    /// Creates for materials on renderer.
    /// </summary>
    /// <returns>Generates an MB2_TextureBakeResult that can be used if all objects to be combined use the same material.
    /// Returns a MB2_TextureBakeResults that will map all materials used by renderer r to
    /// the rectangle 0,0..1,1 in the atlas.</returns>
    /// <param name="r">The red component.</param>
    public static MB2_TextureBakeResults CreateForMaterialsOnRenderer(Renderer r)
    {
        MB2_TextureBakeResults tbr = (MB2_TextureBakeResults)ScriptableObject.CreateInstance(typeof(MB2_TextureBakeResults));

        Material[] ms = r.materials;
        tbr.resultMaterial    = ms[0];
        tbr.fixOutOfBoundsUVs = false;
        tbr.materials         = ms;
        tbr.resultMaterials   = new MB_MultiMaterial[ms.Length];
        if (ms.Length > 1)
        {
            tbr.prefabUVRects = new Rect[ms.Length];
            for (int i = 0; i < ms.Length; i++)
            {
                tbr.prefabUVRects[i]   = new Rect(0f, 0f, 1f, 1f);
                tbr.resultMaterials[i] = new MB_MultiMaterial();
                List <Material> sourceMats = new List <Material>();
                sourceMats.Add(ms[i]);
                tbr.resultMaterials[i].sourceMaterials  = sourceMats;
                tbr.resultMaterials[i].combinedMaterial = ms[i];
            }
            tbr.doMultiMaterial = true;
        }
        else
        {
            tbr.doMultiMaterial = false;
            tbr.prefabUVRects   = new Rect[] { new Rect(0f, 0f, 1f, 1f) };
        }
        return(tbr);
    }
 private static bool IsGoodToBake(Renderer r, MB2_TextureBakeResults tbr)
 {
     if (r == null)
     {
         return(false);
     }
     if (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer))
     {
         return(false);
     }
     Material[] mats = r.sharedMaterials;
     for (int i = 0; i < mats.Length; i++)
     {
         if (!tbr.ContainsMaterial(mats[i]))
         {
             Debug.LogWarning("Mesh on " + r + " uses a material " + mats[i] + " that is not in the list of materials. This mesh will not be baked. The original mesh and material will be used in the result prefab.");
             return(false);
         }
     }
     if (MB_Utility.GetMesh(r.gameObject) == null)
     {
         return(false);
     }
     return(true);
 }
        public Material2AtlasRectangleMapper(MB2_TextureBakeResults res)
        {
            tbr = res;
            matsAndSrcUVRect = res.materialsAndUVRects;

            //count the number of times a material appears in the atlas. used for fast lookup
            numTimesMatAppearsInAtlas = new int[matsAndSrcUVRect.Length];
            for (int i = 0; i < matsAndSrcUVRect.Length; i++)
            {
                if (numTimesMatAppearsInAtlas[i] > 1)
                {
                    continue;
                }
                int count = 1;
                for (int j = i + 1; j < matsAndSrcUVRect.Length; j++)
                {
                    if (matsAndSrcUVRect[i].material == matsAndSrcUVRect[j].material)
                    {
                        count++;
                    }
                }
                numTimesMatAppearsInAtlas[i] = count;
                if (count > 1)
                {
                    //allMatsAreUnique = false;
                    for (int j = i + 1; j < matsAndSrcUVRect.Length; j++)
                    {
                        if (matsAndSrcUVRect[i].material == matsAndSrcUVRect[j].material)
                        {
                            numTimesMatAppearsInAtlas[j] = count;
                        }
                    }
                }
            }
        }
Esempio n. 5
0
    public static MB2_TextureBakeResults CreateForMaterialsOnRenderer(Renderer r)
    {
        MB2_TextureBakeResults mb2_TextureBakeResults = (MB2_TextureBakeResults)ScriptableObject.CreateInstance(typeof(MB2_TextureBakeResults));

        Material[] sharedMaterials = r.sharedMaterials;
        mb2_TextureBakeResults.resultMaterial    = sharedMaterials[0];
        mb2_TextureBakeResults.fixOutOfBoundsUVs = false;
        mb2_TextureBakeResults.materials         = sharedMaterials;
        mb2_TextureBakeResults.resultMaterials   = new MB_MultiMaterial[sharedMaterials.Length];
        if (sharedMaterials.Length > 1)
        {
            mb2_TextureBakeResults.prefabUVRects = new Rect[sharedMaterials.Length];
            for (int i = 0; i < sharedMaterials.Length; i++)
            {
                mb2_TextureBakeResults.prefabUVRects[i]   = new Rect(0f, 0f, 1f, 1f);
                mb2_TextureBakeResults.resultMaterials[i] = new MB_MultiMaterial();
                List <Material> list = new List <Material>();
                list.Add(sharedMaterials[i]);
                mb2_TextureBakeResults.resultMaterials[i].sourceMaterials  = list;
                mb2_TextureBakeResults.resultMaterials[i].combinedMaterial = sharedMaterials[i];
            }
            mb2_TextureBakeResults.doMultiMaterial = true;
        }
        else
        {
            mb2_TextureBakeResults.doMultiMaterial = false;
            mb2_TextureBakeResults.prefabUVRects   = new Rect[]
            {
                new Rect(0f, 0f, 1f, 1f)
            };
        }
        return(mb2_TextureBakeResults);
    }
Esempio n. 6
0
 public void DoIntegrityCheckMergedEncapsulatingSamplingRects(List <MB_TexSet> distinctMaterialTextures)
 {
     if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
     {
         for (int i = 0; i < distinctMaterialTextures.Count; i++)
         {
             MB_TexSet tx1 = distinctMaterialTextures[i];
             if (!tx1.allTexturesUseSameMatTiling)
             {
                 continue;
             }
             for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
             {
                 MatAndTransformToMerged mat = tx1.matsAndGOs.mats[matIdx];
                 DRect uvR  = mat.obUVRectIfTilingSame;
                 DRect matR = mat.materialTiling;
                 if (!MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(tx1.tilingTreatment, uvR.GetRect(), matR.GetRect(), tx1.ts[0].GetEncapsulatingSamplingRect().GetRect(), MB2_LogLevel.info))
                 {
                     Debug.LogErrorFormat("mesh " + tx1.matsAndGOs.mats[matIdx].objName + "\n" +
                                          " uv=" + uvR + "\n" +
                                          " mat=" + matR.GetRect().ToString("f5") + "\n" +
                                          " samplingRect=" + tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling.GetRect().ToString("f4") + "\n" +
                                          " encapsulatingRect " + tx1.ts[0].GetEncapsulatingSamplingRect().GetRect().ToString("f4") + "\n");
                     Debug.LogErrorFormat(string.Format("Integrity check failed. " + tx1.matsAndGOs.mats[matIdx].objName + " Encapsulating sampling rect failed to contain potentialRect\n"));
                     MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(tx1.tilingTreatment, uvR.GetRect(), matR.GetRect(), tx1.ts[0].GetEncapsulatingSamplingRect().GetRect(), MB2_LogLevel.trace);
                     Debug.Assert(false);
                 }
             }
         }
     }
 }
Esempio n. 7
0
 internal static IEnumerator FindRuntimeMaterialsFromAddresses(MB2_TextureBakeResults textureBakeResult, MB2_TextureBakeResults.CoroutineResult isComplete)
 {
     if (_MBVersion == null)
     {
         _MBVersion = _CreateMBVersionConcrete();
     }
     yield return(_MBVersion.FindRuntimeMaterialsFromAddresses(textureBakeResult, isComplete));
 }
 private void UpgradeToCurrentVersion(MB2_TextureBakeResults tbr)
 {
     if (tbr.version < 3252)
     {
         for (int i = 0; i < tbr.materialsAndUVRects.Length; i++)
         {
             tbr.materialsAndUVRects[i].allPropsUseSameTiling = true;
         }
     }
 }
 protected virtual bool _CreateTemporaryTextrueBakeResult(GameObject[] gos, List <Material> matsOnTargetRenderer)
 {
     if (GetNumObjectsInCombined() > 0)
     {
         Debug.LogError("Can't add objects if there are already objects in combined mesh when 'Texture Bake Result' is not set. Perhaps enable 'Clear Buffers After Bake'");
         return(false);
     }
     _usingTemporaryTextureBakeResult = true;
     _textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(gos, matsOnTargetRenderer);
     return(true);
 }
Esempio n. 10
0
    /// <summary>
    /// Creates for materials on renderer.
    /// </summary>
    /// <returns>Generates an MB2_TextureBakeResult that can be used if all objects to be combined use the same material.
    /// Returns a MB2_TextureBakeResults that will map all materials used by renderer r to
    /// the rectangle 0,0..1,1 in the atlas.</returns>
    /// <param name="r">The red component.</param>
    public static MB2_TextureBakeResults CreateForMaterialsOnRenderer(Renderer r)
    {
        MB2_TextureBakeResults tbr = (MB2_TextureBakeResults)ScriptableObject.CreateInstance(typeof(MB2_TextureBakeResults));
        //Material[] ms = r.sharedMaterials;
        //MB_MaterialAndUVRect[] mss = new MB_MaterialAndUVRect[r.sharedMaterials.Length];
        List <MB_MaterialAndUVRect> mss = new List <MB_MaterialAndUVRect>();

        Material[] ms;
        for (int i = 0; i < r.sharedMaterials.Length; i++)
        {
            if (r.sharedMaterials[i] != null)
            {
                MB_MaterialAndUVRect matAndUVRect = new MB_MaterialAndUVRect(r.sharedMaterials[i], new Rect(0f, 0f, 1f, 1f), new Rect(0f, 0f, 1f, 1f), new Rect(0f, 0f, 1f, 1f), new Rect(0f, 0f, 1f, 1f), r.name);
                if (!mss.Contains(matAndUVRect))
                {
                    mss.Add(matAndUVRect);
                }
            }
        }
        if (r.sharedMaterials.Length > 1)
        {
            tbr.prefabUVRects   = new Rect[mss.Count];
            tbr.materials       = ms = new Material[mss.Count];
            tbr.resultMaterials = new MB_MultiMaterial[mss.Count];
            for (int i = 0; i < mss.Count; i++)
            {
                ms[i] = mss[i].material;
                tbr.prefabUVRects[i]   = new Rect(0f, 0f, 1f, 1f);
                tbr.resultMaterials[i] = new MB_MultiMaterial();
                List <Material> sourceMats = new List <Material>();
                sourceMats.Add(ms[i]);
                tbr.resultMaterials[i].sourceMaterials  = sourceMats;
                tbr.resultMaterials[i].combinedMaterial = ms[i];
            }
            tbr.doMultiMaterial = true;
        }
        else
        {
            tbr.doMultiMaterial = false;
            tbr.prefabUVRects   = new Rect[] { new Rect(0f, 0f, 1f, 1f) };
            tbr.materials       = ms = new Material[] { mss[0].material };
            tbr.resultMaterial  = mss[0].material;
            tbr.resultMaterials = new MB_MultiMaterial[] { new MB_MultiMaterial() };
            List <Material> sourceMats = new List <Material>();
            sourceMats.Add(ms[0]);
            tbr.resultMaterials[0].sourceMaterials  = sourceMats;
            tbr.resultMaterials[0].combinedMaterial = mss[0].material;
        }
        tbr.materialsAndUVRects = mss.ToArray();
        tbr.fixOutOfBoundsUVs   = false;
        return(tbr);
    }
Esempio n. 11
0
        //Rect[] uvRectInAtlas;

        public Material2AtlasRectangleMapper(MB2_TextureBakeResults res)
        {
            tbr = res;
            matsAndSrcUVRect = res.materialsAndUVRects;
            //uvRectInAtlas = res.prefabUVRects;
            //allMatsAreUnique = true;

            //backward compatibility. this may be an old TextureBakeResult which has no materialsAndUVRects if so then build it now
            if (matsAndSrcUVRect == null || matsAndSrcUVRect.Length == 0)
            {
                matsAndSrcUVRect = new MB_MaterialAndUVRect[res.materials.Length];
                for (int i = 0; i < res.materials.Length; i++)
                {
                    matsAndSrcUVRect[i] = new MB_MaterialAndUVRect(res.materials[i], res.prefabUVRects[i], new Rect(0f, 0f, 1f, 1f));
                }
                res.materialsAndUVRects = matsAndSrcUVRect;
            }

            //count the number of times a material appears in the atlas. used for fast lookup
            numTimesMatAppearsInAtlas = new int[matsAndSrcUVRect.Length];
            for (int i = 0; i < matsAndSrcUVRect.Length; i++)
            {
                if (numTimesMatAppearsInAtlas[i] > 1)
                {
                    continue;
                }
                int count = 1;
                for (int j = i + 1; j < matsAndSrcUVRect.Length; j++)
                {
                    if (matsAndSrcUVRect[i].material == matsAndSrcUVRect[j].material)
                    {
                        count++;
                    }
                }
                numTimesMatAppearsInAtlas[i] = count;
                if (count > 1)
                {
                    //allMatsAreUnique = false;
                    for (int j = i + 1; j < matsAndSrcUVRect.Length; j++)
                    {
                        if (matsAndSrcUVRect[i].material == matsAndSrcUVRect[j].material)
                        {
                            numTimesMatAppearsInAtlas[j] = count;
                        }
                    }
                }
            }
        }
Esempio n. 12
0
        protected virtual bool _CheckIfAllObjsToAddUseSameMaterialsAndCreateTemporaryTextrueBakeResult(GameObject[] gos)
        {
            _usingTemporaryTextureBakeResult = false;
            Renderer r = MB_Utility.GetRenderer(gos[0]);

            if (r != null)
            {
                Material[] mats = MB_Utility.GetGOMaterials(gos[0]);
                for (int i = 0; i < gos.Length; i++)
                {
                    if (gos[i] == null)
                    {
                        Debug.LogError(string.Format("Game object {0} in list of objects to add was null", i));
                        return(false);
                    }
                    Material[] oMats = MB_Utility.GetGOMaterials(gos[i]);
                    if (oMats == null)
                    {
                        Debug.LogError(string.Format("Game object {0} in list of objects to add no renderer", i));
                        return(false);
                    }
                    for (int j = 0; j < oMats.Length; j++)
                    {
                        bool found = false;
                        for (int k = 0; k < mats.Length; k++)
                        {
                            if (oMats[j] == mats[k])
                            {
                                found = true;
                                break;
                            }
                        }
                        if (found == false)
                        {
                            Debug.LogError(string.Format("Material Bake Result is null and game object {0} in list of objects to add did not have a subset of the materials in on the first object. You need to bake textures or all objects must have a subset of materials on the first object.", i));
                            return(false);
                        }
                    }
                }
                _usingTemporaryTextureBakeResult = true;
                _textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(r);
                return(true);
            }
            return(false);
        }
Esempio n. 13
0
    void unpackMat2RectMap(MB2_TextureBakeResults results)
    {
        List <Material> ms = new List <Material>();
        List <Rect>     rs = new List <Rect>();

        for (int i = 0; i < results.combinedMaterialInfo.Length; i++)
        {
            MB_AtlasesAndRects          newMesh = results.combinedMaterialInfo[i];
            Dictionary <Material, Rect> map     = newMesh.mat2rect_map;
            foreach (Material m in map.Keys)
            {
                ms.Add(m);
                rs.Add(map[m]);
            }
        }
        results.materials     = ms.ToArray();
        results.prefabUVRects = rs.ToArray();
    }
Esempio n. 14
0
    private void unpackMat2RectMap(MB2_TextureBakeResults resultAtlasesAndRects)
    {
        List <Material> list  = new List <Material>();
        List <Rect>     list2 = new List <Rect>();

        for (int i = 0; i < resultAtlasesAndRects.combinedMaterialInfo.Length; i++)
        {
            MB_AtlasesAndRects          mb_AtlasesAndRects = resultAtlasesAndRects.combinedMaterialInfo[i];
            Dictionary <Material, Rect> mat2rect_map       = mb_AtlasesAndRects.mat2rect_map;
            foreach (Material material in mat2rect_map.Keys)
            {
                list.Add(material);
                list2.Add(mat2rect_map[material]);
            }
        }
        resultAtlasesAndRects.materials     = list.ToArray();
        resultAtlasesAndRects.prefabUVRects = list2.ToArray();
    }
Esempio n. 15
0
    /*
     * MB_AtlasesAndRects[] _CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null)
     * {
     *  //validation
     *  if (saveAtlasesAsAssets && editorMethods == null)
     *  {
     *      Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true then editorMethods cannot be null.");
     *      return null;
     *  }
     *  if (saveAtlasesAsAssets && !Application.isEditor)
     *  {
     *      Debug.LogError("Error in CreateAtlases If saveAtlasesAsAssets = true it must be called from the Unity Editor.");
     *      return null;
     *  }
     *  MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;
     *  if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, editorMethods, vl))
     *  {
     *      return null;
     *  }
     *  if (_doMultiMaterial && !_ValidateResultMaterials())
     *  {
     *      return null;
     *  }
     *  else if (!_doMultiMaterial)
     *  {
     *      if (_resultMaterial == null)
     *      {
     *          Debug.LogError("Combined Material is null please create and assign a result material.");
     *          return null;
     *      }
     *      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.");
     *              }
     *
     *          }
     *      }
     *  }
     *
     *  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)
     *          {
     *              Debug.LogError("Game object " + objsToMesh[i] + " has a null material. Can't build atlases");
     *              return null;
     *          }
     *
     *      }
     *  }
     *
     *  MB3_TextureCombiner combiner = new MB3_TextureCombiner();
     *  combiner.LOG_LEVEL = LOG_LEVEL;
     *  combiner.atlasPadding = _atlasPadding;
     *  combiner.maxAtlasSize = _maxAtlasSize;
     *  combiner.customShaderPropNames = _customShaderProperties;
     *  combiner.fixOutOfBoundsUVs = _fixOutOfBoundsUVs;
     *  combiner.maxTilingBakeSize = _maxTilingBakeSize;
     *  combiner.packingAlgorithm = _packingAlgorithm;
     *  combiner.meshBakerTexturePackerForcePowerOfTwo = _meshBakerTexturePackerForcePowerOfTwo;
     *  combiner.resizePowerOfTwoTextures = _resizePowerOfTwoTextures;
     *  combiner.saveAtlasesAsAssets = saveAtlasesAsAssets;
     *  combiner.considerNonTextureProperties = _considerNonTextureProperties;
     *
     *  // if editor analyse meshes and suggest treatment
     *  if (!Application.isPlaying && _doSuggestTreatment)
     *  {
     *      Material[] rms;
     *      if (_doMultiMaterial)
     *      {
     *          rms = new Material[resultMaterials.Length];
     *          for (int i = 0; i < rms.Length; i++) rms[i] = resultMaterials[i].combinedMaterial;
     *      }
     *      else
     *      {
     *          rms = new Material[1];
     *          rms[0] = _resultMaterial;
     *      }
     *      combiner.SuggestTreatment(objsToMesh, rms, combiner.customShaderPropNames);
     *  }
     *
     *  //initialize structure to store results
     *  int numResults = 1;
     *  if (_doMultiMaterial) numResults = resultMaterials.Length;
     *  MB_AtlasesAndRects[] resultAtlasesAndRects = new MB_AtlasesAndRects[numResults];
     *  for (int i = 0; i < resultAtlasesAndRects.Length; i++)
     *  {
     *      resultAtlasesAndRects[i] = new MB_AtlasesAndRects();
     *  }
     *
     *  //Do the material combining.
     *  for (int i = 0; i < resultAtlasesAndRects.Length; i++)
     *  {
     *      Material resMatToPass = null;
     *      List<Material> sourceMats = null;
     *      if (_doMultiMaterial)
     *      {
     *          sourceMats = resultMaterials[i].sourceMaterials;
     *          resMatToPass = resultMaterials[i].combinedMaterial;
     *      }
     *      else
     *      {
     *          resMatToPass = _resultMaterial;
     *      }
     *      Debug.Log(string.Format("Creating atlases for result material {0} using shader {1}", resMatToPass, resMatToPass.shader));
     *      if (!combiner.CombineTexturesIntoAtlases(progressInfo, resultAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods))
     *      {
     *          return null;
     *      }
     *  }
     *
     *  //Save the results
     *  textureBakeResults.combinedMaterialInfo = resultAtlasesAndRects;
     *  textureBakeResults.doMultiMaterial = _doMultiMaterial;
     *  textureBakeResults.resultMaterial = _resultMaterial;
     *  textureBakeResults.resultMaterials = resultMaterials;
     *  textureBakeResults.fixOutOfBoundsUVs = combiner.fixOutOfBoundsUVs;
     *  unpackMat2RectMap(textureBakeResults);
     *
     *  //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;
     *  }
     *
     *  if (LOG_LEVEL >= MB2_LogLevel.info) Debug.Log("Created Atlases");
     *  return resultAtlasesAndRects;
     * }
     */

    void unpackMat2RectMap(MB2_TextureBakeResults tbr)
    {
        List <Material>             ms  = new List <Material>();
        List <MB_MaterialAndUVRect> mss = new List <MB_MaterialAndUVRect>();
        List <Rect> rs = new List <Rect>();

        for (int i = 0; i < tbr.combinedMaterialInfo.Length; i++)
        {
            MB_AtlasesAndRects          newMesh = tbr.combinedMaterialInfo[i];
            List <MB_MaterialAndUVRect> map     = newMesh.mat2rect_map;
            for (int j = 0; j < map.Count; j++)
            {
                mss.Add(map[j]);
                ms.Add(map[j].material);
                rs.Add(map[j].atlasRect);
            }
        }
        tbr.materialsAndUVRects = mss.ToArray();
        tbr.materials           = ms.ToArray();
        tbr.prefabUVRects       = rs.ToArray();
    }
Esempio n. 16
0
    void unpackMat2RectMap(MB2_TextureBakeResults tbr)
    {
        List <Material>             ms  = new List <Material>();
        List <MB_MaterialAndUVRect> mss = new List <MB_MaterialAndUVRect>();
        List <Rect> rs = new List <Rect>();

        for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++)
        {
            MB_AtlasesAndRects          newMesh = this.OnCombinedTexturesCoroutineAtlasesAndRects[i];
            List <MB_MaterialAndUVRect> map     = newMesh.mat2rect_map;
            if (map != null)
            {
                for (int j = 0; j < map.Count; j++)
                {
                    mss.Add(map[j]);
                    ms.Add(map[j].material);
                    rs.Add(map[j].atlasRect);
                }
            }
        }
        tbr.version             = MB2_TextureBakeResults.VERSION;
        tbr.materialsAndUVRects = mss.ToArray();
    }
            public UVAdjuster_Atlas(MB2_TextureBakeResults tbr, MB2_LogLevel ll)
            {
                textureBakeResults = tbr;
                LOG_LEVEL          = ll;
                matsAndSrcUVRect   = tbr.materialsAndUVRects;

                //count the number of times a material appears in the atlas. used for fast lookup
                numTimesMatAppearsInAtlas = new int[matsAndSrcUVRect.Length];
                for (int i = 0; i < matsAndSrcUVRect.Length; i++)
                {
                    if (numTimesMatAppearsInAtlas[i] > 1)
                    {
                        continue;
                    }
                    int count = 1;
                    for (int j = i + 1; j < matsAndSrcUVRect.Length; j++)
                    {
                        if (matsAndSrcUVRect[i].material == matsAndSrcUVRect[j].material)
                        {
                            count++;
                        }
                    }
                    numTimesMatAppearsInAtlas[i] = count;
                    if (count > 1)
                    {
                        //allMatsAreUnique = false;
                        for (int j = i + 1; j < matsAndSrcUVRect.Length; j++)
                        {
                            if (matsAndSrcUVRect[i].material == matsAndSrcUVRect[j].material)
                            {
                                numTimesMatAppearsInAtlas[j] = count;
                            }
                        }
                    }
                }
            }
	bool IsGoodToBake(Renderer r, MB2_TextureBakeResults tbr){
		if (r == null) return false;
		if (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)){
			return false;	
		}
		Material[] mats = r.sharedMaterials;
		for (int i = 0; i < mats.Length; i++){
			if (!ArrayUtility.Contains<Material>(tbr.materials,mats[i])){
				Debug.LogWarning("Mesh on " + r + " uses a material " + mats[i] + " that is not in the list of materials. This mesh will not be baked. The original mesh and material will be used in the result prefab.");
				//todo assign the source assets to the result
				return false;
			}
		}
		if (MB_Utility.GetMesh(r.gameObject) == null){
			return false;
		}
		return true;
	}
Esempio n. 19
0
	void unpackMat2RectMap(MB2_TextureBakeResults resultAtlasesAndRects){
		List<Material> ms = new List<Material>();
		List<Rect> rs = new List<Rect>();
		for (int i = 0; i < resultAtlasesAndRects.combinedMaterialInfo.Length; i++){
			MB_AtlasesAndRects newMesh = resultAtlasesAndRects.combinedMaterialInfo[i];
			Dictionary<Material,Rect> map = newMesh.mat2rect_map;
			foreach(Material m in map.Keys){
				ms.Add(m);
				rs.Add(map[m]);
			}
		}
		resultAtlasesAndRects.materials = ms.ToArray();
		resultAtlasesAndRects.prefabUVRects = rs.ToArray();
	}
            /// <summary>
            /// A material can appear more than once in an atlas if using fixOutOfBoundsUVs.
            /// in this case you need to use the UV rect of the mesh to find the correct rectangle.
            /// If the all properties on the mat use the same tiling then
            /// encapsulatingRect can be larger and will include baked UV and material tiling
            /// If mat uses different tiling for different maps then encapsulatingRect is the uvs of
            /// source mesh used to bake atlas and sourceMaterialTilingOut is 0,0,1,1. This works because
            /// material tiling was baked into the atlas.
            /// </summary>
            public bool TryMapMaterialToUVRect(Material mat, Mesh m, int submeshIdx, int idxInResultMats,
                                               MB3_MeshCombinerSingle.MeshChannelsCache meshChannelCache,
                                               Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisCache,
                                               out MB_TextureTilingTreatment tilingTreatment,
                                               out Rect rectInAtlas,
                                               out Rect encapsulatingRectOut,
                                               out Rect sourceMaterialTilingOut,
                                               out int sliceIdx,
                                               ref String errorMsg,
                                               MB2_LogLevel logLevel)
            {
                if (textureBakeResults.version < MB2_TextureBakeResults.VERSION)
                {
                    textureBakeResults.UpgradeToCurrentVersion(textureBakeResults);
                }
                tilingTreatment = MB_TextureTilingTreatment.unknown;
                if (textureBakeResults.materialsAndUVRects.Length == 0)
                {
                    errorMsg                = "The 'Texture Bake Result' needs to be re-baked to be compatible with this version of Mesh Baker. Please re-bake using the MB3_TextureBaker.";
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx                = -1;
                    return(false);
                }
                if (mat == null)
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx = -1;
                    errorMsg = String.Format("Mesh {0} Had no material on submesh {1} cannot map to a material in the atlas", m.name, submeshIdx);
                    return(false);
                }
                if (submeshIdx >= m.subMeshCount)
                {
                    errorMsg                = "Submesh index is greater than the number of submeshes";
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx                = -1;
                    return(false);
                }

                //find the first index of this material
                int idx = -1;

                for (int i = 0; i < matsAndSrcUVRect.Length; i++)
                {
                    if (mat == matsAndSrcUVRect[i].material)
                    {
                        idx = i;
                        break;
                    }
                }
                // if couldn't find material
                if (idx == -1)
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx = -1;
                    errorMsg = String.Format("Material {0} could not be found in the Texture Bake Result", mat.name);
                    return(false);
                }

                bool considerUVs = textureBakeResults.GetConsiderMeshUVs(idxInResultMats, mat);

                if (!considerUVs)
                {
                    if (numTimesMatAppearsInAtlas[idx] != 1)
                    {
                        Debug.LogError("There is a problem with this TextureBakeResults. FixOutOfBoundsUVs is false and a material appears more than once: " + matsAndSrcUVRect[idx].material + " appears: " + numTimesMatAppearsInAtlas[idx]);
                    }
                    MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                    rectInAtlas             = mr.atlasRect;
                    tilingTreatment         = mr.tilingTreatment;
                    encapsulatingRectOut    = mr.GetEncapsulatingRect();
                    sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                    sliceIdx = mr.textureArraySliceIdx;
                    return(true);
                }
                else
                {
                    //todo what if no UVs
                    //Find UV rect in source mesh
                    MB_Utility.MeshAnalysisResult[] mar;
                    if (!meshAnalysisCache.TryGetValue(m.GetInstanceID(), out mar))
                    {
                        mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount];
                        for (int j = 0; j < m.subMeshCount; j++)
                        {
                            Vector2[] uvss = meshChannelCache.GetUv0Raw(m);
                            MB_Utility.hasOutOfBoundsUVs(uvss, m, ref mar[j], j);
                        }
                        meshAnalysisCache.Add(m.GetInstanceID(), mar);
                    }

                    //this could be a mesh that was not used in the texture baking that has huge UV tiling too big for the rect that was baked
                    //find a record that has an atlas uvRect capable of containing this
                    bool found                = false;
                    Rect encapsulatingRect    = new Rect(0, 0, 0, 0);
                    Rect sourceMaterialTiling = new Rect(0, 0, 0, 0);
                    if (logLevel >= MB2_LogLevel.trace)
                    {
                        Debug.Log(String.Format("Trying to find a rectangle in atlas capable of holding tiled sampling rect for mesh {0} using material {1} meshUVrect={2}", m, mat, mar[submeshIdx].uvRect.ToString("f5")));
                    }
                    for (int i = idx; i < matsAndSrcUVRect.Length; i++)
                    {
                        MB_MaterialAndUVRect matAndUVrect = matsAndSrcUVRect[i];
                        if (matAndUVrect.material == mat)
                        {
                            if (matAndUVrect.allPropsUseSameTiling)
                            {
                                encapsulatingRect    = matAndUVrect.allPropsUseSameTiling_samplingEncapsulatinRect;
                                sourceMaterialTiling = matAndUVrect.allPropsUseSameTiling_sourceMaterialTiling;
                            }
                            else
                            {
                                encapsulatingRect    = matAndUVrect.propsUseDifferntTiling_srcUVsamplingRect;
                                sourceMaterialTiling = new Rect(0, 0, 1, 1);
                            }

                            if (MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(
                                    matAndUVrect.tilingTreatment,
                                    mar[submeshIdx].uvRect,
                                    sourceMaterialTiling,
                                    encapsulatingRect,
                                    logLevel))
                            {
                                if (logLevel >= MB2_LogLevel.trace)
                                {
                                    Debug.Log("Found rect in atlas capable of containing tiled sampling rect for mesh " + m + " at idx=" + i);
                                }
                                idx   = i;
                                found = true;
                                break;
                            }
                        }
                    }
                    if (found)
                    {
                        MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                        rectInAtlas             = mr.atlasRect;
                        tilingTreatment         = mr.tilingTreatment;
                        encapsulatingRectOut    = mr.GetEncapsulatingRect();
                        sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                        sliceIdx = mr.textureArraySliceIdx;
                        return(true);
                    }
                    else
                    {
                        rectInAtlas             = new Rect();
                        encapsulatingRectOut    = new Rect();
                        sourceMaterialTilingOut = new Rect();
                        sliceIdx = -1;
                        errorMsg = String.Format("Could not find a tiled rectangle in the atlas capable of containing the uv and material tiling on mesh {0} for material {1}. Was this mesh included when atlases were baked?", m.name, mat);
                        return(false);
                    }
                }
            }
Esempio n. 21
0
        void bake(MB3_MeshBakerCommon mom)
        {
            bool createdDummyTextureBakeResults = false;

            try{
                if (mom.textureBakeResults == null)
                {
                    if (_OkToCreateDummyTextureBakeResult(mom))
                    {
                        createdDummyTextureBakeResults = true;
                        List <GameObject> gos = mom.GetObjectsToCombine();
                        mom.textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(MB_Utility.GetRenderer(gos[0]));
                    }
                }
                if (mom.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoSceneObject)
                {
                    MB3_MeshBakerEditorFunctions.BakeIntoCombined(mom);
                }
                else if (mom.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoPrefab)
                {
                    MB3_MeshBakerEditorFunctions.BakeIntoCombined(mom);
                }
                else
                {
                    if (mom is MB3_MeshBaker)
                    {
                        if (MB3_MeshCombiner.EVAL_VERSION)
                        {
                            Debug.LogError("Bake Meshes In Place is disabled in the evaluation version.");
                        }
                        else
                        {
                            MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;
                            if (!MB3_MeshBakerRoot.DoCombinedValidate(mom, MB_ObjsToCombineTypes.prefabOnly, new MB3_EditorMethods(), vl))
                            {
                                return;
                            }

                            List <GameObject> objsToMesh = mom.GetObjectsToCombine();
                            //objsToMesh = mom.GetComponent<MB3_TextureBaker>().GetObjectsToCombine();
                            MB3_BakeInPlace.BakeMeshesInPlace((MB3_MeshCombinerSingle)((MB3_MeshBaker)mom).meshCombiner, objsToMesh, mom.bakeAssetsInPlaceFolderPath, updateProgressBar);
                        }
                    }
                    else
                    {
                        Debug.LogError("Multi-mesh Baker components cannot be used for Bake In Place. Use an ordinary Mesh Baker object instead.");
                    }
                }
                if (mom.clearBuffersAfterBake)
                {
                    mom.meshCombiner.ClearBuffers();
                }
            } catch (Exception e) {
                Debug.LogError(e);
            } finally {
                if (createdDummyTextureBakeResults)
                {
                    GameObject.DestroyImmediate(mom.textureBakeResults);
                    mom.textureBakeResults = null;
                }
                EditorUtility.ClearProgressBar();
            }
        }
    /// <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 override void meshAssign_UV0(int channel, MB_IMeshBakerSettings settings, MB2_TextureBakeResults textureBakeResults, Mesh mesh, Vector2[] uvs, float[] sliceIndexes)
        {
            if (textureBakeResults.resultType == MB2_TextureBakeResults.ResultType.atlas)
            {
                mesh.uv = uvs;
            }
            else
            {
                {
                    if (uvs.Length == sliceIndexes.Length)
                    {
                        List <Vector3> nuvs = new List <Vector3>();
                        for (int i = 0; i < uvs.Length; i++)
                        {
                            nuvs.Add(new Vector3(uvs[i].x, uvs[i].y, sliceIndexes[i]));
                        }

                        mesh.SetUVs(0, nuvs);
                    }
                    else
                    {
                        Debug.LogError("UV slice buffer was not the same size as the uv buffer");
                    }
                }
            }
        }
 public static void DefaultDelegateAssignMeshColors(MB_IMeshBakerSettings settings, MB2_TextureBakeResults textureBakeResults,
                                                    Mesh mesh, Color[] colors, float[] sliceIndexes)
 {
     mesh.colors = colors;
 }
    public void _bakePrefabs()
    {
        Debug.Log("Batch baking prefabs");
        if (Application.isPlaying)
        {
            Debug.LogError("The BatchPrefabBaker cannot be run in play mode.");
            return;
        }
        MB3_BatchPrefabBaker pb = (MB3_BatchPrefabBaker)target;
        MB3_MeshBaker        mb = pb.GetComponent <MB3_MeshBaker>();

        if (mb == null)
        {
            Debug.LogError("Prefab baker needs to be attached to a Game Object with a MB3_MeshBaker component.");
            return;
        }

        if (mb.textureBakeResults == null)
        {
            Debug.LogError("Texture Bake Results is not set");
            return;
        }

        if (mb.meshCombiner.outputOption != MB2_OutputOptions.bakeMeshAssetsInPlace)
        {
            mb.meshCombiner.outputOption = MB2_OutputOptions.bakeMeshAssetsInPlace;
        }

        MB2_TextureBakeResults tbr = mb.textureBakeResults;

        HashSet <Mesh> sourceMeshes    = new HashSet <Mesh>();
        HashSet <Mesh> allResultMeshes = new HashSet <Mesh>();

        //validate prefabs
        for (int i = 0; i < pb.prefabRows.Length; i++)
        {
            if (pb.prefabRows[i] == null || pb.prefabRows[i].sourcePrefab == null)
            {
                Debug.LogError("Source Prefab on row " + i + " is not set.");
                return;
            }
            if (pb.prefabRows[i].resultPrefab == null)
            {
                Debug.LogError("Result Prefab on row " + i + " is not set.");
                return;
            }
            for (int j = i + 1; j < pb.prefabRows.Length; j++)
            {
                if (pb.prefabRows[i].sourcePrefab == pb.prefabRows[j].sourcePrefab)
                {
                    Debug.LogError("Rows " + i + " and " + j + " contain the same source prefab");
                    return;
                }
            }
            for (int j = 0; j < pb.prefabRows.Length; j++)
            {
                if (pb.prefabRows[i].sourcePrefab == pb.prefabRows[j].resultPrefab)
                {
                    Debug.LogError("Row " + i + " source prefab is the same as row " + j + " result prefab");
                    return;
                }
            }
            if (PrefabUtility.GetPrefabType(pb.prefabRows[i].sourcePrefab) != PrefabType.ModelPrefab &&
                PrefabUtility.GetPrefabType(pb.prefabRows[i].sourcePrefab) != PrefabType.Prefab)
            {
                Debug.LogError("Row " + i + " source prefab is not a prefab asset");
                return;
            }
            if (PrefabUtility.GetPrefabType(pb.prefabRows[i].resultPrefab) != PrefabType.ModelPrefab &&
                PrefabUtility.GetPrefabType(pb.prefabRows[i].resultPrefab) != PrefabType.Prefab)
            {
                Debug.LogError("Row " + i + " result prefab is not a prefab asset");
                return;
            }

            GameObject so = (GameObject)Instantiate(pb.prefabRows[i].sourcePrefab);
            GameObject ro = (GameObject)Instantiate(pb.prefabRows[i].resultPrefab);
            Renderer[] rs = (Renderer[])so.GetComponentsInChildren <Renderer>();

            for (int j = 0; j < rs.Length; j++)
            {
                if (IsGoodToBake(rs[j], tbr))
                {
                    sourceMeshes.Add(MB_Utility.GetMesh(rs[j].gameObject));
                }
            }
            rs = (Renderer[])ro.GetComponentsInChildren <Renderer>();

            for (int j = 0; j < rs.Length; j++)
            {
                Renderer r = rs[j];
                if (r is MeshRenderer || r is SkinnedMeshRenderer)
                {
                    Mesh m = MB_Utility.GetMesh(r.gameObject);
                    if (m != null)
                    {
                        allResultMeshes.Add(m);
                    }
                }
            }
            DestroyImmediate(so);             //todo should cache these and have a proper cleanup at end
            DestroyImmediate(ro);
        }

        sourceMeshes.IntersectWith(allResultMeshes);
        HashSet <Mesh> sourceMeshesThatAreUsedByResult = sourceMeshes;

        if (sourceMeshesThatAreUsedByResult.Count > 0)
        {
            foreach (Mesh m in sourceMeshesThatAreUsedByResult)
            {
                Debug.LogWarning("Mesh " + m + " is used by both the source and result prefabs. New meshes will be created.");
            }
            //return;
        }

        Dictionary <string, string> createdMeshPaths = new Dictionary <string, string>();

        // Bake the meshes using the meshBaker component one prefab at a time
        for (int prefabIdx = 0; prefabIdx < pb.prefabRows.Length; prefabIdx++)
        {
            Debug.Log("==== Processing Source Prefab " + pb.prefabRows[prefabIdx].sourcePrefab);
            GameObject sceneObj     = (GameObject)Instantiate(pb.prefabRows[prefabIdx].sourcePrefab);
            GameObject resultPrefab = (GameObject)Instantiate(pb.prefabRows[prefabIdx].resultPrefab);

            Renderer[] rs = sceneObj.GetComponentsInChildren <Renderer>();
            if (rs.Length < 1)
            {
                Debug.LogWarning("Prefab " + prefabIdx + " does not have a renderer");
                DestroyImmediate(sceneObj);
                DestroyImmediate(resultPrefab);
                continue;
            }

            List <Mesh>           usedMeshes      = new List <Mesh>();
            List <UnityTransform> unityTransforms = new List <UnityTransform>();
            for (int j = 0; j < rs.Length; j++)
            {
                unityTransforms.Clear();
                Renderer r = rs[j];

                if (!IsGoodToBake(r, tbr))
                {
                    continue;
                }

                //find the corresponding mesh in the result prefab
                string resultFolderPath = AssetDatabase.GetAssetPath(pb.prefabRows[prefabIdx].resultPrefab);
                resultFolderPath = Path.GetDirectoryName(resultFolderPath);

                Mesh      m    = null;
                Transform tRes = FindCorrespondingTransform(sceneObj.transform, r.transform, resultPrefab.transform);
                if (tRes != null)
                {
                    m = MB_Utility.GetMesh(tRes.gameObject);
                }

                //if the meshes on source and result are the same we want to remove mesh so will create a new one
                if (sourceMeshesThatAreUsedByResult.Contains(m))
                {
                    Debug.LogWarning("Source and result prefabs share a mesh. Creating a new mesh for " + m);
                    MB_Utility.SetMesh(tRes.gameObject, null);
                    m = null;
                }


                string meshPath;
                //check that the mesh is an asset and that we have not used it already
                if (m != null && AssetDatabase.IsMainAsset(m.GetInstanceID()) && !usedMeshes.Contains(m))
                {
                    meshPath = AssetDatabase.GetAssetPath(m);
                    if (createdMeshPaths.ContainsKey(meshPath))
                    {
                        Debug.LogWarning("Different result prefabs share a mesh." + meshPath);
                    }
                }
                else                     //create a new mesh asset with a unique name
                {
                    string resultPrefabFilename = AssetDatabase.GetAssetPath(pb.prefabRows[prefabIdx].resultPrefab);
                    resultPrefabFilename = resultPrefabFilename.Substring(0, resultPrefabFilename.Length - ".prefab".Length) + ".asset";
                    meshPath             = AssetDatabase.GenerateUniqueAssetPath(resultPrefabFilename);
                    m = new Mesh();
                    AssetDatabase.CreateAsset(m, meshPath);
                    m = (Mesh)AssetDatabase.LoadAssetAtPath(meshPath, typeof(Mesh));
                }
                Debug.Log("  creating new mesh asset at path " + meshPath);
                if (!createdMeshPaths.ContainsKey(meshPath))
                {
                    createdMeshPaths.Add(meshPath, meshPath);
                }

                // position rotation and scale are baked into combined mesh.
                // Remember all the transforms settings then
                // record transform values to root of hierarchy
                Transform t = r.transform;
                if (t != t.root)
                {
                    do
                    {
                        unityTransforms.Add(new UnityTransform(t));
                        t = t.parent;
                    } while (t != null && t != t.root);
                }
                //add the root
                unityTransforms.Add(new UnityTransform(t.root));

                //position at identity
                for (int k = 0; k < unityTransforms.Count; k++)
                {
                    unityTransforms[k].t.localPosition = Vector3.zero;
                    unityTransforms[k].t.localRotation = Quaternion.identity;
                    unityTransforms[k].t.localScale    = Vector3.one;
                }

                //throw new Exception("");
                //bake the mesh
                mb.ClearMesh();
                MB3_MeshCombiner mc = mb.meshCombiner;
                m = MB3_BakeInPlace.BakeOneMesh((MB3_MeshCombinerSingle)mc, meshPath, r.gameObject);

                //replace the mesh
                if (r is MeshRenderer)
                {
                    MeshFilter mf = r.gameObject.GetComponent <MeshFilter>();
                    mf.sharedMesh = m;
                }
                else                     //skinned mesh
                {
                    SkinnedMeshRenderer smr = r.gameObject.GetComponent <SkinnedMeshRenderer>();
                    smr.sharedMesh = m;
                    smr.bones      = ((SkinnedMeshRenderer)mc.targetRenderer).bones;
                }

                //replace the result material(s)
                if (mb.textureBakeResults.doMultiMaterial)
                {
                    Material[] rss = new Material[mb.textureBakeResults.resultMaterials.Length];
                    for (int k = 0; k < rss.Length; k++)
                    {
                        rss[k] = mb.textureBakeResults.resultMaterials[k].combinedMaterial;
                    }
                    r.sharedMaterials = rss;
                }
                else
                {
                    Material[] originalMats = r.sharedMaterials;
                    Material[] rss          = new Material[originalMats.Length];
                    for (int k = 0; k < originalMats.Length; k++)
                    {
                        if (tbr.ContainsMaterial(originalMats[k]))
                        {
                            rss[k] = mb.textureBakeResults.resultMaterial;
                        }
                        else
                        {
                            rss[k] = originalMats[k];
                        }
                    }

                    r.sharedMaterials = rss;
                }

                //restore the transforms
                for (int k = 0; k < unityTransforms.Count; k++)
                {
                    unityTransforms[k].t.localPosition = unityTransforms[k].p;
                    unityTransforms[k].t.localRotation = unityTransforms[k].q;
                    unityTransforms[k].t.localScale    = unityTransforms[k].s;
                }
            }

            //replace the result prefab with the source object
            //duplicate the sceneObj so we can replace the clone into the prefab, not the source
            GameObject clone = (GameObject)Instantiate(sceneObj);
            PrefabUtility.ReplacePrefab(clone, pb.prefabRows[prefabIdx].resultPrefab, ReplacePrefabOptions.ReplaceNameBased);
            DestroyImmediate(clone);
            DestroyImmediate(sceneObj);
            DestroyImmediate(resultPrefab);
        }
        AssetDatabase.Refresh();
        mb.ClearMesh();
    }
Esempio n. 26
0
		protected virtual bool _CheckIfAllObjsToAddUseSameMaterialsAndCreateTemporaryTextrueBakeResult(GameObject[] gos){ 
			_usingTemporaryTextureBakeResult = false;
			Renderer r = MB_Utility.GetRenderer(gos[0]);
			if (r != null){
				Material[] mats = MB_Utility.GetGOMaterials(gos[0]);
				for (int i = 0; i < gos.Length; i++){
					if (gos[i] == null){
						Debug.LogError(string.Format("Game object {0} in list of objects to add was null", i));
						return false;
					}
					Material[] oMats = MB_Utility.GetGOMaterials(gos[i]);
					if (oMats == null){
						Debug.LogError(string.Format("Game object {0} in list of objects to add no renderer", i));
						return false;							
					}
					for (int j = 0; j <oMats.Length; j++){
						bool found = false;
						for (int k = 0; k < mats.Length; k++){
							if (oMats[j] == mats[k]){
								found = true;
								break;
							}
						}
						if (found == false){
							Debug.LogError (string.Format("Material Bake Result is null and game object {0} in list of objects to add did not have a subset of the materials in on the first object. You need to bake textures or all objects must have a subset of materials on the first object.",i));
							return false;
						}
					}
				}
				_usingTemporaryTextureBakeResult = true;
				_textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(r);
				return true;
			}
			return false;
		}
    private static void ProcessPrefabRowReplaceTargetPrefab(MB3_BatchPrefabBaker pb, MB3_BatchPrefabBaker.MB3_PrefabBakerRow pr, MB2_TextureBakeResults tbr, List <UnityTransform> unityTransforms, MB3_MeshBaker mb)
    {
        if (pb.LOG_LEVEL >= MB2_LogLevel.info)
        {
            Debug.Log("==== Processing Source Prefab " + pr.sourcePrefab);
        }

        GameObject srcPrefab        = pr.sourcePrefab;
        GameObject targetPrefab     = pr.resultPrefab;
        string     targetPrefabName = AssetDatabase.GetAssetPath(targetPrefab);
        GameObject prefabInstance   = GameObject.Instantiate(srcPrefab);

        Renderer[] rs = prefabInstance.GetComponentsInChildren <Renderer>();
        if (rs.Length < 1)
        {
            Debug.LogWarning("Prefab " + pr.sourcePrefab + " does not have a renderer");
            DestroyImmediate(prefabInstance);
            return;
        }

        Renderer[] sourceRenderers = prefabInstance.GetComponentsInChildren <Renderer>();

        Dictionary <Mesh, List <ProcessedMeshInfo> > processedMeshesSrcToTargetMap = new Dictionary <Mesh, List <ProcessedMeshInfo> >();

        for (int i = 0; i < sourceRenderers.Length; i++)
        {
            if (!IsGoodToBake(sourceRenderers[i], tbr))
            {
                continue;
            }

            Mesh sourceMesh = MB_Utility.GetMesh(sourceRenderers[i].gameObject);

            if (pb.LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("== Visiting renderer: " + sourceRenderers[i]);
            }
            // Try to find an existing mesh in the target that we can re-use
            Mesh      targetMeshAsset = null;
            Transform tr = FindCorrespondingTransform(prefabInstance.transform, sourceRenderers[i].transform, targetPrefab.transform);
            if (tr != null)
            {
                Mesh targMesh = MB_Utility.GetMesh(tr.gameObject);

                // Only replace target meshes if they are part of the target prefab.
                if (AssetDatabase.GetAssetPath(targMesh) == AssetDatabase.GetAssetPath(targetPrefab))
                {
                    targetMeshAsset = MB_Utility.GetMesh(tr.gameObject);
                    if (pb.LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log("Found correspoinding transform in target prefab: " + tr + " mesh: " + targetMeshAsset);
                    }
                }
            }

            // Check that we haven't processed this mesh already.
            List <ProcessedMeshInfo> lpmi;
            if (processedMeshesSrcToTargetMap.TryGetValue(sourceMesh, out lpmi))
            {
                Material[] srcMats = MB_Utility.GetGOMaterials(sourceRenderers[i].gameObject);
                for (int j = 0; j < lpmi.Count; j++)
                {
                    if (ComapreMaterials(srcMats, lpmi[j].srcMaterials))
                    {
                        if (pb.LOG_LEVEL >= MB2_LogLevel.trace)
                        {
                            Debug.Log("Found already processed mesh that uses the same mats");
                        }
                        targetMeshAsset = lpmi[j].targetMesh;
                        break;
                    }
                }
            }

            Material[]          sourceMaterials     = MB_Utility.GetGOMaterials(sourceRenderers[i].gameObject);
            TargetMeshTreatment targetMeshTreatment = TargetMeshTreatment.createNewMesh;
            string newMeshName = sourceMesh.name;
            if (targetMeshAsset != null)
            {
                // check if this mesh has already been processed
                processedMeshesSrcToTargetMap.TryGetValue(sourceMesh, out lpmi);
                if (lpmi != null)
                {
                    // check if this mesh uses the same materials as one of the processed meshs
                    bool       foundMatch            = false;
                    bool       targetMeshHasBeenUsed = false;
                    Material[] foundMatchMaterials   = null;
                    for (int j = 0; j < lpmi.Count; j++)
                    {
                        if (lpmi[j].targetMesh == targetMeshAsset)
                        {
                            targetMeshHasBeenUsed = true;
                        }
                        if (ComapreMaterials(sourceMaterials, lpmi[j].srcMaterials))
                        {
                            foundMatchMaterials = lpmi[j].targMaterials;
                            foundMatch          = true;
                            break;
                        }
                    }

                    if (foundMatch)
                    {
                        // If materials match then we can re-use this processed mesh don't process.
                        if (pb.LOG_LEVEL >= MB2_LogLevel.trace)
                        {
                            Debug.Log(" we can re-use this processed mesh don't process. " + targetMeshAsset);
                        }
                        targetMeshTreatment = TargetMeshTreatment.reuseMesh;
                        MB_Utility.SetMesh(sourceRenderers[i].gameObject, targetMeshAsset);
                        SetMaterials(foundMatchMaterials, sourceRenderers[i]);
                        continue;
                    }
                    else
                    {
                        if (targetMeshHasBeenUsed)
                        {
                            // we need a new target mesh with a safe different name
                            if (pb.LOG_LEVEL >= MB2_LogLevel.trace)
                            {
                                Debug.Log(" we can't re-use this processed mesh create new with different name. " + targetMeshAsset);
                            }
                            newMeshName         = GetNameForNewMesh(AssetDatabase.GetAssetPath(targetPrefab), newMeshName);
                            targetMeshTreatment = TargetMeshTreatment.createNewMesh;
                            targetMeshAsset     = null;
                        }
                        else
                        {
                            // is it safe to reuse the target mesh
                            // we need a new target mesh with a safe different name
                            if (pb.LOG_LEVEL >= MB2_LogLevel.trace)
                            {
                                Debug.Log(" we can replace this processed mesh. " + targetMeshAsset);
                            }
                            targetMeshTreatment = TargetMeshTreatment.replaceMesh;
                        }
                    }
                }
                else
                {
                    // source mesh has not been processed can reuse the target mesh
                    targetMeshTreatment = TargetMeshTreatment.replaceMesh;
                }
            }

            if (targetMeshTreatment == TargetMeshTreatment.replaceMesh)
            {
                if (pb.LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Replace mesh " + targetMeshAsset);
                }
                EditorUtility.CopySerialized(sourceMesh, targetMeshAsset);
                AssetDatabase.SaveAssets();
                AssetDatabase.ImportAsset(targetPrefabName);
            }
            else if (targetMeshTreatment == TargetMeshTreatment.createNewMesh)
            {
                if (pb.LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Create new mesh " + newMeshName);
                }
                targetMeshAsset      = GameObject.Instantiate <Mesh>(sourceMesh);
                targetMeshAsset.name = newMeshName;
                AssetDatabase.AddObjectToAsset(targetMeshAsset, targetPrefab);
#if UNITY_2018_3_OR_NEWER
                PrefabUtility.SavePrefabAsset(targetPrefab);
#endif
                Debug.Assert(targetMeshAsset != null);
                // need a new mesh
            }

            if (targetMeshTreatment == TargetMeshTreatment.createNewMesh || targetMeshTreatment == TargetMeshTreatment.replaceMesh)
            {
                if (ProcessMesh(sourceRenderers[i], targetMeshAsset, unityTransforms, mb))
                {
                    if (pb.LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Done processing mesh " + targetMeshAsset + " verts " + targetMeshAsset.vertexCount);
                    }
                    ProcessedMeshInfo pmi = new ProcessedMeshInfo();
                    pmi.targetMesh    = targetMeshAsset;
                    pmi.srcMaterials  = sourceMaterials;
                    pmi.targMaterials = sourceRenderers[i].sharedMaterials;
                    AddToDictionary(sourceMesh, pmi, processedMeshesSrcToTargetMap);
                }
                else
                {
                    Debug.LogError("Error processing mesh " + targetMeshAsset);
                }
            }

            MB_Utility.SetMesh(sourceRenderers[i].gameObject, targetMeshAsset);
        }

        // TODO replace this with MBVersionEditor.ReplacePrefab I tried to do this, but when I did,
        // ProcessedMeshInfo.targetMesh becomes null, not sure what is going on there.
        GameObject obj = (GameObject)AssetDatabase.LoadAssetAtPath(targetPrefabName, typeof(GameObject));
        PrefabUtility.ReplacePrefab(prefabInstance, obj, ReplacePrefabOptions.ReplaceNameBased);
        GameObject.DestroyImmediate(prefabInstance);

        // Destroy obsolete meshes
        UnityEngine.Object[] allAssets    = AssetDatabase.LoadAllAssetsAtPath(targetPrefabName);
        HashSet <Mesh>       usedByTarget = new HashSet <Mesh>();
        foreach (List <ProcessedMeshInfo> ll in processedMeshesSrcToTargetMap.Values)
        {
            for (int i = 0; i < ll.Count; i++)
            {
                usedByTarget.Add(ll[i].targetMesh);
            }
        }
        int numDestroyed = 0;
        for (int i = 0; i < allAssets.Length; i++)
        {
            if (allAssets[i] is Mesh)
            {
                if (!usedByTarget.Contains((Mesh)allAssets[i]) && AssetDatabase.GetAssetPath(allAssets[i]) == AssetDatabase.GetAssetPath(targetPrefab))
                {
                    numDestroyed++;
                    GameObject.DestroyImmediate(allAssets[i], true);
                }
            }
        }

        if (pb.LOG_LEVEL >= MB2_LogLevel.debug)
        {
            Debug.Log("Destroyed " + numDestroyed + " meshes");
        }
        AssetDatabase.SaveAssets();
        //--------------------------
    }
    public static void BakePrefabs(MB3_BatchPrefabBaker pb, bool doReplaceTargetPrefab)
    {
        if (pb.LOG_LEVEL >= MB2_LogLevel.info)
        {
            Debug.Log("Batch baking prefabs");
        }
        if (Application.isPlaying)
        {
            Debug.LogError("The BatchPrefabBaker cannot be run in play mode.");
            return;
        }

        MB3_MeshBaker mb = pb.GetComponent <MB3_MeshBaker>();

        if (mb == null)
        {
            Debug.LogError("Prefab baker needs to be attached to a Game Object with a MB3_MeshBaker component.");
            return;
        }

        if (mb.textureBakeResults == null)
        {
            Debug.LogError("Texture Bake Results is not set");
            return;
        }

        if (mb.meshCombiner.outputOption != MB2_OutputOptions.bakeMeshAssetsInPlace)
        {
            mb.meshCombiner.outputOption = MB2_OutputOptions.bakeMeshAssetsInPlace;
        }

        MB2_TextureBakeResults tbr = mb.textureBakeResults;

        HashSet <Mesh> sourceMeshes    = new HashSet <Mesh>();
        HashSet <Mesh> allResultMeshes = new HashSet <Mesh>();

        //validate prefabs
        for (int i = 0; i < pb.prefabRows.Length; i++)
        {
            if (pb.prefabRows[i] == null || pb.prefabRows[i].sourcePrefab == null)
            {
                Debug.LogError("Source Prefab on row " + i + " is not set.");
                return;
            }
            if (pb.prefabRows[i].resultPrefab == null)
            {
                Debug.LogError("Result Prefab on row " + i + " is not set.");
                return;
            }
            for (int j = i + 1; j < pb.prefabRows.Length; j++)
            {
                if (pb.prefabRows[i].sourcePrefab == pb.prefabRows[j].sourcePrefab)
                {
                    Debug.LogError("Rows " + i + " and " + j + " contain the same source prefab");
                    return;
                }
            }
            for (int j = 0; j < pb.prefabRows.Length; j++)
            {
                if (pb.prefabRows[i].sourcePrefab == pb.prefabRows[j].resultPrefab)
                {
                    Debug.LogError("Row " + i + " source prefab is the same as row " + j + " result prefab");
                    return;
                }
            }
            if (MBVersionEditor.GetPrefabType(pb.prefabRows[i].sourcePrefab) != MB_PrefabType.modelPrefab &&
                MBVersionEditor.GetPrefabType(pb.prefabRows[i].sourcePrefab) != MB_PrefabType.prefab)
            {
                Debug.LogError("Row " + i + " source prefab is not a prefab asset ");
                return;
            }
            if (MBVersionEditor.GetPrefabType(pb.prefabRows[i].resultPrefab) != MB_PrefabType.modelPrefab &&
                MBVersionEditor.GetPrefabType(pb.prefabRows[i].resultPrefab) != MB_PrefabType.prefab)
            {
                Debug.LogError("Row " + i + " result prefab is not a prefab asset");
                return;
            }

            GameObject so = (GameObject)Instantiate(pb.prefabRows[i].sourcePrefab);
            GameObject ro = (GameObject)Instantiate(pb.prefabRows[i].resultPrefab);
            Renderer[] rs = (Renderer[])so.GetComponentsInChildren <Renderer>();

            for (int j = 0; j < rs.Length; j++)
            {
                if (IsGoodToBake(rs[j], tbr))
                {
                    sourceMeshes.Add(MB_Utility.GetMesh(rs[j].gameObject));
                }
            }
            rs = (Renderer[])ro.GetComponentsInChildren <Renderer>();

            for (int j = 0; j < rs.Length; j++)
            {
                Renderer r = rs[j];
                if (r is MeshRenderer || r is SkinnedMeshRenderer)
                {
                    Mesh m = MB_Utility.GetMesh(r.gameObject);
                    if (m != null)
                    {
                        allResultMeshes.Add(m);
                    }
                }
            }
            DestroyImmediate(so); //todo should cache these and have a proper cleanup at end
            DestroyImmediate(ro);
        }

        sourceMeshes.IntersectWith(allResultMeshes);
        HashSet <Mesh> sourceMeshesThatAreUsedByResult = sourceMeshes;

        if (sourceMeshesThatAreUsedByResult.Count > 0)
        {
            foreach (Mesh m in sourceMeshesThatAreUsedByResult)
            {
                Debug.LogWarning("Mesh " + m + " is used by both the source and result prefabs. New meshes will be created.");
            }
            //return;
        }

        List <UnityTransform> unityTransforms = new List <UnityTransform>();

        // Bake the meshes using the meshBaker component one prefab at a time
        for (int prefabIdx = 0; prefabIdx < pb.prefabRows.Length; prefabIdx++)
        {
            if (doReplaceTargetPrefab)
            {
                ProcessPrefabRowReplaceTargetPrefab(pb, pb.prefabRows[prefabIdx], tbr, unityTransforms, mb);
            }
            else
            {
                ProcessPrefabRowOnlyMeshesAndMaterials(pb, pb.prefabRows[prefabIdx], tbr, unityTransforms, mb);
            }
        }
        AssetDatabase.Refresh();
        mb.ClearMesh();
    }
 public virtual void meshAssign_UV0(int channel, MB_IMeshBakerSettings settings, MB2_TextureBakeResults textureBakeResults, Mesh mesh, Vector2[] uvs, float[] sliceIndexes)
 {
     mesh.uv = uvs;
 }
Esempio n. 30
0
    /// <summary>
    /// Creates for materials on renderer.
    /// </summary>
    /// <returns>Generates an MB2_TextureBakeResult that can be used if all objects to be combined use the same material.
    /// Returns a MB2_TextureBakeResults that will map all materials used by renderer r to
    /// the rectangle 0,0..1,1 in the atlas.</returns>
    /// <param name="r">The red component.</param>
    public static MB2_TextureBakeResults CreateForMaterialsOnRenderer(GameObject[] gos, List <Material> matsOnTargetRenderer)
    {
        HashSet <Material> fullMaterialList = new HashSet <Material>(matsOnTargetRenderer);

        for (int i = 0; i < gos.Length; i++)
        {
            if (gos[i] == null)
            {
                Debug.LogError(string.Format("Game object {0} in list of objects to add was null", i));
                return(null);
            }
            Material[] oMats = MB_Utility.GetGOMaterials(gos[i]);
            if (oMats.Length == 0)
            {
                Debug.LogError(string.Format("Game object {0} in list of objects to add no renderer", i));
                return(null);
            }
            for (int j = 0; j < oMats.Length; j++)
            {
                if (!fullMaterialList.Contains(oMats[j]))
                {
                    fullMaterialList.Add(oMats[j]);
                }
            }
        }
        Material[] rms = new Material[fullMaterialList.Count];
        fullMaterialList.CopyTo(rms);

        MB2_TextureBakeResults tbr = (MB2_TextureBakeResults)ScriptableObject.CreateInstance(typeof(MB2_TextureBakeResults));
        //Material[] ms = rms;
        //MB_MaterialAndUVRect[] mss = new MB_MaterialAndUVRect[rms.Length];
        List <MB_MaterialAndUVRect> mss = new List <MB_MaterialAndUVRect>();

        Material[] ms;
        for (int i = 0; i < rms.Length; i++)
        {
            if (rms[i] != null)
            {
                MB_MaterialAndUVRect matAndUVRect = new MB_MaterialAndUVRect(rms[i], new Rect(0f, 0f, 1f, 1f), new Rect(0f, 0f, 1f, 1f), new Rect(0f, 0f, 1f, 1f), new Rect(0f, 0f, 1f, 1f), "");
                if (!mss.Contains(matAndUVRect))
                {
                    mss.Add(matAndUVRect);
                }
            }
        }

        tbr.materials       = ms = new Material[mss.Count];
        tbr.resultMaterials = new MB_MultiMaterial[mss.Count];
        for (int i = 0; i < mss.Count; i++)
        {
            ms[i] = mss[i].material;
            tbr.resultMaterials[i] = new MB_MultiMaterial();
            List <Material> sourceMats = new List <Material>();
            sourceMats.Add(mss[i].material);
            tbr.resultMaterials[i].sourceMaterials  = sourceMats;
            tbr.resultMaterials[i].combinedMaterial = ms[i];
            tbr.resultMaterials[i].considerMeshUVs  = false;
        }
        if (rms.Length == 1)
        {
            tbr.doMultiMaterial = false;
        }
        else
        {
            tbr.doMultiMaterial = true;
        }

        tbr.materialsAndUVRects = mss.ToArray();
        //tbr.fixOutOfBoundsUVs = false;
        return(tbr);
    }
    public static bool BakeIntoCombined(MB3_MeshBakerCommon mom, out bool createdDummyTextureBakeResults)
    {
		MB2_OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;
        createdDummyTextureBakeResults = false;
        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.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)
                {
                    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."); }
            }
        }
        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( UnwrapUV2 );
            if (createdDummyTextureBakeResults)
            {
                Debug.Log(String.Format("Successfully baked {0} meshes each material is mapped to its own submesh.", mom.GetObjectsToCombine().Count));
            } else
            {
                Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count));
            }

            
			if (prefabOrSceneObject == 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;
	}
 public virtual void meshAssign_colors(MB_IMeshBakerSettings settings, MB2_TextureBakeResults textureBakeResults, Mesh mesh, Color[] colors, float[] sliceIndexes)
 {
     mesh.colors = colors;
 }
        public virtual void meshAssign_UV8(int channel, MB_IMeshBakerSettings settings, MB2_TextureBakeResults textureBakeResults, Mesh mesh, Vector2[] uvs, float[] sliceIndexes)
        {
#if UNITY_2018_2_OR_NEWER
            mesh.uv8 = uvs;
#endif
        }