public bool ValidateSkinnedMeshes(List <GameObject> objs)
        {
            for (int i = 0; i < objs.Count; i++)
            {
                Renderer r = MB_Utility.GetRenderer(objs[i]);
                if (r is SkinnedMeshRenderer)
                {
                    Transform[] bones = ((SkinnedMeshRenderer)r).bones;
                    if (bones.Length == 0)
                    {
                        Debug.LogWarning("SkinnedMesh " + i + " (" + objs[i] + ") in the list of objects to combine has no bones. Check that 'optimize game object' is not checked in the 'Rig' tab of the asset importer. Mesh Baker cannot combine optimized skinned meshes because the bones are not available.");
                    }
//					UnityEngine.Object parentObject = EditorUtility.GetPrefabParent(r.gameObject);
//					string path = AssetDatabase.GetAssetPath(parentObject);
//					Debug.Log (path);
//					AssetImporter ai = AssetImporter.GetAtPath( path );
//					Debug.Log ("bbb " + ai);
//					if (ai != null && ai is ModelImporter){
//						Debug.Log ("valing 2");
//						ModelImporter modelImporter = (ModelImporter) ai;
//						if(modelImporter.optimizeMesh){
//							Debug.LogError("SkinnedMesh " + i + " (" + objs[i] + ") in the list of objects to combine is optimized. Mesh Baker cannot combine optimized skinned meshes because the bones are not available.");
//						}
//					}
                }
            }
            return(true);
        }
Exemplo n.º 2
0
        public static bool GetBounds(GameObject go, out Bounds b)
        {
            if (go == null)
            {
                Debug.LogError("go paramater was null");
                b = new Bounds(Vector3.zero, Vector3.zero);
                return(false);
            }
            Renderer renderer = MB_Utility.GetRenderer(go);

            if (renderer == null)
            {
                Debug.LogError("GetBounds must be called on an object with a Renderer");
                b = new Bounds(Vector3.zero, Vector3.zero);
                return(false);
            }
            if (renderer is MeshRenderer)
            {
                b = renderer.bounds;
                return(true);
            }
            if (renderer is SkinnedMeshRenderer)
            {
                b = renderer.bounds;
                return(true);
            }
            Debug.LogError("GetBounds must be called on an object with a MeshRender or a SkinnedMeshRenderer.");
            b = new Bounds(Vector3.zero, Vector3.zero);
            return(false);
        }
Exemplo n.º 3
0
        static public Mesh BakeOneMesh(MB3_MeshCombinerSingle mom, string newMeshFilePath, GameObject objToBake)
        {
            Mesh outMesh = null;

            if (objToBake == null)
            {
                Debug.LogError("An object on the list of objects to combine is 'None'. Use Command-Delete on Mac OS X; Delete or Shift-Delete on Windows to remove this one element.");
                return(null);
            }

            MB3_EditorMethods editorMethods = new MB3_EditorMethods();

            GameObject[] objs = new GameObject[] { objToBake };
            Renderer     r    = MB_Utility.GetRenderer(objToBake);

            if (r is SkinnedMeshRenderer)
            {
                mom.renderType = MB_RenderType.skinnedMeshRenderer;
            }
            else if (r is MeshRenderer)
            {
                mom.renderType = MB_RenderType.meshRenderer;
            }
            else
            {
                Debug.LogError("Unsupported Renderer type on object. Must be SkinnedMesh or MeshFilter.");
                return(null);
            }
            if (newMeshFilePath == null && newMeshFilePath.Length != 0)              //todo check directory exists
            {
                Debug.LogError("File path was not in assets folder.");
                return(null);
            }
            if (mom.AddDeleteGameObjects(objs, null, false))
            {
                mom.Apply(MB3_MeshBakerEditorFunctions.UnwrapUV2);
                Mesh mf = MB_Utility.GetMesh(objToBake);
                if (mf != null)
                {
                    Debug.Log("Creating mesh for " + objToBake.name + " with adjusted UVs at: " + newMeshFilePath);
                    AssetDatabase.CreateAsset(mom.GetMesh(), newMeshFilePath);
                    outMesh = (Mesh)AssetDatabase.LoadAssetAtPath(newMeshFilePath, typeof(Mesh));
                }
            }
            mom.DestroyMeshEditor(editorMethods);
            return(outMesh);
        }
Exemplo n.º 4
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);
        }
        static public bool BakeOneMesh(MB3_MeshCombinerSingle mom, Mesh targMesh, GameObject objToBake)
        {
            if (objToBake == null)
            {
                Debug.LogError("An object on the list of objects to combine is 'None'. Use Command-Delete on Mac OS X; Delete or Shift-Delete on Windows to remove this one element.");
                return(false);
            }
            if (targMesh == null)
            {
                Debug.LogError("No mesh was provided.");
                return(false);
            }

            mom.SetMesh(targMesh);
            mom.ClearMesh();
            GameObject[] objs = new GameObject[] { objToBake };
            Renderer     r    = MB_Utility.GetRenderer(objToBake);

            if (r is SkinnedMeshRenderer)
            {
                mom.renderType = MB_RenderType.skinnedMeshRenderer;
            }
            else if (r is MeshRenderer)
            {
                mom.renderType = MB_RenderType.meshRenderer;
            }
            else
            {
                Debug.LogError("Unsupported Renderer type on object. Must be SkinnedMesh or MeshFilter.");
                return(false);
            }
            if (mom.AddDeleteGameObjects(objs, null, false))
            {
                mom.Apply(MB3_MeshBakerEditorFunctions.UnwrapUV2);
                Mesh mf = MB_Utility.GetMesh(objToBake);
                if (mf == null)
                {
                    Debug.LogError("Failed to create mesh for " + objToBake.name);
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 6
0
        public GameObjectFilterInfo(GameObject g, HashSet <GameObject> objsAlreadyInBakers, IGroupByFilter[] filts)
        {
            go = g;
            Renderer r = MB_Utility.GetRenderer(g);
            //material = r.sharedMaterial;
            //if (material != null) shader = material.shader;
            HashSet <Material> matsSet   = new HashSet <Material>();
            HashSet <Shader>   shaderSet = new HashSet <Shader>();

            if (r is SkinnedMeshRenderer)
            {
                isMeshRenderer = false;
            }
            else
            {
                isMeshRenderer = true;
            }
            materials = r.sharedMaterials;
            //shaders = new Shader[materials.Length];
            for (int i = 0; i < materials.Length; i++)
            {
                if (materials[i] != null)
                {
                    matsSet.Add(materials[i]);
                    shaderSet.Add(materials[i].shader);
                }
            }
            materials = new Material[matsSet.Count];
            matsSet.CopyTo(materials);
            shaders = new Shader[shaderSet.Count];
            standardShaderBlendModes = new StandardShaderBlendMode[matsSet.Count];

            shaderSet.CopyTo(shaders);

            Array.Sort(materials, new NameComparer());
            Array.Sort(shaders, new NameComparer());

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

            for (int i = 0; i < materials.Length; i++)
            {
                if (materials[i].shader.name.StartsWith("Standard") && materials[i].HasProperty("_Mode"))
                {
                    standardShaderBlendModes[i] = (StandardShaderBlendMode)materials[i].GetFloat("_Mode");
                }
                else
                {
                    standardShaderBlendModes[i] = StandardShaderBlendMode.NotApplicable;
                }
                if (!standardShaderBlendModesNameSet.Contains(standardShaderBlendModes[i].ToString()))
                {
                    standardShaderBlendModesNameSet.Add(standardShaderBlendModes[i].ToString());
                }
                materialName += (materials[i] == null ? "null" : materials[i].name);
                if (i < materials.Length - 1)
                {
                    materialName += ",";
                }
            }
            standardShaderBlendModesName = "";
            standardShaderBlendModesNameSet.Sort();
            foreach (string modeName in standardShaderBlendModesNameSet)
            {
                standardShaderBlendModesName += modeName + ",";
            }
            for (int i = 0; i < shaders.Length; i++)
            {
                shaderName += (shaders[i] == null ? "null" : shaders[i].name);
                if (i < shaders.Length - 1)
                {
                    shaderName += ",";
                }
            }

            lightmapIndex = r.lightmapIndex;
            Mesh mesh = MB_Utility.GetMesh(g);

            numVerts = 0;
            if (mesh != null)
            {
                numVerts = mesh.vertexCount;
            }
            isStatic           = go.isStatic;
            numMaterials       = materials.Length;
            warning            = "";
            alreadyInBakerList = objsAlreadyInBakers.Contains(g);
            outOfBoundsUVs     = false;
            submeshesOverlap   = false;
            filters            = filts;
        }
Exemplo n.º 7
0
        public void DrawGUI(MB3_MeshBakerCommon target, System.Type editorWindowType)
        {
            if (meshBaker == null)
            {
                _init(target);
            }

            meshBaker.Update();

            showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions:");
            if (showInstructions)
            {
                EditorGUILayout.HelpBox("1. Bake combined material(s).\n\n" +
                                        "2. If necessary set the 'Material Bake Results' field.\n\n" +
                                        "3. Add scene objects or prefabs to combine or check 'Same As Texture Baker'. For best results these should use the same shader as result material.\n\n" +
                                        "4. Select options and 'Bake'.\n\n" +
                                        "6. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
                                        "7. (optional) Disable renderers in source objects.", UnityEditor.MessageType.None);

                EditorGUILayout.Separator();
            }

            MB3_MeshBakerCommon mom = (MB3_MeshBakerCommon)target;

            mom.meshCombiner.LOG_LEVEL = (MB2_LogLevel)EditorGUILayout.EnumPopup("Log Level", mom.meshCombiner.LOG_LEVEL);

            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.LabelField("Objects To Be Combined", EditorStyles.boldLabel);
            if (mom.GetTextureBaker() != null)
            {
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, useTextureBakerObjsGUIContent);
            }
            else
            {
                useObjsToMeshFromTexBaker.boolValue = false;
                mom.useObjsToMeshFromTexBaker       = false;
                GUI.enabled = false;
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, useTextureBakerObjsGUIContent);
                GUI.enabled = true;
            }

            if (!mom.useObjsToMeshFromTexBaker)
            {
                if (GUILayout.Button(openToolsWindowLabelContent))
                {
                    MB3_MeshBakerEditorWindowInterface mmWin = (MB3_MeshBakerEditorWindowInterface)EditorWindow.GetWindow(editorWindowType);
                    mmWin.target = (MB3_MeshBakerRoot)target;
                }
                EditorGUILayout.PropertyField(objsToMesh, objectsToCombineGUIContent, true);
            }
            else
            {
                GUI.enabled = false;
                EditorGUILayout.PropertyField(objsToMesh, objectsToCombineGUIContent, true);
                GUI.enabled = true;
            }

            EditorGUILayout.LabelField("Output", EditorStyles.boldLabel);
            if (mom is MB3_MultiMeshBaker)
            {
                MB3_MultiMeshCombiner mmc = (MB3_MultiMeshCombiner)mom.meshCombiner;
                mmc.maxVertsInMesh = EditorGUILayout.IntField("Max Verts In Mesh", mmc.maxVertsInMesh);
            }

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doNorm, doNormGUIContent);
            EditorGUILayout.PropertyField(doTan, doTanGUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doUV, doUVGUIContent);
            EditorGUILayout.PropertyField(doUV1, doUV1GUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.PropertyField(doCol, doColGUIContent);

            if (mom.meshCombiner.lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
            {
                EditorGUILayout.HelpBox("Generating new lightmap UVs can split vertices which can push the number of vertices over the 64k limit.", MessageType.Warning);
            }
            EditorGUILayout.PropertyField(lightmappingOption, lightmappingOptionGUIContent);

            EditorGUILayout.PropertyField(outputOptions, outputOptoinsGUIContent);
            EditorGUILayout.PropertyField(renderType, renderTypeGUIContent);
            if (mom.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoSceneObject)
            {
                //todo switch to renderer
                mom.meshCombiner.resultSceneObject = (GameObject)EditorGUILayout.ObjectField("Combined Mesh Object", mom.meshCombiner.resultSceneObject, typeof(GameObject), true);
                if (mom is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    if (mesh.objectReferenceValue != null)
                    {
                        l += " (" + mesh.objectReferenceValue.GetInstanceID() + ")";
                    }
                    EditorGUILayout.PropertyField(mesh, new GUIContent(l));
                }
            }
            else if (mom.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoPrefab)
            {
                mom.resultPrefab = (GameObject)EditorGUILayout.ObjectField(combinedMeshPrefabGUIContent, mom.resultPrefab, typeof(GameObject), true);
                if (mom is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    if (mesh.objectReferenceValue != null)
                    {
                        l += " (" + mesh.objectReferenceValue.GetInstanceID() + ")";
                    }
                    EditorGUILayout.PropertyField(mesh, new GUIContent(l));
                }
            }
            else if (mom.meshCombiner.outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
            {
                EditorGUILayout.HelpBox("NEW! Try the BatchPrefabBaker component. It makes preparing a batch of prefabs for static/ dynamic batching much easier.", MessageType.Info);
                if (GUILayout.Button("Choose Folder For Bake In Place Meshes"))
                {
                    string newFolder = EditorUtility.SaveFolderPanel("Folder For Bake In Place Meshes", Application.dataPath, "");
                    if (!newFolder.Contains(Application.dataPath))
                    {
                        Debug.LogWarning("The chosen folder must be in your assets folder.");
                    }
                    mom.bakeAssetsInPlaceFolderPath = "Assets" + newFolder.Replace(Application.dataPath, "");
                }
                EditorGUILayout.LabelField("Folder For Meshes: " + mom.bakeAssetsInPlaceFolderPath);
            }

            EditorGUILayout.PropertyField(clearBuffersAfterBake, clearBuffersAfterBakeGUIContent);
            if (GUILayout.Button("Bake"))
            {
                bake(mom);
            }

            string enableRenderersLabel;
            bool   disableRendererInSource = false;

            if (mom.GetObjectsToCombine().Count > 0)
            {
                Renderer r = MB_Utility.GetRenderer(mom.GetObjectsToCombine()[0]);
                if (r != null && r.enabled)
                {
                    disableRendererInSource = true;
                }
            }
            if (disableRendererInSource)
            {
                enableRenderersLabel = "Disable Renderers On Source Objects";
            }
            else
            {
                enableRenderersLabel = "Enable Renderers On Source Objects";
            }
            if (GUILayout.Button(enableRenderersLabel))
            {
                mom.EnableDisableSourceObjectRenderers(!disableRendererInSource);
            }

            meshBaker.ApplyModifiedProperties();
            meshBaker.SetIsDifferentCacheDirty();
        }
Exemplo n.º 8
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();
            }
        }
Exemplo n.º 9
0
        public static Mesh BakeMeshesInPlace(MB2_MeshCombiner mom, List <GameObject> objsToMesh, string saveFolder, ProgressUpdateDelegate updateProgressBar)
        {
            if (MB2_MeshCombiner.EVAL_VERSION)
            {
                return(null);
            }

            Mesh mesh;

            if (!Directory.Exists(Application.dataPath + saveFolder.Substring(6, saveFolder.Length - 6)))
            {
                Debug.Log((Application.dataPath + saveFolder));
                Debug.Log(Path.GetFullPath(Application.dataPath + saveFolder));
                Debug.LogError("The selected Folder For Meshes does not exist or is not inside the projects Assets folder. Please 'Choose Folder For Bake In Place Meshes' that is inside the project's assets folder.");
                return(null);
            }

            MB2_EditorMethods editorMethods = new MB2_EditorMethods();

            mom.DestroyMeshEditor(editorMethods);

            GameObject[]  objs = new GameObject[1];
            MB_RenderType originalRenderType = mom.renderType;
            Mesh          outMesh            = null;

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                if (objsToMesh[i] == null)
                {
                    Debug.LogError("The " + i + "th object on the list of objects to combine is 'None'. Use Command-Delete on Mac OS X; Delete or Shift-Delete on Windows to remove this one element.");
                    return(null);
                }
                string[] objNames = GenerateNames(objsToMesh);
                objs[0] = objsToMesh[i];
                Renderer r = MB_Utility.GetRenderer(objsToMesh[i]);
                if (r is SkinnedMeshRenderer)
                {
                    mom.renderType = MB_RenderType.skinnedMeshRenderer;
                }
                else
                {
                    mom.renderType = MB_RenderType.meshRenderer;
                }
                mesh = mom.AddDeleteGameObjects(objs, null, false);
                if (mesh != null)
                {
                    mom.Apply();
                    Mesh mf = MB_Utility.GetMesh(objs[0]);
                    if (mf != null)
                    {
                        string newFilename = saveFolder + "/" + objNames[i];
                        if (updateProgressBar != null)
                        {
                            updateProgressBar("Created mesh saving mesh on " + objs[0].name + " to asset " + newFilename, .6f);
                        }
                        if (newFilename != null && newFilename.Length != 0)
                        {
                            Debug.Log("Creating mesh for " + objs[0].name + " with adjusted UVs at: " + newFilename);
                            AssetDatabase.CreateAsset(mesh, newFilename);
                            outMesh = (Mesh)AssetDatabase.LoadAssetAtPath(newFilename, typeof(Mesh));
                        }
                        else
                        {
                            Debug.LogWarning("Could not save mesh for " + objs[0].name);
                        }
                    }
                }
                mom.DestroyMeshEditor(editorMethods);
            }
            mom.renderType = originalRenderType;
            return(outMesh);
        }
Exemplo n.º 10
0
        public static void BakeMeshesInPlace(MB2_MeshCombiner mom, List <UnityEngine.GameObject> objsToMesh, ProgressUpdateDelegate updateProgressBar)
        {
#if UNITY_EDITOR
            Mesh mesh;

//		if (!MB_Utility.doCombinedValidate(mom, MB_ObjsToCombineTypes.prefabOnly)) return;

//		List<UnityEngine.GameObject> objsToMesh = mom.objsToMesh;
//		if (mom.useObjsToMeshFromTexBaker && mom.GetComponent<MB2_TextureBaker>() != null){
//			objsToMesh = mom.GetComponent<MB2_TextureBaker>().objsToMesh;
//		}

            mom.DestroyMesh();

            UnityEngine.GameObject[] objs               = new UnityEngine.GameObject[1];
            List <string>            usedNames          = new List <string>();
            MB_RenderType            originalRenderType = mom.renderType;
            for (int i = 0; i < objsToMesh.Count; i++)
            {
                if (objsToMesh[i] == null)
                {
                    Debug.LogError("The " + i + "th object on the list of objects to combine is 'None'. Use Command-Delete on Mac OS X; Delete or Shift-Delete on Windows to remove this one element.");
                    return;
                }
                objs[0] = objsToMesh[i];
                UnityEngine.Renderer r = MB_Utility.GetRenderer(objsToMesh[i]);
                if (r is SkinnedMeshRenderer)
                {
                    mom.renderType = MB_RenderType.skinnedMeshRenderer;
                }
                else
                {
                    mom.renderType = MB_RenderType.meshRenderer;
                }
                mesh = mom.AddDeleteGameObjects(objs, null, false);
                if (mesh != null)
                {
                    //mom.ApplyAll();
                    mom.Apply();
                    Mesh mf = MB_Utility.GetMesh(objs[0]);
                    if (mf != null)
                    {
                        string baseName, folderPath, newFilename;
                        string pth = AssetDatabase.GetAssetPath(mf);
                        if (pth != null && pth.Length != 0)
                        {
                            baseName   = Path.GetFileNameWithoutExtension(pth) + "_" + objs[0].name + "_MB";
                            folderPath = Path.GetDirectoryName(pth);
                        }
                        else                                           //try to get the name from prefab
                        {
                            pth = AssetDatabase.GetAssetPath(objs[0]); //get prefab name
                            if (pth != null && pth.Length != 0)
                            {
                                baseName   = Path.GetFileNameWithoutExtension(pth) + "_" + objs[0].name + "_MB";
                                folderPath = Path.GetDirectoryName(pth);
                            }
                            else                         //save in root
                            {
                                baseName   = objs[0].name + "mesh_MB";
                                folderPath = "Assets";
                            }
                        }
                        //make name unique
                        newFilename = Path.Combine(folderPath, baseName + ".asset");
                        int j = 0;
                        while (usedNames.Contains(newFilename))
                        {
                            newFilename = Path.Combine(folderPath, baseName + j + ".asset");
                            j++;
                        }
                        usedNames.Add(newFilename);
                        updateProgressBar("Created mesh saving mesh on " + objs[0].name + " to asset " + newFilename, .6f);
                        if (newFilename != null && newFilename.Length != 0)
                        {
                            Debug.Log("Creating mesh for " + objs[0].name + " with adjusted UVs at: " + newFilename);
                            AssetDatabase.CreateAsset(mesh, newFilename);
                        }
                        else
                        {
                            Debug.LogWarning("Could not save mesh for " + objs[0].name);
                        }
                    }
                }
                mom.DestroyMesh();
            }
            mom.renderType = originalRenderType;
#endif
        }
        public void DrawGUI(SerializedObject meshBaker, MB3_MeshBakerCommon target, System.Type editorWindowType)
        {
            if (meshBaker == null)
            {
                return;
            }
            meshBaker.Update();

            showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions:");
            if (showInstructions)
            {
                EditorGUILayout.HelpBox("1. Bake combined material(s).\n\n" +
                                        "2. If necessary set the 'Texture Bake Results' field.\n\n" +
                                        "3. Add scene objects or prefabs to combine or check 'Same As Texture Baker'. For best results these should use the same shader as result material.\n\n" +
                                        "4. Select options and 'Bake'.\n\n" +
                                        "6. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
                                        "7. (optional) Disable renderers in source objects.", UnityEditor.MessageType.None);

                EditorGUILayout.Separator();
            }

            MB3_MeshBakerCommon momm = (MB3_MeshBakerCommon)target;

            //mom.meshCombiner.LOG_LEVEL = (MB2_LogLevel) EditorGUILayout.EnumPopup("Log Level", mom.meshCombiner.LOG_LEVEL);
            EditorGUILayout.PropertyField(logLevel, gc_logLevelContent);

            EditorGUILayout.PropertyField(textureBakeResults, gc_textureBakeResultsGUIContent);
            if (textureBakeResults.objectReferenceValue != null)
            {
                showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained");
                if (showContainsReport)
                {
                    EditorGUILayout.HelpBox(((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info);
                }
            }

            EditorGUILayout.BeginVertical(editorBoxBackgroundStyle);
            EditorGUILayout.LabelField("Objects To Be Combined", EditorStyles.boldLabel);
            if (momm.GetTextureBaker() != null)
            {
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
            }
            else
            {
                useObjsToMeshFromTexBaker.boolValue = false;
                momm.useObjsToMeshFromTexBaker      = false;
                GUI.enabled = false;
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
                GUI.enabled = true;
            }

            if (!momm.useObjsToMeshFromTexBaker)
            {
                if (GUILayout.Button(gc_openToolsWindowLabelContent))
                {
                    MB3_MeshBakerEditorWindowInterface mmWin = (MB3_MeshBakerEditorWindowInterface)EditorWindow.GetWindow(editorWindowType);
                    mmWin.target = (MB3_MeshBakerRoot)target;
                }
                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                EditorGUILayout.Separator();
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Select Objects In Scene"))
                {
                    Selection.objects = momm.GetObjectsToCombine().ToArray();
                    if (momm.GetObjectsToCombine().Count > 0)
                    {
                        SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position;
                    }
                }
                if (GUILayout.Button(gc_SortAlongAxis))
                {
                    MB3_MeshBakerRoot.ZSortObjects sorter = new MB3_MeshBakerRoot.ZSortObjects();
                    sorter.sortAxis = sortOrderAxis.vector3Value;
                    sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine());
                }
                EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none);
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                GUI.enabled = false;
                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                GUI.enabled = true;
            }
            EditorGUILayout.EndVertical();

            EditorGUILayout.LabelField("Output", EditorStyles.boldLabel);
            if (momm is MB3_MultiMeshBaker)
            {
                MB3_MultiMeshCombiner mmc = (MB3_MultiMeshCombiner)momm.meshCombiner;
                mmc.maxVertsInMesh = EditorGUILayout.IntField("Max Verts In Mesh", mmc.maxVertsInMesh);
            }

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doNorm, gc_doNormGUIContent);
            EditorGUILayout.PropertyField(doTan, gc_doTanGUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doUV, gc_doUVGUIContent);
            EditorGUILayout.PropertyField(doUV3, gc_doUV3GUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(doUV4, gc_doUV4GUIContent);
            EditorGUILayout.PropertyField(doCol, gc_doColGUIContent);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.PropertyField(doBlendShapes, gc_doBlendShapeGUIContent);

            if (momm.meshCombiner.lightmapOption == MB2_LightmapOptions.preserve_current_lightmapping)
            {
                if (MBVersion.GetMajorVersion() == 5)
                {
                    EditorGUILayout.HelpBox("The best choice for Unity 5 is to Ignore_UV2 or Generate_New_UV2 layout. Unity's baked GI will create the UV2 layout it wants. See manual for more information.", MessageType.Warning);
                }
            }
            if (momm.meshCombiner.lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
            {
                EditorGUILayout.HelpBox("Generating new lightmap UVs can split vertices which can push the number of vertices over the 64k limit.", MessageType.Warning);
            }
            EditorGUILayout.PropertyField(lightmappingOption, gc_lightmappingOptionGUIContent);
            if (momm.meshCombiner.lightmapOption == MB2_LightmapOptions.generate_new_UV2_layout)
            {
                EditorGUILayout.PropertyField(uv2OutputParamsHardAngle, gc_uv2HardAngleGUIContent);
                EditorGUILayout.PropertyField(uv2OutputParamsPackingMargin, gc_uv2PackingMarginUV3GUIContent);
                EditorGUILayout.Separator();
            }

            EditorGUILayout.PropertyField(outputOptions, gc_outputOptoinsGUIContent);
            EditorGUILayout.PropertyField(renderType, gc_renderTypeGUIContent);
            if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoSceneObject)
            {
                //todo switch to renderer
                momm.meshCombiner.resultSceneObject = (GameObject)EditorGUILayout.ObjectField("Combined Mesh Object", momm.meshCombiner.resultSceneObject, typeof(GameObject), true);
                if (momm is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    if (mesh.objectReferenceValue != null)
                    {
                        l += " (" + mesh.objectReferenceValue.GetInstanceID() + ")";
                    }
                    EditorGUILayout.PropertyField(mesh, new GUIContent(l));
                }
            }
            else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoPrefab)
            {
                momm.resultPrefab = (GameObject)EditorGUILayout.ObjectField(gc_combinedMeshPrefabGUIContent, momm.resultPrefab, typeof(GameObject), true);
                if (momm is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    if (mesh.objectReferenceValue != null)
                    {
                        l += " (" + mesh.objectReferenceValue.GetInstanceID() + ")";
                    }
                    EditorGUILayout.PropertyField(mesh, new GUIContent(l));
                }
            }
            else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
            {
                EditorGUILayout.HelpBox("NEW! Try the BatchPrefabBaker component. It makes preparing a batch of prefabs for static/ dynamic batching much easier.", MessageType.Info);
                if (GUILayout.Button("Choose Folder For Bake In Place Meshes"))
                {
                    string newFolder = EditorUtility.SaveFolderPanel("Folder For Bake In Place Meshes", Application.dataPath, "");
                    if (!newFolder.Contains(Application.dataPath))
                    {
                        Debug.LogWarning("The chosen folder must be in your assets folder.");
                    }
                    momm.bakeAssetsInPlaceFolderPath = "Assets" + newFolder.Replace(Application.dataPath, "");
                }
                EditorGUILayout.LabelField("Folder For Meshes: " + momm.bakeAssetsInPlaceFolderPath);
            }

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(clearBuffersAfterBake, gc_clearBuffersAfterBakeGUIContent);
            EditorGUILayout.PropertyField(centerMeshToBoundsCenter, gc_CenterMeshToBoundsCenter);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.PropertyField(optimizeAfterBake, gc_OptimizeAfterBake);
            Color oldColor = GUI.backgroundColor;

            GUI.backgroundColor = buttonColor;
            if (GUILayout.Button("Bake"))
            {
                bake(momm);
            }
            GUI.backgroundColor = oldColor;

            string enableRenderersLabel;
            bool   disableRendererInSource = false;

            if (momm.GetObjectsToCombine().Count > 0)
            {
                Renderer r = MB_Utility.GetRenderer(momm.GetObjectsToCombine()[0]);
                if (r != null && r.enabled)
                {
                    disableRendererInSource = true;
                }
            }
            if (disableRendererInSource)
            {
                enableRenderersLabel = "Disable Renderers On Source Objects";
            }
            else
            {
                enableRenderersLabel = "Enable Renderers On Source Objects";
            }
            if (GUILayout.Button(enableRenderersLabel))
            {
                momm.EnableDisableSourceObjectRenderers(!disableRendererInSource);
            }

            meshBaker.ApplyModifiedProperties();
            meshBaker.SetIsDifferentCacheDirty();
        }
Exemplo n.º 12
0
        public void DrawGUI(SerializedObject meshBaker, MB3_MeshBakerCommon target, System.Type editorWindowType)
        {
            if (meshBaker == null)
            {
                return;
            }

            meshBaker.Update();

            showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions:");
            if (showInstructions)
            {
                EditorGUILayout.HelpBox("1. Bake combined material(s).\n\n" +
                                        "2. If necessary set the 'Texture Bake Results' field.\n\n" +
                                        "3. Add scene objects or prefabs to combine or check 'Same As Texture Baker'. For best results these should use the same shader as result material.\n\n" +
                                        "4. Select options and 'Bake'.\n\n" +
                                        "6. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
                                        "7. (optional) Disable renderers in source objects.", UnityEditor.MessageType.None);

                EditorGUILayout.Separator();
            }

            MB3_MeshBakerCommon momm = (MB3_MeshBakerCommon)target;

            EditorGUILayout.PropertyField(logLevel, gc_logLevelContent);
            EditorGUILayout.PropertyField(textureBakeResults, gc_textureBakeResultsGUIContent);
            if (textureBakeResults.objectReferenceValue != null)
            {
                showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained");
                if (showContainsReport)
                {
                    EditorGUILayout.HelpBox(((MB2_TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info);
                }
            }

            EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle);
            EditorGUILayout.LabelField("Objects To Be Combined", EditorStyles.boldLabel);
            if (momm.GetTextureBaker() != null)
            {
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
            }
            else
            {
                useObjsToMeshFromTexBaker.boolValue = false;
                momm.useObjsToMeshFromTexBaker      = false;
                GUI.enabled = false;
                EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent);
                GUI.enabled = true;
            }

            if (!momm.useObjsToMeshFromTexBaker)
            {
                if (GUILayout.Button(gc_openToolsWindowLabelContent))
                {
                    MB3_MeshBakerEditorWindowInterface mmWin = (MB3_MeshBakerEditorWindowInterface)EditorWindow.GetWindow(editorWindowType);
                    mmWin.target = (MB3_MeshBakerRoot)target;
                }

                object[] objs = MB3_EditorMethods.DropZone("Drag & Drop Renderers Or Parents Here To Add Objects To Be Combined", 300, 50);
                MB3_EditorMethods.AddDroppedObjects(objs, momm);

                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                EditorGUILayout.Separator();
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Select Objects In Scene"))
                {
                    Selection.objects = momm.GetObjectsToCombine().ToArray();
                    if (momm.GetObjectsToCombine().Count > 0)
                    {
                        SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position;
                    }
                }
                if (GUILayout.Button(gc_SortAlongAxis))
                {
                    MB3_MeshBakerRoot.ZSortObjects sorter = new MB3_MeshBakerRoot.ZSortObjects();
                    sorter.sortAxis = sortOrderAxis.vector3Value;
                    sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine());
                }
                EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none);
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                GUI.enabled = false;
                EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true);
                GUI.enabled = true;
            }
            EditorGUILayout.EndVertical();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Output", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(outputOptions, gc_outputOptoinsGUIContent);
            if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoSceneObject)
            {
                //todo switch to renderer
                momm.meshCombiner.resultSceneObject = (GameObject)EditorGUILayout.ObjectField("Combined Mesh Object", momm.meshCombiner.resultSceneObject, typeof(GameObject), true);
                if (momm is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    Mesh   m = (Mesh)mesh.objectReferenceValue;
                    if (m != null)
                    {
                        l += " (" + m.GetInstanceID() + ")";
                    }
                    Mesh nm = (Mesh)EditorGUILayout.ObjectField(new GUIContent(l), m, typeof(Mesh), true);
                    if (nm != m)
                    {
                        Undo.RecordObject(momm, "Assign Mesh");
                        ((MB3_MeshCombinerSingle)momm.meshCombiner).SetMesh(nm);
                        mesh.objectReferenceValue = nm;
                    }
                }
            }
            else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeIntoPrefab)
            {
                momm.resultPrefab = (GameObject)EditorGUILayout.ObjectField(gc_combinedMeshPrefabGUIContent, momm.resultPrefab, typeof(GameObject), true);
                if (momm is MB3_MeshBaker)
                {
                    string l = "Mesh";
                    Mesh   m = (Mesh)mesh.objectReferenceValue;
                    if (m != null)
                    {
                        l += " (" + m.GetInstanceID() + ")";
                    }
                    Mesh nm = (Mesh)EditorGUILayout.ObjectField(new GUIContent(l), m, typeof(Mesh), true);
                    if (nm != m)
                    {
                        Undo.RecordObject(momm, "Assign Mesh");
                        ((MB3_MeshCombinerSingle)momm.meshCombiner).SetMesh(nm);
                        mesh.objectReferenceValue = nm;
                    }
                }
            }
            else if (momm.meshCombiner.outputOption == MB2_OutputOptions.bakeMeshAssetsInPlace)
            {
                EditorGUILayout.HelpBox("NEW! Try the BatchPrefabBaker component. It makes preparing a batch of prefabs for static/ dynamic batching much easier.", MessageType.Info);
                if (GUILayout.Button("Choose Folder For Bake In Place Meshes"))
                {
                    string newFolder = EditorUtility.SaveFolderPanel("Folder For Bake In Place Meshes", Application.dataPath, "");
                    if (!newFolder.Contains(Application.dataPath))
                    {
                        Debug.LogWarning("The chosen folder must be in your assets folder.");
                    }
                    momm.bakeAssetsInPlaceFolderPath = "Assets" + newFolder.Replace(Application.dataPath, "");
                }
                EditorGUILayout.LabelField("Folder For Meshes: " + momm.bakeAssetsInPlaceFolderPath);
            }

            if (momm is MB3_MultiMeshBaker)
            {
                MB3_MultiMeshCombiner mmc = (MB3_MultiMeshCombiner)momm.meshCombiner;
                mmc.maxVertsInMesh = EditorGUILayout.IntField("Max Verts In Mesh", mmc.maxVertsInMesh);
            }

            //-----------------------------------
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
            bool settingsEnabled = true;

            //------------- Mesh Baker Settings is a bit tricky because it is an interface.



            EditorGUILayout.Space();
            UnityEngine.Object obj = settingsHolder.objectReferenceValue;

            // Don't use a PropertyField because we may not be able to use the assigned object. It may not implement requried interface.
            obj = EditorGUILayout.ObjectField(gc_Settings, obj, typeof(UnityEngine.Object), true);

            if (obj == null)
            {
                settingsEnabled = true;
                settingsHolder.objectReferenceValue = null;
                if (meshBakerSettingsExternal != null)
                {
                    meshBakerSettingsExternal.OnDisable();
                    meshBakerSettingsExternal = null;
                }
            }

            else if (obj is GameObject)
            {
                // Check to see if there is a component on this game object that implements MB_IMeshBakerSettingsHolder
                MB_IMeshBakerSettingsHolder itf = (MB_IMeshBakerSettingsHolder)((GameObject)obj).GetComponent(typeof(MB_IMeshBakerSettingsHolder));
                if (itf != null)
                {
                    settingsEnabled = false;
                    Component settingsHolderComponent = (Component)itf;
                    if (settingsHolder.objectReferenceValue != settingsHolderComponent)
                    {
                        settingsHolder.objectReferenceValue = settingsHolderComponent;
                        meshBakerSettingsExternal           = new MB_MeshBakerSettingsEditor();
                        meshBakerSettingsExternal.OnEnable(itf.GetMeshBakerSettingsAsSerializedProperty());
                    }
                }
                else
                {
                    settingsEnabled = true;
                    settingsHolder  = null;
                    if (meshBakerSettingsExternal != null)
                    {
                        meshBakerSettingsExternal.OnDisable();
                        meshBakerSettingsExternal = null;
                    }
                }
            }
            else if (obj is MB_IMeshBakerSettingsHolder)
            {
                settingsEnabled = false;
                if (settingsHolder.objectReferenceValue != obj)
                {
                    settingsHolder.objectReferenceValue = obj;
                    meshBakerSettingsExternal           = new MB_MeshBakerSettingsEditor();
                    meshBakerSettingsExternal.OnEnable(((MB_IMeshBakerSettingsHolder)obj).GetMeshBakerSettingsAsSerializedProperty());
                }
            }
            else
            {
                Debug.LogError("Object was not a Mesh Baker Settings object.");
            }
            EditorGUILayout.Space();

            if (settingsHolder.objectReferenceValue == null)
            {
                // Use the meshCombiner settings
                meshBakerSettingsThis.DrawGUI(momm.meshCombiner, settingsEnabled);
            }
            else
            {
                if (meshBakerSettingsExternal == null)
                {
                    meshBakerSettingsExternal = new MB_MeshBakerSettingsEditor();
                    meshBakerSettingsExternal.OnEnable(((MB_IMeshBakerSettingsHolder)obj).GetMeshBakerSettingsAsSerializedProperty());
                }
                meshBakerSettingsExternal.DrawGUI(((MB_IMeshBakerSettingsHolder)settingsHolder.objectReferenceValue).GetMeshBakerSettings(), settingsEnabled);
            }

            Color oldColor = GUI.backgroundColor;

            GUI.backgroundColor = buttonColor;
            if (GUILayout.Button("Bake"))
            {
                bake(momm);
            }
            GUI.backgroundColor = oldColor;

            string enableRenderersLabel;
            bool   disableRendererInSource = false;

            if (momm.GetObjectsToCombine().Count > 0)
            {
                Renderer r = MB_Utility.GetRenderer(momm.GetObjectsToCombine()[0]);
                if (r != null && r.enabled)
                {
                    disableRendererInSource = true;
                }
            }
            if (disableRendererInSource)
            {
                enableRenderersLabel = "Disable Renderers On Source Objects";
            }
            else
            {
                enableRenderersLabel = "Enable Renderers On Source Objects";
            }
            if (GUILayout.Button(enableRenderersLabel))
            {
                momm.EnableDisableSourceObjectRenderers(!disableRendererInSource);
            }

            meshBaker.ApplyModifiedProperties();
            meshBaker.SetIsDifferentCacheDirty();
        }
Exemplo n.º 13
0
        public GameObjectFilterInfo(GameObject g, HashSet <GameObject> objsAlreadyInBakers)
        {
            go = g;
            Renderer r = MB_Utility.GetRenderer(g);
            //material = r.sharedMaterial;
            //if (material != null) shader = material.shader;
            HashSet <Material> matsSet   = new HashSet <Material>();
            HashSet <Shader>   shaderSet = new HashSet <Shader>();

            if (r is SkinnedMeshRenderer)
            {
                isMeshRenderer = false;
            }
            else
            {
                isMeshRenderer = true;
            }
            materials = r.sharedMaterials;
            //shaders = new Shader[materials.Length];
            for (int i = 0; i < materials.Length; i++)
            {
                if (materials[i] != null)
                {
                    matsSet.Add(materials[i]);
                    shaderSet.Add(materials[i].shader);
                }
            }
            materials = new Material[matsSet.Count];
            matsSet.CopyTo(materials);
            shaders = new Shader[shaderSet.Count];
            shaderSet.CopyTo(shaders);

            Array.Sort(materials, new NameComparer());
            Array.Sort(shaders, new NameComparer());

            for (int i = 0; i < materials.Length; i++)
            {
                materialName += (materials[i] == null ? "null" : materials[i].name);
                if (i < materials.Length - 1)
                {
                    materialName += ",";
                }
            }
            for (int i = 0; i < shaders.Length; i++)
            {
                shaderName += (shaders[i] == null ? "null" : shaders[i].name);
                if (i < shaders.Length - 1)
                {
                    shaderName += ",";
                }
            }

            lightmapIndex = r.lightmapIndex;
            Mesh mesh = MB_Utility.GetMesh(g);

            numVerts = 0;
            if (mesh != null)
            {
                numVerts = mesh.vertexCount;
            }
            isStatic           = go.isStatic;
            numMaterials       = materials.Length;
            warning            = "";
            alreadyInBakerList = objsAlreadyInBakers.Contains(g);
            outOfBoundsUVs     = false;
            submeshesOverlap   = false;
        }
            public bool CollectBonesToAddForDGO(MB_DynamicGameObject dgo, Renderer r, bool noExtraBonesForMeshRenderers, MeshChannelsCache meshChannelCache)
            {
                bool success = true;

                Debug.Assert(_didSetup, "Need to setup first.");
                Debug.Assert(combiner.settings.renderType == MB_RenderType.skinnedMeshRenderer);
                // We could be working with adding and deleting smr body parts from the same rig. Different smrs will share
                // the same bones.

                //cache the bone data that we will be adding.
                Matrix4x4[]  dgoBindPoses   = dgo._tmpSMR_CachedBindposes = meshChannelCache.GetBindposes(r, out dgo.isSkinnedMeshWithBones);
                BoneWeight[] dgoBoneWeights = dgo._tmpSMR_CachedBoneWeights = meshChannelCache.GetBoneWeights(r, dgo.numVerts, dgo.isSkinnedMeshWithBones);
                Transform[]  dgoBones       = dgo._tmpSMR_CachedBones = combiner._getBones(r, dgo.isSkinnedMeshWithBones);


                for (int i = 0; i < dgoBones.Length; i++)
                {
                    if (dgoBones[i] == null)
                    {
                        Debug.LogError("Source mesh r had a 'null' bone. Bones must not be null: " + r);
                        success = false;
                    }
                }

                if (!success)
                {
                    return(success);
                }

                if (noExtraBonesForMeshRenderers)
                {
                    if (MB_Utility.GetRenderer(dgo.gameObject) is MeshRenderer)
                    {
                        // We are visiting a single dgo which is a MeshRenderer.
                        // It may be the child decendant of a bone in another skinned mesh that is being baked or is already in the combined mesh. We need to find that bone if it exists.
                        // We need to check our parent ancestors and search the bone lists of the other dgos being added or previously baked looking for bones that may have been added
                        Debug.Assert(dgoBones.Length == 1 && dgoBindPoses.Length == 1);
                        //     find and cache the parent bone for this MeshRenderer (it may not be the transform.parent)
                        bool            foundBoneParent = false;
                        BoneAndBindpose boneParent      = new BoneAndBindpose();
                        {
                            Transform t = dgo.gameObject.transform.parent;
                            while (t != null)
                            {
                                // Look for parent peviously baked in the combined mesh.
                                foreach (BoneAndBindpose b in boneAndBindPose2idx.Keys)
                                {
                                    if (b.bone == t)
                                    {
                                        boneParent      = b;
                                        foundBoneParent = true;
                                        break;
                                    }
                                }

                                // Look for parent in something we are adding.
                                foreach (BoneAndBindpose b in bonesToAdd)
                                {
                                    if (b.bone == t)
                                    {
                                        boneParent      = b;
                                        foundBoneParent = true;
                                        break;
                                    }
                                }

                                if (foundBoneParent)
                                {
                                    break;
                                }
                                else
                                {
                                    t = t.parent;
                                }
                            }
                        }

                        if (foundBoneParent)
                        {
                            dgoBones[0]     = boneParent.bone;
                            dgoBindPoses[0] = boneParent.bindPose;
                        }
                    }
                }

                // The mesh being added may not use all bones on the rig. Find the bones actually used.
                int[] usedBoneIdx2srcMeshBoneIdx;
                {
                    /*
                     * HashSet<int> usedBones = new HashSet<int>();
                     * for (int j = 0; j < dgoBoneWeights.Length; j++)
                     * {
                     *  usedBones.Add(dgoBoneWeights[j].boneIndex0);
                     *  usedBones.Add(dgoBoneWeights[j].boneIndex1);
                     *  usedBones.Add(dgoBoneWeights[j].boneIndex2);
                     *  usedBones.Add(dgoBoneWeights[j].boneIndex3);
                     * }
                     *
                     * usedBoneIdx2srcMeshBoneIdx = new int[usedBones.Count];
                     * usedBones.CopyTo(usedBoneIdx2srcMeshBoneIdx);
                     */
                }

                {
                    usedBoneIdx2srcMeshBoneIdx = new int[dgoBones.Length];
                    for (int i = 0; i < usedBoneIdx2srcMeshBoneIdx.Length; i++)
                    {
                        usedBoneIdx2srcMeshBoneIdx[i] = i;
                    }
                }

                // For each bone see if it exists in the bones array (with the same bindpose.).
                // We might be baking several skinned meshes on the same rig. We don't want duplicate bones in the bones array.
                for (int i = 0; i < dgoBones.Length; i++)
                {
                    bool            foundInBonesList = false;
                    int             bidx;
                    int             dgoBoneIdx = usedBoneIdx2srcMeshBoneIdx[i];
                    BoneAndBindpose bb         = new BoneAndBindpose(dgoBones[dgoBoneIdx], dgoBindPoses[dgoBoneIdx]);
                    if (boneAndBindPose2idx.TryGetValue(bb, out bidx))
                    {
                        if (dgoBones[dgoBoneIdx] == combiner.bones[bidx] &&
                            !boneIdxsToDelete.Contains(bidx) &&
                            dgoBindPoses[dgoBoneIdx] == combiner.bindPoses[bidx])
                        {
                            foundInBonesList = true;
                        }
                    }

                    if (!foundInBonesList)
                    {
                        if (!bonesToAdd.Contains(bb))
                        {
                            bonesToAdd.Add(bb);
                        }
                    }
                }

                dgo._tmpSMRIndexesOfSourceBonesUsed = usedBoneIdx2srcMeshBoneIdx;
                return(success);
            }