public void PopulatePrefabRowsFromTextureBaker(MB3_BatchPrefabBaker prefabBaker)
    {
        Undo.RecordObject(prefabBaker, "Populate prefab rows");
        MB3_TextureBaker  texBaker = prefabBaker.GetComponent <MB3_TextureBaker>();
        List <GameObject> prefabs  = new List <GameObject>();
        List <GameObject> gos      = texBaker.GetObjectsToCombine();

        for (int i = 0; i < gos.Count; i++)
        {
            GameObject         go  = (GameObject)PrefabUtility.FindPrefabRoot(gos[i]);
            UnityEngine.Object obj = MBVersionEditor.PrefabUtility_GetCorrespondingObjectFromSource(go);

            if (obj != null && obj is GameObject)
            {
                if (!prefabs.Contains((GameObject)obj))
                {
                    prefabs.Add((GameObject)obj);
                }
            }
            else
            {
                Debug.LogWarning(String.Format("Object {0} did not have a prefab", gos[i]));
            }
        }
        List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow> newRows = new List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow>();

        for (int i = 0; i < prefabs.Count; i++)
        {
            MB3_BatchPrefabBaker.MB3_PrefabBakerRow row = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow();
            row.sourcePrefab = prefabs[i];
            newRows.Add(row);
        }
        prefabBaker.prefabRows = newRows.ToArray();
    }
    public void DoClustering(MB3_TextureBaker tb)
    {
        if (this.clusterGrouper == null)
        {
            Debug.LogError("Cluster Grouper was null.");
            return;
        }
        Dictionary <string, List <Renderer> > dictionary = this.clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine());

        Debug.Log("Found " + dictionary.Count + " cells with Renderers. Creating bakers.");
        if (this.clusterOnLMIndex)
        {
            Dictionary <string, List <Renderer> > dictionary2 = new Dictionary <string, List <Renderer> >();
            foreach (string text in dictionary.Keys)
            {
                List <Renderer> gaws = dictionary[text];
                Dictionary <int, List <Renderer> > dictionary3 = this.GroupByLightmapIndex(gaws);
                foreach (int num in dictionary3.Keys)
                {
                    string key = text + "-LM-" + num;
                    dictionary2.Add(key, dictionary3[num]);
                }
            }
            dictionary = dictionary2;
        }
        foreach (string key2 in dictionary.Keys)
        {
            List <Renderer> gaws2 = dictionary[key2];
            this.AddMeshBaker(tb, key2, gaws2);
        }
    }
Example #3
0
        public static void CreateNewTextureBaker()
        {
            MB3_TextureBaker[] mbs = (MB3_TextureBaker[])Editor.FindObjectsOfType(typeof(MB3_TextureBaker));
            Regex regex            = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
            int   largest          = 0;

            try{
                for (int i = 0; i < mbs.Length; i++)
                {
                    Match match = regex.Match(mbs[i].name);
                    if (match.Success)
                    {
                        int val = Convert.ToInt32(match.Groups[1].Value);
                        if (val >= largest)
                        {
                            largest = val + 1;
                        }
                    }
                }
            } catch (Exception e) {
                if (e == null)
                {
                    e = null;                            //Do nothing supress compiler warning
                }
            }
            GameObject nmb = new GameObject("TextureBaker (" + largest + ")");

            nmb.transform.position = Vector3.zero;
            nmb.AddComponent <MB3_MeshBakerGrouper>();
            MB3_TextureBaker tb = nmb.AddComponent <MB3_TextureBaker>();

            tb.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
        }
 public MB3_MeshBakerGrouperCore CreateGrouper(ClusterType t, GrouperData data)
 {
     if (t == ClusterType.grid)
     {
         grouper = new MB3_MeshBakerGrouperGrid(data);
     }
     if (t == ClusterType.pie)
     {
         grouper = new MB3_MeshBakerGrouperPie(data);
     }
     if (t == ClusterType.agglomerative)
     {
         MB3_TextureBaker  tb = GetComponent <MB3_TextureBaker>();
         List <GameObject> gos;
         if (tb != null)
         {
             gos = tb.GetObjectsToCombine();
         }
         else
         {
             gos = new List <GameObject>();
         }
         grouper = new MB3_MeshBakerGrouperCluster(data, gos);
     }
     if (t == ClusterType.none)
     {
         grouper = new MB3_MeshBakerGrouperNone(data);
     }
     return(grouper);
 }
        void AddMeshBaker(MB3_TextureBaker tb, string key, List <Renderer> gaws)
        {
            int numVerts = 0;

            for (int i = 0; i < gaws.Count; i++)
            {
                Mesh m = MB_Utility.GetMesh(gaws[i].gameObject);
                if (m != null)
                {
                    numVerts += m.vertexCount;
                }
            }

            GameObject nmb = new GameObject("MeshBaker-" + key);

            nmb.transform.position = Vector3.zero;
            MB3_MeshBakerCommon newMeshBaker;

            if (numVerts >= 65535)
            {
                newMeshBaker = nmb.AddComponent <MB3_MultiMeshBaker>();
                newMeshBaker.useObjsToMeshFromTexBaker = false;
            }
            else
            {
                newMeshBaker = nmb.AddComponent <MB3_MeshBaker>();
                newMeshBaker.useObjsToMeshFromTexBaker = false;
            }
            newMeshBaker.textureBakeResults = tb.textureBakeResults;
            newMeshBaker.transform.parent   = tb.transform;
            for (int i = 0; i < gaws.Count; i++)
            {
                newMeshBaker.GetObjectsToCombine().Add(gaws[i].gameObject);
            }
        }
Example #6
0
    public void DoClustering(MB3_TextureBaker tb)
    {
        if (clusterGrouper == null)
        {
            Debug.LogError("Cluster Grouper was null.");
            return;
        }

        //todo warn for no objects and no material bake result
        Dictionary <string, List <Renderer> > cell2objs = clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine());

        Debug.Log("Found " + cell2objs.Count + " cells with Renderers. Creating bakers.");
        if (clusterOnLMIndex)
        {
            Dictionary <string, List <Renderer> > cell2objsNew = new Dictionary <string, List <Renderer> >();
            foreach (string key in cell2objs.Keys)
            {
                List <Renderer> gaws = cell2objs[key];
                Dictionary <int, List <Renderer> > idx2objs = GroupByLightmapIndex(gaws);
                foreach (int keyIdx in idx2objs.Keys)
                {
                    string keyNew = key + "-LM-" + keyIdx;
                    cell2objsNew.Add(keyNew, idx2objs[keyIdx]);
                }
            }
            cell2objs = cell2objsNew;
        }
        foreach (string key in cell2objs.Keys)
        {
            List <Renderer> gaws = cell2objs[key];
            AddMeshBaker(tb, key, gaws);
        }
    }
    private void AddMeshBaker(MB3_TextureBaker tb, string key, List <Renderer> gaws)
    {
        int num = 0;

        for (int i = 0; i < gaws.Count; i++)
        {
            Mesh mesh = MB_Utility.GetMesh(gaws[i].gameObject);
            if (mesh != null)
            {
                num += mesh.vertexCount;
            }
        }
        GameObject gameObject = new GameObject("MeshBaker-" + key);

        gameObject.transform.position = Vector3.zero;
        MB3_MeshBakerCommon mb3_MeshBakerCommon;

        if (num >= 65535)
        {
            mb3_MeshBakerCommon = gameObject.AddComponent <MB3_MultiMeshBaker>();
            mb3_MeshBakerCommon.useObjsToMeshFromTexBaker = false;
        }
        else
        {
            mb3_MeshBakerCommon = gameObject.AddComponent <MB3_MeshBaker>();
            mb3_MeshBakerCommon.useObjsToMeshFromTexBaker = false;
        }
        mb3_MeshBakerCommon.textureBakeResults = tb.textureBakeResults;
        mb3_MeshBakerCommon.transform.parent   = tb.transform;
        for (int j = 0; j < gaws.Count; j++)
        {
            mb3_MeshBakerCommon.GetObjectsToCombine().Add(gaws[j].gameObject);
        }
    }
    /// <summary>
    /// </summary>
    /// <param name="path">
    /// path[0] meshbaker生成器资源路径
    /// path[1] meshbaker材质资源路径
    /// path[2] meshbaker贴图资源路径
    /// path[3] meshbaker合并对象资源路径
    /// </param>
    /// <param name="type"></param>
    /// <param name="count"></param>
    public CharObjCreator(string[] paths, BattleObjManager.E_BATTLE_OBJECT_TYPE type, int count)
    {
        bool retCode = false;

        m_meshbakerGo = ResourcesManagerMediator.
                        GetGameObjectFromResourcesManager(paths[0]);
        if (m_meshbakerGo == null)
        {
            Debug.LogError("加载baker生成器资源出错" + paths[0]);
            return;
        }

        MB3_TextureBaker textureBaker = m_meshbakerGo.GetComponent <MB3_TextureBaker>();

        m_meshBaker = m_meshbakerGo.GetComponentInChildren <MB3_MeshBaker>();

        retCode = InitBaker(paths, textureBaker, m_meshBaker);
        if (!retCode)
        {
            Debug.LogError("MeshBaker初始化失败");
            return;
        }

        m_seed = ResourcesManagerMediator.GetGameObjectFromResourcesManager(paths[3]);
        if (m_seed == null)
        {
            Debug.LogError("加载种子资源失败 " + paths[3]);
            return;
        }
        m_seed.transform.position = INIT_POS;

        m_count = count;
    }
    void OnGUI()
    {
        GUILayout.Label("Time to bake textures: " + elapsedTime);
        if (GUILayout.Button("Combine textures & build combined mesh"))
        {
            MB3_MeshBaker    meshbaker    = target.GetComponent <MB3_MeshBaker>();
            MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>();

            //These can be assets configured at runtime or you can create them
            // on the fly like this
            textureBaker.textureBakeResults = ScriptableObject.CreateInstance <MB2_TextureBakeResults>();
            textureBaker.resultMaterial     = new Material(Shader.Find("Diffuse"));

            float t1 = Time.realtimeSinceStartup;
            textureBaker.CreateAtlases();
            elapsedTime = Time.realtimeSinceStartup - t1;

            meshbaker.ClearMesh();             //only necessary if your not sure whats in the combined mesh
            meshbaker.textureBakeResults = textureBaker.textureBakeResults;
            //Add the objects to the combined mesh
            meshbaker.AddDeleteGameObjects(textureBaker.GetObjectsToCombine().ToArray(), null);

            meshbaker.Apply();
        }
    }
    private bool InitBaker(string[] paths, MB3_TextureBaker textureBaker, MB3_MeshBaker meshBaker)
    {
        bool result = false;

        Material material = ResourcesManagerMediator.
                            GetNoGameObjectFromResourcesManager <Material>(paths[1]);

        if (material == null)
        {
            Debug.LogError("加载合并材质资源失败" + paths[1]);
            return(result);
        }

        MB2_TextureBakeResults textureBakeResults = ResourcesManagerMediator.
                                                    GetNoGameObjectFromResourcesManager <MB2_TextureBakeResults>(paths[2]);

        if (textureBakeResults == null)
        {
            Debug.LogError("加载MB2_TextureBakeResults资源失败" + paths[2]);
            return(result);
        }

        textureBaker.resultMaterial     = material;
        textureBaker.textureBakeResults = textureBakeResults;
        meshBaker.textureBakeResults    = textureBakeResults;

        result = true;
        return(result);
    }
 public void BuildAllSource(MB3_TextureBaker mom)
 {
     SerializedObject tbr = new SerializedObject(mom);
     SerializedProperty resultMaterials = tbr.FindProperty("resultMaterials");
     MB3_TextureBakerEditorInternal.ConfigureMutiMaterialsFromObjsToCombine (mom,resultMaterials,tbr);
     tbr.UpdateIfDirtyOrScript();
 }
        private static void _bakeAllChildMeshBakers(UnityEngine.Object target, ref SerializedObject grouper)
        {
            MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
            MB3_TextureBaker     tb  = tbg.GetComponent <MB3_TextureBaker>();

            try
            {
                MB3_MeshBakerCommon[] mBakers = tbg.GetComponentsInChildren <MB3_MeshBakerCommon>();
                for (int i = 0; i < mBakers.Length; i++)
                {
                    bool createdDummyMaterialBakeResult;
                    if (grouper.targetObject == tbg)
                    {
                        MB3_MeshBakerEditorFunctions.BakeIntoCombined(mBakers[i], out createdDummyMaterialBakeResult, ref grouper);
                    }
                    else
                    {
                        MB3_MeshBakerEditorFunctions.BakeIntoCombined(mBakers[i], out createdDummyMaterialBakeResult);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
        }
Example #13
0
 public override List <GameObject> GetObjectsToCombine()
 {
     if (useObjsToMeshFromTexBaker)
     {
         MB3_TextureBaker tb = gameObject.GetComponent <MB3_TextureBaker>();
         if (tb == null)
         {
             tb = gameObject.transform.parent.GetComponent <MB3_TextureBaker>();
         }
         if (tb != null)
         {
             return(tb.GetObjectsToCombine());
         }
         else
         {
             Debug.LogWarning("Use Objects To Mesh From Texture Baker was checked but no texture baker");
             return(new List <GameObject>());
         }
     }
     else
     {
         if (objsToMesh == null)
         {
             objsToMesh = new List <GameObject>();
         }
         return(objsToMesh);
     }
 }
        public static void CreateCombinedMaterialAssets(MB3_TextureBaker target, string pth)
        {
            MB3_TextureBaker mom      = (MB3_TextureBaker)target;
            string           baseName = Path.GetFileNameWithoutExtension(pth);

            if (baseName == null || baseName.Length == 0)
            {
                return;
            }
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);

            List <string> matNames = new List <string>();

            if (mom.doMultiMaterial)
            {
                for (int i = 0; i < mom.resultMaterials.Length; i++)
                {
                    matNames.Add(folderPath + baseName + "-mat" + i + ".mat");
                    AssetDatabase.CreateAsset(new Material(Shader.Find("Diffuse")), matNames[i]);
                    mom.resultMaterials[i].combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matNames[i], typeof(Material));
                }
            }
            else
            {
                matNames.Add(folderPath + baseName + "-mat.mat");
                Material newMat = null;
                if (mom.GetObjectsToCombine().Count > 0 && mom.GetObjectsToCombine()[0] != null)
                {
                    Renderer r = mom.GetObjectsToCombine()[0].GetComponent <Renderer>();
                    if (r == null)
                    {
                        Debug.LogWarning("Object " + mom.GetObjectsToCombine()[0] + " does not have a Renderer on it.");
                    }
                    else
                    {
                        if (r.sharedMaterial != null)
                        {
                            newMat = new Material(r.sharedMaterial);
                            //newMat.shader = r.sharedMaterial.shader;
                            MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, r.sharedMaterial);
                        }
                    }
                }
                else
                {
                    Debug.Log("If you add objects to be combined before creating the Combined Material Assets. Then Mesh Baker will create a result material that is a duplicate of the material on the first object to be combined. This saves time configuring the shader.");
                }
                if (newMat == null)
                {
                    newMat = new Material(Shader.Find("Diffuse"));
                }
                AssetDatabase.CreateAsset(newMat, matNames[0]);
                mom.resultMaterial = (Material)AssetDatabase.LoadAssetAtPath(matNames[0], typeof(Material));
            }
            //create the MB2_TextureBakeResults
            AssetDatabase.CreateAsset(ScriptableObject.CreateInstance <MB2_TextureBakeResults>(), pth);
            mom.textureBakeResults = (MB2_TextureBakeResults)AssetDatabase.LoadAssetAtPath(pth, typeof(MB2_TextureBakeResults));
            AssetDatabase.Refresh();
        }
Example #15
0
    public void BuildAllSource(MB3_TextureBaker mom)
    {
        SerializedObject   tbr             = new SerializedObject(mom);
        SerializedProperty resultMaterials = tbr.FindProperty("resultMaterials");

        MB3_TextureBakerEditorInternal.ConfigureMutiMaterialsFromObjsToCombine(mom, resultMaterials, tbr);
        tbr.UpdateIfDirtyOrScript();
    }
Example #16
0
 void bakeAllBakersInScene()
 {
     MB3_MeshBakerRoot[] bakers = (MB3_MeshBakerRoot[])FindObjectsOfType(typeof(MB3_MeshBakerRoot));
     for (int i = 0; i < bakers.Length; i++)
     {
         if (bakers[i] is MB3_TextureBaker)
         {
             MB3_TextureBaker tb = (MB3_TextureBaker)bakers[i];
             tb.CreateAtlases(updateProgressBar, true, new MB3_EditorMethods());
         }
     }
     EditorUtility.ClearProgressBar();
 }
Example #17
0
    /// <summary>
    /// Gets the texture baker on this component or its parent if it exists
    /// </summary>
    /// <returns>The texture baker.</returns>
    public MB3_TextureBaker GetTextureBaker()
    {
        MB3_TextureBaker tb = GetComponent <MB3_TextureBaker>();

        if (tb != null)
        {
            return(tb);
        }
        if (transform.parent != null)
        {
            return(transform.parent.GetComponent <MB3_TextureBaker>());
        }
        return(null);
    }
Example #18
0
    public MB3_TextureBaker GetTextureBaker()
    {
        MB3_TextureBaker component = base.GetComponent <MB3_TextureBaker>();

        if (component != null)
        {
            return(component);
        }
        if (base.transform.parent != null)
        {
            return(base.transform.parent.GetComponent <MB3_TextureBaker>());
        }
        return(null);
    }
 void _init(MB3_TextureBaker target)
 {
     textureBaker             = new SerializedObject(target);
     doMultiMaterial          = textureBaker.FindProperty("_doMultiMaterial");
     fixOutOfBoundsUVs        = textureBaker.FindProperty("_fixOutOfBoundsUVs");
     resultMaterial           = textureBaker.FindProperty("_resultMaterial");
     resultMaterials          = textureBaker.FindProperty("resultMaterials");
     atlasPadding             = textureBaker.FindProperty("_atlasPadding");
     resizePowerOfTwoTextures = textureBaker.FindProperty("_resizePowerOfTwoTextures");
     customShaderPropNames    = textureBaker.FindProperty("_customShaderPropNames");
     objsToMesh              = textureBaker.FindProperty("objsToMesh");
     maxTilingBakeSize       = textureBaker.FindProperty("_maxTilingBakeSize");
     textureBakeResults      = textureBaker.FindProperty("_textureBakeResults");
     texturePackingAlgorithm = textureBaker.FindProperty("_packingAlgorithm");
 }
		void _init(MB3_TextureBaker target) {
			textureBaker = new SerializedObject(target);
			doMultiMaterial = textureBaker.FindProperty("_doMultiMaterial");
			fixOutOfBoundsUVs = textureBaker.FindProperty("_fixOutOfBoundsUVs");
			resultMaterial = textureBaker.FindProperty("_resultMaterial");
			resultMaterials = textureBaker.FindProperty("resultMaterials");
			atlasPadding = textureBaker.FindProperty("_atlasPadding");
			resizePowerOfTwoTextures = textureBaker.FindProperty("_resizePowerOfTwoTextures");
			customShaderProperties= textureBaker.FindProperty("_customShaderProperties");
			objsToMesh = textureBaker.FindProperty("objsToMesh");
			maxTilingBakeSize = textureBaker.FindProperty("_maxTilingBakeSize");
			maxAtlasSize = textureBaker.FindProperty("_maxAtlasSize");
			textureBakeResults = textureBaker.FindProperty("_textureBakeResults");
			texturePackingAlgorithm = textureBaker.FindProperty("_packingAlgorithm");
			forcePowerOfTwoAtlas = textureBaker.FindProperty("_meshBakerTexturePackerForcePowerOfTwo");
		}	
    void OnBuiltAtlasesSuccess()
    {
        Debug.Log("Calling success callback. baking meshes");
        MB3_MeshBaker    meshbaker    = target.GetComponentInChildren <MB3_MeshBaker>();
        MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>();

        //elapsedTime = Time.realtimeSinceStartup - t1;

        if (result.isFinished &&
            result.success)
        {
            meshbaker.ClearMesh(); //only necessary if your not sure whats in the combined mesh
            meshbaker.textureBakeResults = textureBaker.textureBakeResults;
            //Add the objects to the combined mesh
            meshbaker.AddDeleteGameObjects(textureBaker.GetObjectsToCombine().ToArray(), null, true);
            meshbaker.Apply();
        }
        Debug.Log("Completed baking textures on frame " + Time.frameCount);
    }
        public static GameObject CreateNewMeshBaker()
        {
            MB3_TextureBaker[] mbs = (MB3_TextureBaker[])GameObject.FindObjectsOfType(typeof(MB3_TextureBaker));
            Regex regex            = new Regex(@"\((\d+)\)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
            int   largest          = 0;

            try
            {
                for (int i = 0; i < mbs.Length; i++)
                {
                    Match match = regex.Match(mbs[i].name);
                    if (match.Success)
                    {
                        int val = Convert.ToInt32(match.Groups[1].Value);
                        if (val >= largest)
                        {
                            largest = val + 1;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex == null)
                {
                    ex = null;             //Do nothing supress compiler warning
                }
            }
            GameObject nmb = new GameObject("TextureBaker (" + largest + ")");

            nmb.transform.position = Vector3.zero;
            MB3_TextureBaker tb = nmb.AddComponent <MB3_TextureBaker>();

            tb.packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
            MB3_MeshBakerGrouper mbg       = nmb.AddComponent <MB3_MeshBakerGrouper>();
            GameObject           meshBaker = new GameObject("MultiMeshBaker");
            MB3_MultiMeshBaker   mmb       = meshBaker.AddComponent <MB3_MultiMeshBaker>();

            mmb.meshCombiner.settingsHolder = mbg;
            meshBaker.transform.parent      = nmb.transform;

            return(nmb);
        }
    void OnGUI()
    {
        GUILayout.Label("Time to bake textures: " + elapsedTime);
        if (GUILayout.Button("Combine textures & build combined mesh all at once"))
        {
            MB3_MeshBaker    meshbaker    = target.GetComponentInChildren <MB3_MeshBaker>();
            MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>();

            //These can be assets configured at runtime or you can create them
            // on the fly like this
            textureBaker.textureBakeResults = ScriptableObject.CreateInstance <MB2_TextureBakeResults>();
            textureBaker.resultMaterial     = new Material(Shader.Find(GetShaderNameForPipeline()));

            float t1 = Time.realtimeSinceStartup;
            textureBaker.CreateAtlases();
            elapsedTime = Time.realtimeSinceStartup - t1;

            meshbaker.ClearMesh();             //only necessary if your not sure whats in the combined mesh
            meshbaker.textureBakeResults = textureBaker.textureBakeResults;

            //Add the objects to the combined mesh
            meshbaker.AddDeleteGameObjects(textureBaker.GetObjectsToCombine().ToArray(), null, true);

            meshbaker.Apply();
        }

        if (GUILayout.Button("Combine textures & build combined mesh using coroutine"))
        {
            Debug.Log("Starting to bake textures on frame " + Time.frameCount);
            MB3_TextureBaker textureBaker = target.GetComponent <MB3_TextureBaker>();

            //These can be assets configured at runtime or you can create them
            // on the fly like this
            textureBaker.textureBakeResults = ScriptableObject.CreateInstance <MB2_TextureBakeResults>();
            textureBaker.resultMaterial     = new Material(Shader.Find(GetShaderNameForPipeline()));

            //register an OnSuccess function to be called when texture baking is complete
            textureBaker.onBuiltAtlasesSuccess = new MB3_TextureBaker.OnCombinedTexturesCoroutineSuccess(OnBuiltAtlasesSuccess);
            StartCoroutine(textureBaker.CreateAtlasesCoroutine(null, result, false, null, .01f));
        }
    }
        private static void _enableDisableRenderers(UnityEngine.Object target, bool enableRenderers)
        {
            MB3_MeshBakerGrouper tbg = (MB3_MeshBakerGrouper)target;
            MB3_TextureBaker     tb  = tbg.GetComponent <MB3_TextureBaker>();

            try
            {
                MB3_MeshBakerCommon[] mBakers = tbg.GetComponentsInChildren <MB3_MeshBakerCommon>();
                for (int i = 0; i < mBakers.Length; i++)
                {
                    mBakers[i].EnableDisableSourceObjectRenderers(enableRenderers);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
        }
Example #25
0
    public override List <GameObject> GetObjectsToCombine()
    {
        if (!this.useObjsToMeshFromTexBaker)
        {
            if (this.objsToMesh == null)
            {
                this.objsToMesh = new List <GameObject>();
            }
            return(this.objsToMesh);
        }
        MB3_TextureBaker component = base.gameObject.GetComponent <MB3_TextureBaker>();

        if (component == null)
        {
            component = base.gameObject.transform.parent.GetComponent <MB3_TextureBaker>();
        }
        if (component != null)
        {
            return(component.GetObjectsToCombine());
        }
        Debug.LogWarning("Use Objects To Mesh From Texture Baker was checked but no texture baker");
        return(new List <GameObject>());
    }
Example #26
0
    public static void MigrateTestureBakerToVersion3Component(GameObject go)
    {
        MB2_TextureBaker tb2 = go.GetComponent <MB2_TextureBaker>();

        if (tb2 == null)
        {
            return;
        }
        Debug.Log("Migrating Texture Baker");
        MB3_TextureBaker tb3 = go.AddComponent <MB3_TextureBaker>();

        tb3.atlasPadding      = tb2.atlasPadding;
        tb3.doMultiMaterial   = tb2.doMultiMaterial;
        tb3.fixOutOfBoundsUVs = tb2.fixOutOfBoundsUVs;
        tb3.maxTilingBakeSize = tb2.maxTilingBakeSize;

        tb3.objsToMesh               = tb2.objsToMesh;
        tb3.packingAlgorithm         = tb2.texturePackingAlgorithm;
        tb3.resizePowerOfTwoTextures = tb2.resizePowerOfTwoTextures;
        tb3.resultMaterial           = tb2.resultMaterial;
        tb3.resultMaterials          = tb2.resultMaterials;
        tb3.textureBakeResults       = tb2.textureBakeResults;
        DestroyImmediate(tb2);
    }
Example #27
0
    void drawTabAddObjectsToBakers()
    {
        if (helpBoxString == null)
        {
            helpBoxString = "";
        }
        EditorGUILayout.HelpBox("To add, select one or more objects in the hierarchy view. Child Game Objects with MeshRender or SkinnedMeshRenderer will be added. Use the fields below to filter what is added." +
                                "To remove, use the fields below to filter what is removed.\n" + helpBoxString, UnityEditor.MessageType.None);
        target = (MB3_MeshBakerRoot)EditorGUILayout.ObjectField("Target to add objects to", target, typeof(MB3_MeshBakerRoot), true);

        if (target != null)
        {
            targetGO = target.gameObject;
        }
        else
        {
            targetGO = null;
        }

        if (targetGO != oldTargetGO && targetGO != null)
        {
            textureBaker = targetGO.GetComponent <MB3_TextureBaker>();
            meshBaker    = targetGO.GetComponent <MB3_MeshBaker>();
            tbe          = new MB3_TextureBakerEditorInternal();
            mbe          = new MB3_MeshBakerEditorInternal();
            oldTargetGO  = targetGO;
            if (textureBaker != null)
            {
                serializedObject = new SerializedObject(textureBaker);
                tbe.OnEnable(serializedObject);
            }
            else if (meshBaker != null)
            {
                serializedObject = new SerializedObject(meshBaker);
                mbe.OnEnable(serializedObject);
            }
        }


        EditorGUIUtility.labelWidth = 300;
        onlyStaticObjects           = EditorGUILayout.Toggle("Only Static Objects", onlyStaticObjects);

        onlyEnabledObjects = EditorGUILayout.Toggle("Only Enabled Objects", onlyEnabledObjects);

        excludeMeshesWithOBuvs = EditorGUILayout.Toggle("Exclude meshes with out-of-bounds UVs", excludeMeshesWithOBuvs);

        excludeMeshesAlreadyAddedToBakers = EditorGUILayout.Toggle("Exclude GameObjects already added to bakers", excludeMeshesAlreadyAddedToBakers);

        mat       = (Material)EditorGUILayout.ObjectField("Using Material", mat, typeof(Material), true);
        shaderMat = (Material)EditorGUILayout.ObjectField("Using Shader", shaderMat, typeof(Material), true);

        string[] lightmapDisplayValues = new string[257];
        int[]    lightmapValues        = new int[257];
        lightmapValues[0]        = -2;
        lightmapValues[1]        = -1;
        lightmapDisplayValues[0] = "don't filter on lightmapping";
        lightmapDisplayValues[1] = "not lightmapped";
        for (int i = 2; i < lightmapDisplayValues.Length; i++)
        {
            lightmapDisplayValues[i] = "" + i;
            lightmapValues[i]        = i;
        }
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Using Lightmap Index ");
        lightmapIndex = EditorGUILayout.IntPopup(lightmapIndex,
                                                 lightmapDisplayValues,
                                                 lightmapValues);
        EditorGUILayout.EndHorizontal();
        if (regExParseError != null && regExParseError.Length > 0)
        {
            EditorGUILayout.HelpBox("Error In Regular Expression:\n" + regExParseError, MessageType.Error);
        }
        searchRegEx = EditorGUILayout.TextField(GUIContentRegExpression, searchRegEx);


        EditorGUILayout.Separator();

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Add Selected Meshes To Target"))
        {
            addSelectedObjects();
        }
        if (GUILayout.Button("Remove Matching Meshes From Target"))
        {
            removeSelectedObjects();
        }
        EditorGUILayout.EndHorizontal();

        if (textureBaker != null)
        {
            MB_EditorUtil.DrawSeparator();
            tbFoldout = EditorGUILayout.Foldout(tbFoldout, "Texture Baker");
            if (tbFoldout)
            {
                tbe.DrawGUI(serializedObject, (MB3_TextureBaker)textureBaker, typeof(MB3_MeshBakerEditorWindow));
            }
        }
        if (meshBaker != null)
        {
            MB_EditorUtil.DrawSeparator();
            mbFoldout = EditorGUILayout.Foldout(mbFoldout, "Mesh Baker");
            if (mbFoldout)
            {
                mbe.DrawGUI(serializedObject, (MB3_MeshBaker)meshBaker, typeof(MB3_MeshBakerEditorWindow));
            }
        }
    }
	void drawTabAddObjectsToBakers(){
		EditorGUILayout.HelpBox("Select one or more objects in the hierarchy view. Child Game Objects with MeshRender will be added. Use the fields below to filter what is added.", UnityEditor.MessageType.None);
		target = (MB3_MeshBakerRoot) EditorGUILayout.ObjectField("Target to add objects to",target,typeof(MB3_MeshBakerRoot),true);
		
		if (target != null){
			targetGO = target.gameObject;
		} else {
			targetGO = null;	
		}
		
		if (targetGO != oldTargetGO && targetGO != null){
			textureBaker = targetGO.GetComponent<MB3_TextureBaker>();
			meshBaker = targetGO.GetComponent<MB3_MeshBaker>();
			tbe = new MB3_TextureBakerEditorInternal();
			mbe = new MB3_MeshBakerEditorInternal();
			oldTargetGO = targetGO;
		}

		EditorGUIUtility.labelWidth = 300;
		onlyStaticObjects = EditorGUILayout.Toggle("Only Static Objects", onlyStaticObjects);
		
		onlyEnabledObjects = EditorGUILayout.Toggle("Only Enabled Objects", onlyEnabledObjects);
		
		excludeMeshesWithOBuvs = EditorGUILayout.Toggle("Exclude meshes with out-of-bounds UVs", excludeMeshesWithOBuvs);

		excludeMeshesAlreadyAddedToBakers = EditorGUILayout.Toggle("Exclude GameObjects already added to bakers", excludeMeshesAlreadyAddedToBakers);

		mat = (Material) EditorGUILayout.ObjectField("Using Material",mat,typeof(Material),true);
		shaderMat = (Material) EditorGUILayout.ObjectField("Using Shader",shaderMat,typeof(Material),true);
		
		string[] lightmapDisplayValues = new string[257];
		int[] lightmapValues = new int[257];
		lightmapValues[0] = -2;
		lightmapValues[1] = -1;
		lightmapDisplayValues[0] = "don't filter on lightmapping";
		lightmapDisplayValues[1] = "not lightmapped";
		for (int i = 2; i < lightmapDisplayValues.Length; i++){
			lightmapDisplayValues[i] = "" + i;
			lightmapValues[i] = i;
		}
		EditorGUILayout.BeginHorizontal();
		EditorGUILayout.LabelField("Using Lightmap Index ");
		lightmapIndex = EditorGUILayout.IntPopup(lightmapIndex,
		                                         lightmapDisplayValues,
		                                         lightmapValues);
		EditorGUILayout.EndHorizontal();
		EditorGUILayout.Separator();
		
		if (GUILayout.Button("Add Selected Meshes To Target")){
			addSelectedObjects();
		}
		
		if (textureBaker != null){
			MB_EditorUtil.DrawSeparator();
			tbFoldout = EditorGUILayout.Foldout(tbFoldout,"Texture Baker");
			if (tbFoldout){
				tbe.DrawGUI((MB3_TextureBaker) textureBaker, typeof(MB3_MeshBakerEditorWindow));
			}
			
		}
		if (meshBaker != null){
			MB_EditorUtil.DrawSeparator();
			mbFoldout = EditorGUILayout.Foldout(mbFoldout,"Mesh Baker");
			if (mbFoldout){
				mbe.DrawGUI((MB3_MeshBaker) meshBaker, typeof(MB3_MeshBakerEditorWindow));
			}
		}
	}
Example #29
0
    void createAndSetupBaker(List <GameObjectFilterInfo> gaws, string pthRoot)
    {
        for (int i = gaws.Count - 1; i >= 0; i--)
        {
            if (gaws[i].go == null)
            {
                gaws.RemoveAt(i);
            }
        }
        if (gaws.Count < 1)
        {
            Debug.LogError("No game objects.");
            return;
        }

        if (pthRoot == null || pthRoot == "")
        {
            Debug.LogError("Folder for saving created assets was not set.");
            return;
        }

        int numVerts = 0;

        for (int i = 0; i < gaws.Count; i++)
        {
            if (gaws[i].go != null)
            {
                numVerts = gaws[i].numVerts;
            }
        }

        GameObject newMeshBaker = null;

        if (numVerts >= 65535)
        {
            newMeshBaker = MB3_MultiMeshBakerEditor.CreateNewMeshBaker();
        }
        else
        {
            newMeshBaker = MB3_MeshBakerEditor.CreateNewMeshBaker();
        }

        newMeshBaker.name = ("MeshBaker-" + gaws[0].shaderName + "-LM" + gaws[0].lightmapIndex).ToString().Replace("/", "-");

        MB3_TextureBaker    tb = newMeshBaker.GetComponent <MB3_TextureBaker>();
        MB3_MeshBakerCommon mb = tb.GetComponentInChildren <MB3_MeshBakerCommon>();

        tb.GetObjectsToCombine().Clear();
        for (int i = 0; i < gaws.Count; i++)
        {
            if (gaws[i].go != null)
            {
                tb.GetObjectsToCombine().Add(gaws[i].go);
            }
        }

        if (gaws[0].numMaterials > 1)
        {
            string pthMat = AssetDatabase.GenerateUniqueAssetPath(pthRoot + newMeshBaker.name + ".asset");
            MB3_TextureBakerEditorInternal.CreateCombinedMaterialAssets(tb, pthMat);
            tb.doMultiMaterial = true;
            SerializedObject   tbr             = new SerializedObject(tb);
            SerializedProperty resultMaterials = tbr.FindProperty("resultMaterials");
            MB3_TextureBakerEditorInternal.ConfigureMutiMaterialsFromObjsToCombine(tb, resultMaterials, tbr);
        }
        else
        {
            string pthMat = AssetDatabase.GenerateUniqueAssetPath(pthRoot + newMeshBaker.name + ".asset");
            MB3_TextureBakerEditorInternal.CreateCombinedMaterialAssets(tb, pthMat);
        }
        if (gaws[0].isMeshRenderer)
        {
            mb.meshCombiner.renderType = MB_RenderType.meshRenderer;
        }
        else
        {
            mb.meshCombiner.renderType = MB_RenderType.skinnedMeshRenderer;
        }
    }
    /// <summary>
    ///  Bakes a combined mesh.
    /// </summary>
    /// <param name="so">If this is being called from Inspector code then pass in the SerializedObject for the component.
    /// This is necessary for "bake into prefab" which can corrupt the SerializedObject.</param>
    public static bool BakeIntoCombined(MB3_MeshBakerCommon mom, out bool createdDummyTextureBakeResults, ref SerializedObject so)
    {
        MB2_OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;

        createdDummyTextureBakeResults = false;

        // Initial Validate
        {
            if (mom.meshCombiner.resultSceneObject != null &&
                (MBVersionEditor.PrefabUtility_GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.modelPrefabAsset ||
                 MBVersionEditor.PrefabUtility_GetPrefabType(mom.meshCombiner.resultSceneObject) == MB_PrefabType.prefabAsset))
            {
                Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field.");
                mom.meshCombiner.resultSceneObject = null;
            }

            if (prefabOrSceneObject != MB2_OutputOptions.bakeIntoPrefab && prefabOrSceneObject != MB2_OutputOptions.bakeIntoSceneObject)
            {
                Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject");
                return(false);
            }

            if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
            {
                if (MB3_MeshCombiner.EVAL_VERSION)
                {
                    Debug.LogError("Cannot BakeIntoPrefab with evaluation version.");
                    return(false);
                }

                if (mom.resultPrefab == null)
                {
                    Debug.LogError("Need to set the Combined Mesh Prefab field. Create a prefab asset, drag an empty game object into it, and drag it to the 'Combined Mesh Prefab' field.");
                    return(false);
                }

                string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
                if (prefabPth == null || prefabPth.Length == 0)
                {
                    Debug.LogError("Could not save result to prefab. Result Prefab value is not a project asset. Is it an instance in the scene?");
                    return(false);
                }
            }
        }

        {
            // Find or create texture bake results
            MB3_TextureBaker tb = mom.GetComponentInParent <MB3_TextureBaker>();
            if (mom.textureBakeResults == null && tb != null)
            {
                mom.textureBakeResults = tb.textureBakeResults;
            }

            if (mom.textureBakeResults == null)
            {
                if (_OkToCreateDummyTextureBakeResult(mom))
                {
                    createdDummyTextureBakeResults = true;
                    List <GameObject> gos = mom.GetObjectsToCombine();
                    if (mom.GetNumObjectsInCombined() > 0)
                    {
                        if (mom.clearBuffersAfterBake)
                        {
                            mom.ClearMesh();
                        }
                        else
                        {
                            Debug.LogError("'Texture Bake Result' must be set to add more objects to a combined mesh that already contains objects. Try enabling 'clear buffers after bake'");
                            return(false);
                        }
                    }
                    mom.textureBakeResults = MB2_TextureBakeResults.CreateForMaterialsOnRenderer(gos.ToArray(), mom.meshCombiner.GetMaterialsOnTargetRenderer());
                    if (mom.meshCombiner.LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("'Texture Bake Result' was not set. Creating a temporary one. Each material will be mapped to a separate submesh.");
                    }
                }
            }
        }

        // Second level of validation now that TextureBakeResults exists.
        MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;

        if (!MB3_MeshBakerRoot.DoCombinedValidate(mom, MB_ObjsToCombineTypes.sceneObjOnly, new MB3_EditorMethods(), vl))
        {
            return(false);
        }

        // Add Delete Game Objects
        bool success;

        if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoSceneObject)
        {
            success = _BakeIntoCombinedSceneObject(mom, createdDummyTextureBakeResults, ref so);
        }
        else if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
        {
            success = _BakeIntoCombinedPrefab(mom, createdDummyTextureBakeResults, ref so);
        }
        else
        {
            Debug.LogError("Should be impossible.");
            success = false;
        }

        if (mom.clearBuffersAfterBake)
        {
            mom.meshCombiner.ClearBuffers();
        }
        if (createdDummyTextureBakeResults)
        {
            MB_Utility.Destroy(mom.textureBakeResults);
        }
        return(success);
    }
    public static bool BakeIntoCombined(MB3_MeshBakerCommon mom)
    {
        MB2_OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption;

        if (MB3_MeshCombiner.EVAL_VERSION && prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
        {
            Debug.LogError("Cannot BakeIntoPrefab with evaluation version.");
            return(false);
        }
        if (prefabOrSceneObject != MB2_OutputOptions.bakeIntoPrefab && prefabOrSceneObject != MB2_OutputOptions.bakeIntoSceneObject)
        {
            Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject");
            return(false);
        }

        MB3_TextureBaker tb = mom.GetComponent <MB3_TextureBaker>();

        if (mom.textureBakeResults == null && tb != null)
        {
            mom.textureBakeResults = tb.textureBakeResults;
        }
        MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust;

        if (!MB3_MeshBakerRoot.DoCombinedValidate(mom, MB_ObjsToCombineTypes.sceneObjOnly, new MB3_EditorMethods(), vl))
        {
            return(false);
        }
        if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab &&
            mom.resultPrefab == null)
        {
            Debug.LogError("Need to set the Combined Mesh Prefab field. Create a prefab asset, drag an empty game object into it, and drag it to the 'Combined Mesh Prefab' field.");
            return(false);
        }
        if (mom.meshCombiner.resultSceneObject != null &&
            (PrefabUtility.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.ModelPrefab ||
             PrefabUtility.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.Prefab))
        {
            Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field.");
            mom.meshCombiner.resultSceneObject = null;
        }

        mom.ClearMesh();
        if (mom.AddDeleteGameObjects(mom.GetObjectsToCombine().ToArray(), null, false))
        {
            mom.Apply(Unwrapping.GenerateSecondaryUVSet);
            Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count));
            if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoSceneObject)
            {
                PrefabType pt = PrefabUtility.GetPrefabType(mom.meshCombiner.resultSceneObject);
                if (pt == PrefabType.Prefab || pt == PrefabType.ModelPrefab)
                {
                    Debug.LogError("Combined Mesh Object is a prefab asset. If output option bakeIntoSceneObject then this must be an instance in the scene.");
                    return(false);
                }
            }
            else if (prefabOrSceneObject == MB2_OutputOptions.bakeIntoPrefab)
            {
                string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);
                if (prefabPth == null || prefabPth.Length == 0)
                {
                    Debug.LogError("Could not save result to prefab. Result Prefab value is not an Asset.");
                    return(false);
                }
                string baseName    = Path.GetFileNameWithoutExtension(prefabPth);
                string folderPath  = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 7);
                string newFilename = folderPath + baseName + "-mesh";
                SaveMeshsToAssetDatabase(mom, folderPath, newFilename);

                if (mom.meshCombiner.renderType == MB_RenderType.skinnedMeshRenderer)
                {
                    Debug.LogWarning("Render type is skinned mesh renderer. " +
                                     "Can't create prefab until all bones have been added to the combined mesh object " + mom.resultPrefab +
                                     " Add the bones then drag the combined mesh object to the prefab.");
                }
                else
                {
                    RebuildPrefab(mom);
                }
            }
            else
            {
                Debug.LogError("Unknown parameter");
                return(false);
            }
        }
        return(true);
    }
        //posibilities
        //  using fixOutOfBoundsUVs or not
        //
        public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result asset must be set before using this operation.");
                return;
            }
            Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shader2Material_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >();
            Dictionary <Material, Mesh> obUVobject2mesh_map = new Dictionary <Material, Mesh>();

            //validate that the objects to be combined are valid
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObject go = mom.GetObjectsToCombine()[i];
                if (go == null)
                {
                    Debug.LogError("Null object in list of objects to combine at position " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
                    return;
                }
            }

            //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
            if (mom.doMultiMaterialSplitAtlasesIfOBUVs)
            {
                for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
                {
                    GameObject go = mom.GetObjectsToCombine()[i];
                    Mesh       m  = MB_Utility.GetMesh(go);
                    MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult();
                    Renderer r = go.GetComponent <Renderer>();
                    for (int j = 0; j < r.sharedMaterials.Length; j++)
                    {
                        if (MB_Utility.hasOutOfBoundsUVs(m, ref dummyMar, j))
                        {
                            if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[j]))
                            {
                                Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. This object has been mapped to its own submesh in the combined mesh. It can share a submesh with other objects that use different materials if you use the fix out of bounds UVs feature which will bake the tiling");
                                obUVobject2mesh_map.Add(r.sharedMaterials[j], m);
                            }
                        }
                    }
                }
            }

            //second pass  put other materials without OB uvs in a shader to material map
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                Renderer r = mom.GetObjectsToCombine()[i].GetComponent <Renderer>();
                for (int j = 0; j < r.sharedMaterials.Length; j++)
                {
                    if (!obUVobject2mesh_map.ContainsKey(r.sharedMaterials[j]))
                    { //if not already added
                        if (r.sharedMaterials[j] == null)
                        {
                            continue;
                        }
                        List <List <Material> > binsOfMatsThatUseShader = null;
                        MultiMatSubmeshInfo     newKey = new MultiMatSubmeshInfo(r.sharedMaterials[j].shader, r.sharedMaterials[j]);
                        if (!shader2Material_map.TryGetValue(newKey, out binsOfMatsThatUseShader))
                        {
                            binsOfMatsThatUseShader = new List <List <Material> >();
                            binsOfMatsThatUseShader.Add(new List <Material>());
                            shader2Material_map.Add(newKey, binsOfMatsThatUseShader);
                        }
                        if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j]))
                        {
                            binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]);
                        }
                    }
                }
            }

            int numResMats = shader2Material_map.Count;

            //third pass for each shader grouping check how big the atlas would be and group into bins that would fit in an atlas
            if (mom.doMultiMaterialSplitAtlasesIfTooBig)
            {
                if (mom.packingAlgorithm == MB2_PackingAlgorithmEnum.UnitysPackTextures)
                {
                    Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split.");
                }
                else
                {
                    numResMats = 0;
                    foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys)
                    {
                        List <List <Material> > binsOfMatsThatUseShader = shader2Material_map[sh];
                        List <Material>         allMatsThatUserShader   = binsOfMatsThatUseShader[0];//at this point everything is in the same list
                        binsOfMatsThatUseShader.RemoveAt(0);
                        MB3_TextureCombiner combiner = mom.CreateAndConfigureTextureCombiner();
                        combiner.saveAtlasesAsAssets = false;
                        if (allMatsThatUserShader.Count > 1)
                        {
                            combiner.fixOutOfBoundsUVs = mom.fixOutOfBoundsUVs;
                        }
                        else
                        {
                            combiner.fixOutOfBoundsUVs = false;
                        }

                        // Do the texture pack
                        List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>();
                        Material tempMat = new Material(sh.shader);
                        combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, null, packingResults, true);
                        for (int i = 0; i < packingResults.Count; i++)
                        {
                            List <MatsAndGOs> matsData = (List <MatsAndGOs>)packingResults[i].data;
                            List <Material>   mats     = new List <Material>();
                            for (int j = 0; j < matsData.Count; j++)
                            {
                                for (int kk = 0; kk < matsData[j].mats.Count; kk++)
                                {
                                    if (!mats.Contains(matsData[j].mats[kk].mat))
                                    {
                                        mats.Add(matsData[j].mats[kk].mat);
                                    }
                                }
                            }
                            binsOfMatsThatUseShader.Add(mats);
                        }
                        numResMats += binsOfMatsThatUseShader.Count;
                    }
                }
            }

            //build the result materials
            if (shader2Material_map.Count == 0 && obUVobject2mesh_map.Count == 0)
            {
                Debug.LogError("Found no materials in list of objects to combine");
            }
            mom.resultMaterials = new MB_MultiMaterial[numResMats + obUVobject2mesh_map.Count];
            string pth        = AssetDatabase.GetAssetPath(mom.textureBakeResults);
            string baseName   = Path.GetFileNameWithoutExtension(pth);
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
            int    k          = 0;

            foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys)
            {
                foreach (List <Material> matsThatUse in shader2Material_map[sh])
                {
                    MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                    mm.sourceMaterials = matsThatUse;
                    if (mm.sourceMaterials.Count == 1)
                    {
                        mm.considerMeshUVs = false;
                    }
                    else
                    {
                        mm.considerMeshUVs = mom.fixOutOfBoundsUVs;
                    }
                    string   matName = folderPath + baseName + "-mat" + k + ".mat";
                    Material newMat  = new Material(Shader.Find("Diffuse"));
                    if (matsThatUse.Count > 0 && matsThatUse[0] != null)
                    {
                        MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
                    }
                    AssetDatabase.CreateAsset(newMat, matName);
                    mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                    k++;
                }
            }
            foreach (Material m in obUVobject2mesh_map.Keys)
            {
                MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m);
                mm.considerMeshUVs = false;
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
        }
        /* tried to see if the MultiMaterialConfig could be done using the GroupBy filters. Saddly it didn't work */
        public static void ConfigureMutiMaterialsFromObjsToCombine2(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker)
        {
            if (mom.GetObjectsToCombine().Count == 0)
            {
                Debug.LogError("You need to add some objects to combine before building the multi material list.");
                return;
            }
            if (resultMaterials.arraySize > 0)
            {
                Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
                return;
            }
            if (mom.textureBakeResults == null)
            {
                Debug.LogError("Texture Bake Result asset must be set before using this operation.");
                return;
            }

            //validate that the objects to be combined are valid
            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObject go = mom.GetObjectsToCombine()[i];
                if (go == null)
                {
                    Debug.LogError("Null object in list of objects to combine at position " + i);
                    return;
                }
                Renderer r = go.GetComponent <Renderer>();
                if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer)))
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
                    return;
                }
                if (r.sharedMaterial == null)
                {
                    Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
                    return;
                }
            }

            IGroupByFilter[] filters = new IGroupByFilter[3];
            filters[0] = new GroupByOutOfBoundsUVs();
            filters[1] = new GroupByShader();
            filters[2] = new MB3_GroupByStandardShaderType();

            List <GameObjectFilterInfo> gameObjects = new List <GameObjectFilterInfo>();
            HashSet <GameObject>        objectsAlreadyIncludedInBakers = new HashSet <GameObject>();

            for (int i = 0; i < mom.GetObjectsToCombine().Count; i++)
            {
                GameObjectFilterInfo goaw = new GameObjectFilterInfo(mom.GetObjectsToCombine()[i], objectsAlreadyIncludedInBakers, filters);
                if (goaw.materials.Length > 0) //don't consider renderers with no materials
                {
                    gameObjects.Add(goaw);
                }
            }

            //analyse meshes
            Dictionary <int, MB_Utility.MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MB_Utility.MeshAnalysisResult>();
            int totalVerts = 0;

            for (int i = 0; i < gameObjects.Count; i++)
            {
                //string rpt = String.Format("Processing {0} [{1} of {2}]", gameObjects[i].go.name, i, gameObjects.Count);
                //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " A", .6f);
                Mesh mm     = MB_Utility.GetMesh(gameObjects[i].go);
                int  nVerts = 0;
                if (mm != null)
                {
                    nVerts += mm.vertexCount;
                    MB_Utility.MeshAnalysisResult mar;
                    if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar))
                    {
                        //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f);
                        MB_Utility.hasOutOfBoundsUVs(mm, ref mar);
                        //Rect dummy = mar.uvRect;
                        MB_Utility.doSubmeshesShareVertsOrTris(mm, ref mar);
                        meshAnalysisResultCache.Add(mm.GetInstanceID(), mar);
                    }
                    if (mar.hasOutOfBoundsUVs)
                    {
                        int w = (int)mar.uvRect.width;
                        int h = (int)mar.uvRect.height;
                        gameObjects[i].outOfBoundsUVs = true;
                        gameObjects[i].warning       += " [WARNING: has uvs outside the range (0,1) tex is tiled " + w + "x" + h + " times]";
                    }
                    if (mar.hasOverlappingSubmeshVerts)
                    {
                        gameObjects[i].submeshesOverlap = true;
                        gameObjects[i].warning         += " [WARNING: Submeshes share verts or triangles. 'Multiple Combined Materials' feature may not work.]";
                    }
                }
                totalVerts += nVerts;
                //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Validate OBuvs Multi Material", .6f);
                Renderer mr = gameObjects[i].go.GetComponent <Renderer>();
                if (!MB_Utility.AreAllSharedMaterialsDistinct(mr.sharedMaterials))
                {
                    gameObjects[i].warning += " [WARNING: Object uses same material on multiple submeshes. This may produce poor results when used with multiple materials or fix out of bounds uvs.]";
                }
            }

            List <GameObjectFilterInfo> objsNotAddedToBaker = new List <GameObjectFilterInfo>();

            Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > > gs2bakeGroupMap = MB3_MeshBakerEditorWindow.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize);

            mom.resultMaterials = new MB_MultiMaterial[gs2bakeGroupMap.Keys.Count];
            string pth        = AssetDatabase.GetAssetPath(mom.textureBakeResults);
            string baseName   = Path.GetFileNameWithoutExtension(pth);
            string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6);
            int    k          = 0;

            foreach (GameObjectFilterInfo m in gs2bakeGroupMap.Keys)
            {
                MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
                mm.sourceMaterials = new List <Material>();
                mm.sourceMaterials.Add(m.materials[0]);
                string   matName = folderPath + baseName + "-mat" + k + ".mat";
                Material newMat  = new Material(Shader.Find("Diffuse"));
                MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]);
                AssetDatabase.CreateAsset(newMat, matName);
                mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
                k++;
            }
            MBVersionEditor.UpdateIfDirtyOrScript(textureBaker);
        }
		public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom, SerializedProperty resultMaterials, SerializedObject textureBaker){
			if (mom.GetObjectsToCombine().Count == 0){
				Debug.LogError("You need to add some objects to combine before building the multi material list.");
				return;
			}
			if (resultMaterials.arraySize > 0){
				Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation.");
				return;			
			}
			if (mom.textureBakeResults == null){
				Debug.LogError("Material Bake Result asset must be set before using this operation.");
				return;
			}
			Dictionary<Shader,List<Material>> shader2Material_map = new Dictionary<Shader, List<Material>>();
			Dictionary<Material,Mesh> obUVobject2material_map = new Dictionary<Material,Mesh>();
			
			//validate that the objects to be combined are valid
			for (int i = 0; i < mom.GetObjectsToCombine().Count; i++){
				GameObject go = mom.GetObjectsToCombine()[i];
				if (go == null) {
					Debug.LogError("Null object in list of objects to combine at position " + i);
					return;
				}
				Renderer r = go.GetComponent<Renderer>();
				if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer))){
					Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer");
					return;
				}
				if (r.sharedMaterial == null){
					Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material");
					return;						
				}			
			}
			
			//first pass put any meshes with obUVs on their own submesh if not fixing OB uvs
			if (!mom.fixOutOfBoundsUVs){
				for (int i = 0; i < mom.GetObjectsToCombine().Count; i++){
					GameObject go = mom.GetObjectsToCombine()[i];
					Mesh m = MB_Utility.GetMesh(go);
					Rect dummy = new Rect();
					MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult();
					Renderer r = go.GetComponent<Renderer>();	
					for (int j = 0; j < r.sharedMaterials.Length; j++){
						if (MB_Utility.hasOutOfBoundsUVs(m, ref dummy, ref dummyMar, j)){
							if (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j])){
								Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. This object has been mapped to its own submesh in the combined mesh. It can share a submesh with other objects that use different materials if you use the fix out of bounds UVs feature which will bake the tiling");
								obUVobject2material_map.Add(r.sharedMaterials[j],m);
							}
						}
					}
				}
			}
			
			//second pass  put other materials without OB uvs in a shader to material map
			for (int i = 0; i < mom.GetObjectsToCombine().Count; i++){
				Renderer r = mom.GetObjectsToCombine()[i].GetComponent<Renderer>();
				for (int j = 0; j < r.sharedMaterials.Length; j++){
					if (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j])) {
						if (r.sharedMaterials[j] == null) continue;
						List<Material> matsThatUseShader = null;
						if (!shader2Material_map.TryGetValue(r.sharedMaterials[j].shader, out matsThatUseShader)){
							matsThatUseShader = new List<Material>();
							shader2Material_map.Add(r.sharedMaterials[j].shader, matsThatUseShader);
						}
						if (!matsThatUseShader.Contains(r.sharedMaterials[j])) matsThatUseShader.Add(r.sharedMaterials[j]);
					}
				}			
			}
			
			if (shader2Material_map.Count == 0 && obUVobject2material_map.Count == 0) Debug.LogError("Found no materials in list of objects to combine");
			mom.resultMaterials = new MB_MultiMaterial[shader2Material_map.Count + obUVobject2material_map.Count];
			string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults);
			string baseName = Path.GetFileNameWithoutExtension(pth);
			string folderPath = pth.Substring(0,pth.Length - baseName.Length - 6);		
			int k = 0;
			foreach(Shader sh in shader2Material_map.Keys){ 
				List<Material> matsThatUse = shader2Material_map[sh];
				MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
				mm.sourceMaterials = matsThatUse;
				string matName = folderPath +  baseName + "-mat" + k + ".mat";
				Material newMat = new Material(Shader.Find("Diffuse"));
				if (matsThatUse.Count > 0 && matsThatUse[0] != null){
					MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]);
				}
				AssetDatabase.CreateAsset(newMat, matName);
				mm.combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matName,typeof(Material));
				k++;
			}
			foreach(Material m in obUVobject2material_map.Keys){
				MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial();
				mm.sourceMaterials = new List<Material>();
				mm.sourceMaterials.Add(m);
				string matName = folderPath +  baseName + "-mat" + k + ".mat";
				Material newMat = new Material(Shader.Find("Diffuse"));
				MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat,m);
				AssetDatabase.CreateAsset(newMat, matName);
				mm.combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matName,typeof(Material));
				k++;
			}
			textureBaker.UpdateIfDirtyOrScript();
		}
	public static void CreateCombinedMaterialAssets(MB3_TextureBaker target, string pth){
		MB3_TextureBaker mom = (MB3_TextureBaker) target;
		string baseName = Path.GetFileNameWithoutExtension(pth);
		if (baseName == null || baseName.Length == 0) return;
		string folderPath = pth.Substring(0,pth.Length - baseName.Length - 6);
		
		List<string> matNames = new List<string>();
		if (mom.doMultiMaterial){
			for (int i = 0; i < mom.resultMaterials.Length; i++){
				matNames.Add( folderPath +  baseName + "-mat" + i + ".mat" );
				AssetDatabase.CreateAsset(new Material(Shader.Find("Diffuse")), matNames[i]);
				mom.resultMaterials[i].combinedMaterial = (Material) AssetDatabase.LoadAssetAtPath(matNames[i],typeof(Material));
			}
		}else{
			matNames.Add( folderPath +  baseName + "-mat.mat" );
			Material newMat = null;
			if (mom.GetObjectsToCombine().Count > 0 && mom.GetObjectsToCombine()[0] != null){
				Renderer r = mom.GetObjectsToCombine()[0].GetComponent<Renderer>();
				if (r == null){
					Debug.LogWarning("Object " + mom.GetObjectsToCombine()[0] + " does not have a Renderer on it.");
				} else {
					if (r.sharedMaterial != null){
						newMat = new Material(r.sharedMaterial);
						//newMat.shader = r.sharedMaterial.shader;					
						MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat,r.sharedMaterial);
					}
				}
			} else {
				Debug.Log("If you add objects to be combined before creating the Combined Material Assets. Then Mesh Baker will create a result material that is a duplicate of the material on the first object to be combined. This saves time configuring the shader.");	
			}
			if (newMat == null){ 
				newMat = new Material(Shader.Find("Diffuse"));
			}
			AssetDatabase.CreateAsset(newMat, matNames[0]);
			mom.resultMaterial = (Material) AssetDatabase.LoadAssetAtPath(matNames[0],typeof(Material));
		}
		//create the MB2_TextureBakeResults
		AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<MB2_TextureBakeResults>(),pth);
		mom.textureBakeResults = (MB2_TextureBakeResults) AssetDatabase.LoadAssetAtPath(pth, typeof(MB2_TextureBakeResults));
		AssetDatabase.Refresh();
	}	
		public void DrawGUI(MB3_TextureBaker mom, System.Type editorWindow){
			if (textureBaker == null){
				_init(mom);
			}
			
			textureBaker.Update();
	
			showInstructions = EditorGUILayout.Foldout(showInstructions,"Instructions:");
			if (showInstructions){
				EditorGUILayout.HelpBox("1. Add scene objects or prefabs to combine. For best results these should use the same shader as result material.\n\n" +
										"2. Create Empty Assets For Combined Material(s)\n\n" +
										"3. Check that shader on result material(s) are correct.\n\n" +
										"4. Bake materials into combined material(s).\n\n" +
										"5. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
										"6. You are now ready to build combined meshs or adjust meshes to use the combined material(s).", UnityEditor.MessageType.None);
				
			}
			mom.LOG_LEVEL = (MB2_LogLevel) EditorGUILayout.EnumPopup("Log Level", mom.LOG_LEVEL);

	
			EditorGUILayout.Separator();		
			EditorGUILayout.LabelField("Objects To Be Combined",EditorStyles.boldLabel);	
			if (GUILayout.Button(openToolsWindowLabelContent)){
				MB3_MeshBakerEditorWindowInterface  mmWin = (MB3_MeshBakerEditorWindowInterface) EditorWindow.GetWindow(editorWindow);
				mmWin.target = (MB3_MeshBakerRoot) mom;
			}	
			EditorGUILayout.PropertyField(objsToMesh,objectsToCombineGUIContent, true);		
			
			EditorGUILayout.Separator();
			EditorGUILayout.LabelField("Output",EditorStyles.boldLabel);
			if (GUILayout.Button(createPrefabAndMaterialLabelContent)){
				string newPrefabPath = EditorUtility.SaveFilePanelInProject("Asset name", "", "asset", "Enter a name for the baked texture results");
				if (newPrefabPath != null){
					CreateCombinedMaterialAssets(mom, newPrefabPath);
				}
			}	
			EditorGUILayout.PropertyField(textureBakeResults, textureBakeResultsGUIContent);
			if (textureBakeResults.objectReferenceValue != null){
				showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained");
				if (showContainsReport){
					EditorGUILayout.HelpBox(((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info);	
				}
			}
			EditorGUILayout.PropertyField(doMultiMaterial,new GUIContent("Multiple Combined Materials"));		
			
			if (mom.doMultiMaterial){
				EditorGUILayout.LabelField("Source Material To Combined Mapping",EditorStyles.boldLabel);
				if (GUILayout.Button(configMultiMatFromObjsContent)){
					ConfigureMutiMaterialsFromObjsToCombine(mom,resultMaterials,textureBaker);	
				}
				EditorGUILayout.BeginHorizontal();
				resultMaterialsFoldout = EditorGUILayout.Foldout(resultMaterialsFoldout, combinedMaterialsGUIContent);
				
				if(GUILayout.Button(insertContent, EditorStyles.miniButtonLeft, buttonWidth)){
					if (resultMaterials.arraySize == 0){
						mom.resultMaterials = new MB_MultiMaterial[1];	
					} else {
						resultMaterials.InsertArrayElementAtIndex(resultMaterials.arraySize-1);
					}
				}
				if(GUILayout.Button(deleteContent, EditorStyles.miniButtonRight, buttonWidth)){
					resultMaterials.DeleteArrayElementAtIndex(resultMaterials.arraySize-1);
				}			
				EditorGUILayout.EndHorizontal();
				if (resultMaterialsFoldout){
					for(int i = 0; i < resultMaterials.arraySize; i++){
						EditorGUILayout.Separator();
						string s = "";
						if (i < mom.resultMaterials.Length && mom.resultMaterials[i] != null && mom.resultMaterials[i].combinedMaterial != null) s = mom.resultMaterials[i].combinedMaterial.shader.ToString();
						EditorGUILayout.BeginHorizontal();
						EditorGUILayout.LabelField("---------- submesh:" + i + " " + s,EditorStyles.boldLabel);
						if(GUILayout.Button(deleteContent, EditorStyles.miniButtonRight, buttonWidth)){
							resultMaterials.DeleteArrayElementAtIndex(i);
						}
						if (i < resultMaterials.arraySize){
							EditorGUILayout.EndHorizontal();
							EditorGUILayout.Separator();
							SerializedProperty resMat = resultMaterials.GetArrayElementAtIndex(i);
							EditorGUILayout.PropertyField(resMat.FindPropertyRelative("combinedMaterial"));
							SerializedProperty sourceMats = resMat.FindPropertyRelative("sourceMaterials");
							EditorGUILayout.PropertyField(sourceMats,true);
						}
					}
				}
				
			} else {			
				EditorGUILayout.PropertyField(resultMaterial,new GUIContent("Combined Mesh Material"));
			}				
			
			EditorGUILayout.Separator();
			EditorGUILayout.LabelField("Material Bake Options",EditorStyles.boldLabel);		
			EditorGUILayout.PropertyField(atlasPadding,new GUIContent("Atlas Padding"));
			EditorGUILayout.PropertyField(maxAtlasSize,maxAtlasSizeGUIContent);
			EditorGUILayout.PropertyField(resizePowerOfTwoTextures, resizePowerOfTwoGUIContent);
			EditorGUILayout.PropertyField(customShaderProperties,customShaderPropertyNamesGUIContent,true);
			EditorGUILayout.PropertyField(maxTilingBakeSize, maxTilingBakeSizeGUIContent);
			EditorGUILayout.PropertyField(fixOutOfBoundsUVs,fixOutOfBoundsGUIContent);
			if (texturePackingAlgorithm.intValue == (int) MB2_PackingAlgorithmEnum.UnitysPackTextures){
				EditorGUILayout.HelpBox("Unity's texture packer has memory problems and frequently crashes the editor.",MessageType.Warning);
			}
			EditorGUILayout.PropertyField(texturePackingAlgorithm, texturePackingAgorithmGUIContent);
			if (texturePackingAlgorithm.intValue == (int) MB2_PackingAlgorithmEnum.MeshBakerTexturePacker ||
			    texturePackingAlgorithm.intValue == (int) MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Fast){
				EditorGUILayout.PropertyField(forcePowerOfTwoAtlas,forcePowerOfTwoAtlasContent);
			}
			EditorGUILayout.Separator();				
			if (GUILayout.Button("Bake Materials Into Combined Material")){
				mom.CreateAtlases(updateProgressBar, true, new MB3_EditorMethods());
				EditorUtility.ClearProgressBar();
				if (mom.textureBakeResults != null) EditorUtility.SetDirty(mom.textureBakeResults);
			}
			textureBaker.ApplyModifiedProperties();		
			textureBaker.SetIsDifferentCacheDirty();
		}
	public void DoClustering(MB3_TextureBaker tb){
		if (clusterGrouper == null){
			Debug.LogError("Cluster Grouper was null.");
			return;
		}

		//todo warn for no objects and no material bake result
		Dictionary<string,List<Renderer>> cell2objs = clusterGrouper.FilterIntoGroups(tb.GetObjectsToCombine());
		
		Debug.Log ("Found " + cell2objs.Count + " cells with Renderers. Creating bakers.");
		if (clusterOnLMIndex){
			Dictionary<string,List<Renderer>> cell2objsNew = new Dictionary<string, List<Renderer>>();
			foreach (string key in cell2objs.Keys){
				List<Renderer> gaws = cell2objs[key];
				Dictionary<int,List<Renderer>> idx2objs = GroupByLightmapIndex(gaws);
				foreach(int keyIdx in idx2objs.Keys){
					string keyNew = key + "-LM-" + keyIdx;
					cell2objsNew.Add (keyNew,idx2objs[keyIdx]);
				}
			}
			cell2objs = cell2objsNew;
		}
		foreach (string key in cell2objs.Keys){
			List<Renderer> gaws = cell2objs[key];
			AddMeshBaker (tb,key,gaws);
		}
	}
	void AddMeshBaker(MB3_TextureBaker tb, string key, List<Renderer> gaws){
		int numVerts = 0;
		for (int i = 0; i < gaws.Count; i++){
			Mesh m = MB_Utility.GetMesh(gaws[i].gameObject);
			if (m != null)
				numVerts += m.vertexCount;
		}
		
		GameObject nmb = new GameObject("MeshBaker-" + key);
		nmb.transform.position = Vector3.zero;
		MB3_MeshBakerCommon newMeshBaker;
		if (numVerts >= 65535){
			newMeshBaker = nmb.AddComponent<MB3_MultiMeshBaker>();
			newMeshBaker.useObjsToMeshFromTexBaker = false;
		} else {
			newMeshBaker = nmb.AddComponent<MB3_MeshBaker>();
			newMeshBaker.useObjsToMeshFromTexBaker = false;
		}
		newMeshBaker.textureBakeResults = tb.textureBakeResults;
		newMeshBaker.transform.parent = tb.transform;
		for (int i = 0; i < gaws.Count; i++){
			newMeshBaker.GetObjectsToCombine().Add (gaws[i].gameObject);
		}
	}